diff --git a/backing-services/aws-ebs-csi-driver/.helmignore b/backing-services/aws-ebs-csi-driver/.helmignore new file mode 100644 index 0000000..50af031 --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/.helmignore @@ -0,0 +1,22 @@ +# 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 +.vscode/ diff --git a/backing-services/aws-ebs-csi-driver/CHANGELOG.md b/backing-services/aws-ebs-csi-driver/CHANGELOG.md new file mode 100644 index 0000000..b87ed65 --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/CHANGELOG.md @@ -0,0 +1,382 @@ +# Helm chart +## v2.32.0 +* Bump driver version to `v1.32.0` +* Bump CSI sidecar container versions +* Add `patch` permission to `PV` to `external-provisioner` role (required by v5 and later) +* Add terminationGracePeriodSeconds as a helm parameter ([#2060](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/2060), [@ElijahQuinones](https://github.com/ElijahQuinones)) +* Use release namespace in ClusterRoleBinding subject namespace ([#2059](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/2059), [@etutuit](https://github.com/etutuit)) +* Add parameter to override node DaemonSet namespace ([#2052](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/2052), [@RuStyC0der](https://github.com/RuStyC0der)) +* Set RuntimeDefault as default seccompProfile in securityContext ([#2061](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/2061), [@torredil](https://github.com/torredil)) +* Increase default provisioner, resizer, snapshotter `retry-interval-max` ([#2057](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/2057), [@AndrewSirenko](https://github.com/AndrewSirenko)) + +## v2.31.0 +* Bump driver version to `v1.31.0` +* Expose dnsConfig in Helm Chart for Custom DNS Configuration ([#2034](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/2045), [@omerap12](https://github.com/omerap12)) +* Make scrape interval configurable ([#2035](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/2035), [@omerap12](https://github.com/omerap12)) +* Add defaultStorageClass parameter ([#2039](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/2039), [@torredil](https://github.com/torredil)) +* Upgrade sidecar containers ([#2041](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/2041), [@torredil](https://github.com/torredil)) + +## v2.30.0 +* Bump driver version to `v1.30.0` +* Update voluemessnapshotcontents/status RBAC ([#1991](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1991), [@AndrewSirenko](https://github.com/AndrewSirenko)) +* Upgrade dependencies ([#2016](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/2016), [@torredil](https://github.com/torredil)) + +## v2.29.1 +* Bump driver version to `v1.29.1` +* Remove `--reuse-values` deprecation warning + +## v2.29.0 +### Urgent Upgrade Notes +*(No, really, you MUST read this before you upgrade)* + +The EBS CSI Driver Helm chart no longer supports upgrading with `--reuse-values`. This chart will not test for `--reuse-values` compatibility and upgrading with `--reuse-values` will likely fail. Users of `--reuse-values` are strongly encouraged to migrate to `--reset-then-reuse-values`. + +For more information see [the deprecation announcement](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/issues/1864). + +### Other Changes +* Bump driver version to `v1.29.0` and sidecars to latest versions +* Add helm-tester enabled flag ([#1954](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1954), [@nunodomingues-td](https://github.com/nunodomingues-td)) + +## v2.28.1 +* Add `reservedVolumeAttachments` that overrides heuristic-determined reserved attachments via `--reserved-volume-attachments` CLI option from [PR #1919](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1919) through Helm ([#1939](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1939), [@AndrewSirenko](https://github.com/AndrewSirenko)) +* Add `additionalArgs` parameter to node daemonSet ([#1939](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1939), [@AndrewSirenko](https://github.com/AndrewSirenko)) + +## v2.28.0 +### Urgent Upgrade Notes +*(No, really, you MUST read this before you upgrade)* + +This is the last minor version of the EBS CSI Driver Helm chart to support upgrading with `--reuse-values`. Future versions of the chart (starting with `v2.29.0`) will not test for `--reuse-values` compatibility and upgrading with `--reuse-values` will likely fail. Users of `--reuse-values` are strongly encouraged to migrate to `--reset-then-reuse-values`. + +For more information see [the deprecation announcement](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/issues/1864). + +### Other Changes +* Bump driver version to `v1.28.0` and sidecars to latest versions +* Add labels to leases role used by EBS CSI controller ([#1914](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1914), [@cHiv0rz](https://github.com/cHiv0rz)) +* Enforce `linux` and `amd64` node affinity for helm tester pod ([#1922](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1922), [@AndrewSirenko](https://github.com/AndrewSirenko)) +* Add configuration for `DaemonSet` annotations ([#1923](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1923), [@AndrewSirenko](https://github.com/AndrewSirenko)) +* Incorporate KubeLinter recommended best practices for chart tester pod ([#1924](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1924), [@torredil](https://github.com/torredil)) +* Add configuration for chart tester pod image ([#1928](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1928), [@AndrewSirenko](https://github.com/AndrewSirenko)) + +## v2.27.0 +* Bump driver version to `v1.27.0` +* Add parameters for tuning revisionHistoryLimit and emptyDir volumes ([#1840](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1840), [@bodgit](https://github.com/bodgit)) + +## v2.26.1 +* Bump driver version to `v1.26.1` +* Bump sidecar container versions to fix [restart bug in external attacher, provisioner, resizer, snapshotter, and node-driver-registrar](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/issues/1875) ([#1886](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1886), [@AndrewSirenko](https://github.com/AndrewSirenko)) + +## v2.26.0 +* Bump driver version to `v1.26.0` +* Bump sidecar container versions ([#1867](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1867), [@AndrewSirenko](https://github.com/AndrewSirenko)) +* Add warning about --reuse-values deprecation to NOTES.txt ([#1865](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1865), [@ConnorJC3](https://github.com/ConnorJC3)) + +## v2.25.0 +* Bump driver version to `v1.25.0` +* Update default sidecar timeout values ([#1824](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1824), [@torredil](https://github.com/torredil)) +* Increase default QPS and worker threads of sidecars ([#1834](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1834), [@ConnorJC3](https://github.com/ConnorJC3)) +* Node-driver-registrar sidecar fixes ([#1815](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1815), [@jukie](https://github.com/jukie)) +* Suggest eks.amazonaws.com/role-arn in values.yaml if EKS IAM for SA is used ([#1804](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1804), [@tporeba](https://github.com/tporeba)) + +## v2.24.1 +* Bump driver version to `v1.24.1` +* Upgrade sidecar images + +## v2.24.0 +* Bump driver version to `v1.24.0` +* Add additionalClusterRoleRules to sidecar chart templates. ([#1757](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1757), [@AndrewSirenko](https://github.com/AndrewSirenko)) +* Allow passing template value for clusterName ([#1753](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1753), [@monicastanciu](https://github.com/monicastanciu)) +* Make hostNetwork configurable for daemonset ([#1716](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1716), [@bseenu](https://github.com/bseenu)) +* Add labels to volumesnapshotclass ([#1754](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1754), [@fad3t](https://github.com/fad3t)) +* Update default API version for PodDisruptionBudget ([#1751](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1751), [@AndrewSirenko](https://github.com/AndrewSirenko)) + +## v2.23.2 +* Bump driver version to `v1.23.2` +* Upgrade sidecar images + +## v2.23.1 +* Bump driver version to `v1.23.1` + +## v2.23.0 +* Add `node.enableLinux` parameter ([#1732](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1732), [@monicastanciu](https://github.com/monicastanciu)) +* Additional Node DaemonSets bug fixes ([#1739](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1739), [@monicastanciu](https://github.com/monicastanciu)) +* Additional DaemonSets feature ([#1722](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1722), [@ConnorJC3](https://github.com/ConnorJC3)) +* Add doc of chart value additionalArgs ([#1697](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1697), [@zitudu](https://github.com/zitudu)) + +## v2.22.1 +* Bump driver version to `v1.22.1` + +## v2.22.0 +* Default PodDisruptionBudget to policy/v1 ([#1707](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1707), [@iNoahNothing](https://github.com/iNoahNothing)) + +## v2.21.0 +* Bump driver version to `v1.21.0` +* Enable additional volume mounts on node pods ([#1670](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1670), [@AndrewSirenko](https://github.com/AndrewSirenko)) +* Enable customization of aws-secret name and keys in Helm Chart ([#1668](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1668), [@AndrewSirenko](https://github.com/AndrewSirenko)) +* The sidecars have been updated. The new versions are: + - csi-snapshotter: `v6.2.2` + +## v2.20.0 +* Bump driver version to `v1.20.0` +* Enable leader election in csi-resizer sidecar ([#1606](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1606), [@rdpsin](https://github.com/rdpsin)) +* Namespace-scoped leases permissions ([#1614](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1614), [@torredil](https://github.com/torredil)) +* Add additionalArgs parameter for sidecars ([#1627](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1627), [@ConnorJC3](https://github.com/ConnorJC3)) +* Avoid generating manifests with empty envFrom fields ([#1630](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1630), [@mvgmb](https://github.com/mvgmb)) +* Allow to set automountServiceAccountToken in ServiceAccount ([#1619](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1619), [@kahirokunn](https://github.com/kahirokunn)) + +## v2.19.0 +* Bump driver version to `v1.19.0` +* The sidecars have been updated. The new versions are: + - csi-provisioner: `v3.5.0` + - csi-attacher: `v4.3.0` + - livenessprobe: `v2.10.0` + - csi-resizer: `v1.8.0` + - node-driver-registrar: `v2.8.0` +* Remove CPU limits ([#1596](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1596), [@torredil](https://github.com/torredil)) + +## v2.18.0 +### Urgent Upgrade Notes +*(No, really, you MUST read this before you upgrade)* + +The Helm chart now defaults to using specific releases of the EKS-D sidecars, rather than the `-latest` versions. This is done so the chart will specify an exact container image, as well as for consistency with the EKS Addons version of the driver. + +The new sidecar tags are: +* csi-provisioner: `v3.4.1-eks-1-26-7` +* csi-attacher: `v4.2.0-eks-1-26-7` +* csi-snapshotter: `v6.2.1-eks-1-26-7` +* livenessprobe: `v2.9.0-eks-1-26-7` +* csi-resizer: `v1.7.0-eks-1-26-7` +* node-driver-registrar: `v2.7.0-eks-1-26-7` + +### Improvements +* Bump driver version to `v1.18.0` +* Increase speed and reliability of `helm test` ([#1533](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1533), [@torredil](https://github.com/torredil)) +* Support `VolumeSnapshotClass` in helm chart ([#1540](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1540), [@hanyuel](https://github.com/hanyuel)) + +## v2.17.2 +* Bump driver version to `v1.17.0` +* Bump `external-resizer` version to `v4.2.0` +* All other sidecars have been updated to the latest rebuild (without an associated version change) + +## v2.17.1 +* Bump driver version to `v1.16.1` + +## v2.17.0 +* Bump driver version to `v1.16.0` +* Add support for JSON logging ([#1467](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1467), [@torredil](https://github.com/torredil)) + * `--logging-format` flag has been added to set the log format. Valid values are `text` and `json`. The default value is `text`. + * `--logtostderr` is deprecated. + * Long arguments prefixed with `-` are no longer supported, and must be prefixed with `--`. For example, `--volume-attach-limit` instead of `-volume-attach-limit`. +* The sidecars have been updated. The new versions are: + - csi-provisioner: `v3.4.0` + - csi-attacher: `v4.1.0` + - csi-snapshotter: `v6.2.1` + - livenessprobe: `v2.9.0` + - csi-resizer: `v1.7.0` + - node-driver-registrar: `v2.7.0` + + +## v2.16.0 +* Bump driver version to `v1.15.0` +* Change default sidecars to EKS-D ([#1475](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1475), [@ConnorJC3](https://github.com/ConnorJC3), [@torredil](https://github.com/torredil)) +* The sidecars have been updated. The new versions are: + - csi-provisioner: `v3.3.0` + - csi-attacher: `v4.0.0` + - csi-snapshotter: `v6.1.0` + - livenessprobe: `v2.8.0` + - csi-resizer: `v1.6.0` + - node-driver-registrar: `v2.6.2` + +## v2.15.1 +* Bugfix: Prevent deployment of testing resources during normal installation by adding `helm.sh/hook: test` annotation. + +## v2.15.0 +* Set sensible default resource requests/limits +* Add sensible default update strategy +* Add podAntiAffinity so controller pods prefer scheduling on separate nodes if possible +* Add container registry parameter + +## v2.14.2 +* Bump driver version to `v1.14.1` + +## v2.14.1 +* Add `controller.sdkDebugLog` parameter + +## v2.14.0 +* Bump driver version to `v1.14.0` + +## v2.13.0 +* Bump app/driver to version `v1.13.0` +* Expose volumes and volumeMounts for the ebs-csi-controller deployment ([#1400](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1436), [@cnmcavoy](https://github.com/cnmcavoy)) +* refactor: Move the default controller tolerations in the helm chart values ([#1427](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1427), [@cnmcavoy](https://github.com/Linutux42)) +* Add serviceMonitor.labels parameter ([#1419](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1419), [@torredil](https://github.com/torredil)) +* Add parameter to force enable snapshotter sidecar ([#1418](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1418), [@ConnorJC3](https://github.com/ConnorJC3)) + +## v2.12.1 +* Bump app/driver to version `v1.12.1` + +## v2.12.0 +* Bump app/driver to version `v1.12.0` +* Move default toleration to values.yaml so it can be overriden if desired by users ([#1400](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1400), [@cnmcavoy](https://github.com/cnmcavoy)) +* Add enableMetrics configuration ([#1380](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1380), [@torredil](https://github.com/torredil)) +* add initContainer to the controller's template ([#1379](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1379), [@InsomniaCoder](https://github.com/InsomniaCoder)) +* Add controller nodeAffinity to prefer EC2 over Fargate ([#1360](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1360), [@torredil](https://github.com/torredil)) + +## v2.11.1 +* Add `useOldCSIDriver` parameter to use old `CSIDriver` object. + +## v2.11.0 + +**Important Notice:** This version updates the `CSIDriver` object in order to fix [a bug with static volumes and the `fsGroup` parameter](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/issues/1365). This upgrade will fail on existing clusters because the associated field in `CSIDriver` is immutable. + +Users upgrading to this version should pre-delete the existing `CSIDriver` object (example: `kubectl delete csidriver ebs.csi.aws.com`). This will not affect any existing volumes, but will cause the EBS CSI Driver to be unavailable to handle future requests, and should be immediately followed by an upgrade. For users that cannot delete the `CSIDriver` object, v2.11.1 implements a new parameter `useOldCSIDriver` that will use the previous `CSIDriver`. + +* Bump app/driver to version `v1.11.3` +* Add support for leader election tuning for `csi-provisioner` and `csi-attacher` ([#1371](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1371), [@moogzy](https://github.com/moogzy)) +* Change `fsGroupPolicy` to `File` ([#1377](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1377), [@ConnorJC3](https://github.com/ConnorJC3)) +* Allow all taint for `csi-node` by default ([#1381](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1381), [@gtxu](https://github.com/gtxu)) + +## v2.10.1 +* Bump app/driver to version `v1.11.2` + +## v2.10.0 +* Implement securityContext for containers +* Add securityContext for node pod +* Utilize more secure defaults for securityContext + +## v2.9.0 +* Bump app/driver to version `v1.10.0` +* Feature: Reference `configMaps` across multiple resources using `envFrom` ([#1312](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1312), [@jebbens](https://github.com/jebbens)) + +## v2.8.1 +* Bump app/driver to version `v1.9.0` +* Update livenessprobe to version `v2.6.0` + +## v2.8.0 +* Feature: Support custom affinity definition on node daemon set ([#1277](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1277), [@vauchok](https://github.com/vauchok)) + +## v2.7.1 +* Bump app/driver to version `v1.8.0` + +## v2.7.0 +* Support optional ec2 endpoint configuration. +* Fix node driver registrar socket path. +* Fix hardcoded kubelet path. + +## v2.6.11 +* Bump app/driver to version `v1.7.0` +* Set handle-volume-inuse-error to `false` + +## v2.6.10 + +* Add quotes around the `extra-tags` argument in order to prevent special characters such as `":"` from breaking the manifest YAML after template rendering. + +## v2.6.9 + +* Update csi-snapshotter to version `v6.0.1` +* Update external-attacher to version `v3.4.0` +* Update external-resizer to version `v1.4.0` +* Update external-provisioner to version `v3.1.0` +* Update node-driver-registrar to version `v2.5.1` +* Update livenessprobe to version `v2.5.0` + +## v2.6.8 + +* Bump app/driver to version `v1.6.2` +* Bump sidecar version for nodeDriverRegistrar, provisioner to be consistent with EKS CSI Driver Add-on + +## v2.6.7 + +* Bump app/driver to version `v1.6.1` + +## v2.6.6 + +* Bump app/driver to version `v1.6.0` + +## v2.6.5 + +* Bump app/driver to version `v1.5.3` + +## v2.6.4 + +* Remove exposure all secrets to external-snapshotter-role + +## v2.6.3 + +* Bump app/driver to version `v1.5.1` + +## v2.6.2 + +* Update csi-resizer version to v1.1.0 + +## v2.6.1 + +* Add securityContext support for controller Deployment + +## v2.5.0 + +* Bump app/driver version to `v1.5.0` + +## v2.4.1 + +* Replace deprecated arg `--extra-volume-tags` by `--extra-tags` + +## v2.4.0 + +* Bump app/driver version to `v1.4.0` + +## v2.3.1 + +* Bump app/driver version to `v1.3.1` + +## v2.3.0 + +* Support overriding controller `--default-fstype` flag via values + +## v2.2.1 + +* Bump app/driver version to `v1.3.0` + +## v2.2.0 + +* Support setting imagePullPolicy for all containers + +## v2.1.1 + +* Bump app/driver version to `v1.2.1` + +## v2.1.0 + +* Custom `controller.updateStrategy` to set controller deployment strategy. + +## v2.0.4 + +* Use chart app version as default image tag +* Add updateStrategy to daemonsets + +## v2.0.3 + +* Bump app/driver version to `v1.2.0` + +## v2.0.2 + +* Bump app/driver version to `v1.1.3` + +## v2.0.1 + +* Only create Windows daemonset if enableWindows is true +* Update Windows daemonset to align better to the Linux one + +## v2.0.0 + +* Remove support for Helm 2 +* Remove deprecated values +* No longer install snapshot controller or its CRDs +* Reorganize additional values + +[Upgrade instructions](/docs/README.md#upgrading-from-version-1x-to-2x-of-the-helm-chart) + +## v1.2.4 + +* Bump app/driver version to `v1.1.1` +* Install VolumeSnapshotClass, VolumeSnapshotContent, VolumeSnapshot CRDs if enableVolumeSnapshot is true +* Only run csi-snapshotter sidecar if enableVolumeSnapshot is true or if CRDs are already installed diff --git a/backing-services/aws-ebs-csi-driver/Chart.yaml b/backing-services/aws-ebs-csi-driver/Chart.yaml new file mode 100644 index 0000000..f22a10f --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/Chart.yaml @@ -0,0 +1,16 @@ +apiVersion: v2 +appVersion: 1.32.0 +description: A Helm chart for AWS EBS CSI Driver +home: https://github.com/kubernetes-sigs/aws-ebs-csi-driver +keywords: +- aws +- ebs +- csi +kubeVersion: '>=1.17.0-0' +maintainers: +- name: Kubernetes Authors + url: https://github.com/kubernetes-sigs/aws-ebs-csi-driver/ +name: aws-ebs-csi-driver +sources: +- https://github.com/kubernetes-sigs/aws-ebs-csi-driver +version: 2.32.0 diff --git a/backing-services/aws-ebs-csi-driver/templates/NOTES.txt b/backing-services/aws-ebs-csi-driver/templates/NOTES.txt new file mode 100644 index 0000000..cb3e6ce --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/NOTES.txt @@ -0,0 +1,5 @@ +To verify that aws-ebs-csi-driver has started, run: + + kubectl get pod -n {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "aws-ebs-csi-driver.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" + +NOTE: The [CSI Snapshotter](https://github.com/kubernetes-csi/external-snapshotter) controller and CRDs will no longer be installed as part of this chart and moving forward will be a prerequisite of using the snap shotting functionality. diff --git a/backing-services/aws-ebs-csi-driver/templates/_helpers.tpl b/backing-services/aws-ebs-csi-driver/templates/_helpers.tpl new file mode 100644 index 0000000..42fc138 --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/_helpers.tpl @@ -0,0 +1,85 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "aws-ebs-csi-driver.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "aws-ebs-csi-driver.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "aws-ebs-csi-driver.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "aws-ebs-csi-driver.labels" -}} +{{ include "aws-ebs-csi-driver.selectorLabels" . }} +{{- if ne .Release.Name "kustomize" }} +helm.sh/chart: {{ include "aws-ebs-csi-driver.chart" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/component: csi-driver +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} +{{- if .Values.customLabels }} +{{ toYaml .Values.customLabels }} +{{- end }} +{{- end -}} + +{{/* +Common selector labels +*/}} +{{- define "aws-ebs-csi-driver.selectorLabels" -}} +app.kubernetes.io/name: {{ include "aws-ebs-csi-driver.name" . }} +{{- if ne .Release.Name "kustomize" }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} +{{- end -}} + +{{/* +Convert the `--extra-tags` command line arg from a map. +*/}} +{{- define "aws-ebs-csi-driver.extra-volume-tags" -}} +{{- $result := dict "pairs" (list) -}} +{{- range $key, $value := .Values.controller.extraVolumeTags -}} +{{- $noop := printf "%s=%v" $key $value | append $result.pairs | set $result "pairs" -}} +{{- end -}} +{{- if gt (len $result.pairs) 0 -}} +{{- printf "- \"--extra-tags=%s\"" (join "," $result.pairs) -}} +{{- end -}} +{{- end -}} + +{{/* +Handle http proxy env vars +*/}} +{{- define "aws-ebs-csi-driver.http-proxy" -}} +- name: HTTP_PROXY + value: {{ .Values.proxy.http_proxy | quote }} +- name: HTTPS_PROXY + value: {{ .Values.proxy.http_proxy | quote }} +- name: NO_PROXY + value: {{ .Values.proxy.no_proxy | quote }} +{{- end -}} diff --git a/backing-services/aws-ebs-csi-driver/templates/_node-windows.tpl b/backing-services/aws-ebs-csi-driver/templates/_node-windows.tpl new file mode 100644 index 0000000..76ab90f --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/_node-windows.tpl @@ -0,0 +1,263 @@ +{{- define "node-windows" }} +{{- if .Values.node.enableWindows }} +--- +kind: DaemonSet +apiVersion: apps/v1 +metadata: + name: {{ printf "%s-windows" .NodeName }} + namespace: {{ .Values.node.namespaceOverride | default .Release.Namespace }} + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} +spec: + {{- if or (kindIs "float64" .Values.node.revisionHistoryLimit) (kindIs "int64" .Values.node.revisionHistoryLimit) }} + revisionHistoryLimit: {{ .Values.node.revisionHistoryLimit }} + {{- end }} + selector: + matchLabels: + app: {{ .NodeName }} + {{- include "aws-ebs-csi-driver.selectorLabels" . | nindent 6 }} + updateStrategy: + {{ toYaml .Values.node.updateStrategy | nindent 4 }} + template: + metadata: + labels: + app: {{ .NodeName }} + {{- include "aws-ebs-csi-driver.labels" . | nindent 8 }} + {{- if .Values.node.podLabels }} + {{- toYaml .Values.node.podLabels | nindent 8 }} + {{- end }} + {{- with .Values.node.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.node.affinity }} + affinity: {{- toYaml . | nindent 8 }} + {{- end }} + nodeSelector: + kubernetes.io/os: windows + {{- with .Values.node.nodeSelector }} + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ .Values.node.serviceAccount.name }} + terminationGracePeriodSeconds: {{ .Values.node.terminationGracePeriodSeconds }} + priorityClassName: {{ .Values.node.priorityClassName | default "system-node-critical" }} + tolerations: + {{- if .Values.node.tolerateAllTaints }} + - operator: Exists + {{- else }} + {{- with .Values.node.tolerations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.node.windowsHostProcess }} + securityContext: + windowsOptions: + hostProcess: true + runAsUserName: "NT AUTHORITY\\SYSTEM" + hostNetwork: true + {{- end }} + containers: + - name: ebs-plugin + image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.image.repository (default (printf "v%s" .Chart.AppVersion) (toString .Values.image.tag)) }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.node.windowsHostProcess }} + command: + - "aws-ebs-csi-driver.exe" + {{- end }} + args: + - node + - --endpoint=$(CSI_ENDPOINT) + {{- with .Values.node.volumeAttachLimit }} + - --volume-attach-limit={{ . }} + {{- end }} + {{- with .Values.node.loggingFormat }} + - --logging-format={{ . }} + {{- end }} + - --v={{ .Values.node.logLevel }} + {{- if .Values.node.otelTracing }} + - --enable-otel-tracing=true + {{- end}} + {{- if .Values.node.windowsHostProcess }} + - --windows-host-process=true + {{- end }} + env: + - name: CSI_ENDPOINT + {{- if .Values.node.windowsHostProcess }} + value: unix://C:\\var\\lib\\kubelet\\plugins\\ebs.csi.aws.com\\csi.sock + {{- else }} + value: unix:/csi/csi.sock + {{- end }} + - name: CSI_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + {{- if .Values.proxy.http_proxy }} + {{- include "aws-ebs-csi-driver.http-proxy" . | nindent 12 }} + {{- end }} + {{- with .Values.node.otelTracing }} + - name: OTEL_SERVICE_NAME + value: {{ .otelServiceName }} + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: {{ .otelExporterEndpoint }} + {{- end }} + {{- with .Values.node.env }} + {{- . | toYaml | nindent 12 }} + {{- end }} + volumeMounts: + - name: kubelet-dir + mountPath: C:\var\lib\kubelet + mountPropagation: "None" + - name: plugin-dir + mountPath: C:\csi + {{- if not .Values.node.windowsHostProcess }} + - name: csi-proxy-disk-pipe + mountPath: \\.\pipe\csi-proxy-disk-v1 + - name: csi-proxy-volume-pipe + mountPath: \\.\pipe\csi-proxy-volume-v1 + - name: csi-proxy-filesystem-pipe + mountPath: \\.\pipe\csi-proxy-filesystem-v1 + {{- end }} + ports: + - name: healthz + containerPort: 9808 + protocol: TCP + livenessProbe: + httpGet: + path: /healthz + port: healthz + initialDelaySeconds: 10 + timeoutSeconds: 3 + periodSeconds: 10 + failureThreshold: 5 + {{- with .Values.node.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if not .Values.node.windowsHostProcess }} + securityContext: + windowsOptions: + runAsUserName: "ContainerAdministrator" + {{- end }} + lifecycle: + preStop: + exec: + command: ["/bin/aws-ebs-csi-driver", "pre-stop-hook"] + - name: node-driver-registrar + image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.nodeDriverRegistrar.image.repository .Values.sidecars.nodeDriverRegistrar.image.tag }} + imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.nodeDriverRegistrar.image.pullPolicy }} + {{- if .Values.node.windowsHostProcess }} + command: + - "csi-node-driver-registrar.exe" + {{- end }} + args: + - --csi-address=$(ADDRESS) + - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) + {{- if .Values.node.windowsHostProcess }} + - --plugin-registration-path=$(PLUGIN_REG_DIR) + {{- end }} + - --v={{ .Values.sidecars.nodeDriverRegistrar.logLevel }} + env: + - name: ADDRESS + {{- if .Values.node.windowsHostProcess }} + value: unix://C:\\var\\lib\\kubelet\\plugins\\ebs.csi.aws.com\\csi.sock + {{- else }} + value: unix:/csi/csi.sock + {{- end }} + - name: DRIVER_REG_SOCK_PATH + {{- if .Values.node.windowsHostProcess }} + value: C:\\var\\lib\\kubelet\\plugins\\ebs.csi.aws.com\\csi.sock + {{- else }} + value: C:\var\lib\kubelet\plugins\ebs.csi.aws.com\csi.sock + {{- end }} + {{- if .Values.node.windowsHostProcess }} + - name: PLUGIN_REG_DIR + value: C:\\var\\lib\\kubelet\\plugins_registry\\ + {{- end }} + {{- if .Values.proxy.http_proxy }} + {{- include "aws-ebs-csi-driver.http-proxy" . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.nodeDriverRegistrar.env }} + {{- . | toYaml | nindent 12 }} + {{- end }} + livenessProbe: + exec: + command: + - /csi-node-driver-registrar.exe + - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) + - --mode=kubelet-registration-probe + initialDelaySeconds: 30 + timeoutSeconds: 15 + periodSeconds: 90 + volumeMounts: + - name: plugin-dir + mountPath: C:\csi + - name: registration-dir + mountPath: C:\registration + - name: probe-dir + mountPath: C:\var\lib\kubelet\plugins\ebs.csi.aws.com + {{- with default .Values.node.resources .Values.sidecars.nodeDriverRegistrar.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + - name: liveness-probe + image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.livenessProbe.image.repository .Values.sidecars.livenessProbe.image.tag }} + imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.livenessProbe.image.pullPolicy }} + {{- if .Values.node.windowsHostProcess }} + command: + - "livenessprobe.exe" + {{- end }} + args: + {{- if .Values.node.windowsHostProcess }} + - --csi-address=unix://C:\\var\\lib\\kubelet\\plugins\\ebs.csi.aws.com\\csi.sock + {{- else }} + - --csi-address=unix:/csi/csi.sock + {{- end }} + volumeMounts: + - name: plugin-dir + mountPath: C:\csi + {{- with default .Values.node.resources .Values.sidecars.livenessProbe.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- range .Values.imagePullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} + volumes: + - name: kubelet-dir + hostPath: + path: C:\var\lib\kubelet + type: Directory + - name: plugin-dir + hostPath: + path: C:\var\lib\kubelet\plugins\ebs.csi.aws.com + type: DirectoryOrCreate + - name: registration-dir + hostPath: + path: C:\var\lib\kubelet\plugins_registry + type: Directory + {{- if not .Values.node.windowsHostProcess }} + - name: csi-proxy-disk-pipe + hostPath: + path: \\.\pipe\csi-proxy-disk-v1 + type: "" + - name: csi-proxy-volume-pipe + hostPath: + path: \\.\pipe\csi-proxy-volume-v1 + type: "" + - name: csi-proxy-filesystem-pipe + hostPath: + path: \\.\pipe\csi-proxy-filesystem-v1 + type: "" + {{- end }} + - name: probe-dir + {{- if .Values.node.probeDirVolume }} + {{- toYaml .Values.node.probeDirVolume | nindent 10 }} + {{- else }} + emptyDir: {} + {{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/aws-ebs-csi-driver/templates/_node.tpl b/backing-services/aws-ebs-csi-driver/templates/_node.tpl new file mode 100644 index 0000000..383e2a2 --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/_node.tpl @@ -0,0 +1,245 @@ +{{- define "node" }} +{{- if or (eq (default true .Values.node.enableLinux) true) }} +--- +kind: DaemonSet +apiVersion: apps/v1 +metadata: + name: {{ .NodeName }} + namespace: {{ .Values.node.namespaceOverride | default .Release.Namespace }} + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} + {{- with .Values.node.daemonSetAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if or (kindIs "float64" .Values.node.revisionHistoryLimit) (kindIs "int64" .Values.node.revisionHistoryLimit) }} + revisionHistoryLimit: {{ .Values.node.revisionHistoryLimit }} + {{- end }} + selector: + matchLabels: + app: {{ .NodeName }} + {{- include "aws-ebs-csi-driver.selectorLabels" . | nindent 6 }} + updateStrategy: + {{- toYaml .Values.node.updateStrategy | nindent 4 }} + template: + metadata: + labels: + app: {{ .NodeName }} + {{- include "aws-ebs-csi-driver.labels" . | nindent 8 }} + {{- if .Values.node.podLabels }} + {{- toYaml .Values.node.podLabels | nindent 8 }} + {{- end }} + {{- with .Values.node.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.node.affinity }} + affinity: {{- toYaml . | nindent 8 }} + {{- end }} + nodeSelector: + kubernetes.io/os: linux + {{- with .Values.node.nodeSelector }} + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ .Values.node.serviceAccount.name }} + terminationGracePeriodSeconds: {{ .Values.node.terminationGracePeriodSeconds }} + priorityClassName: {{ .Values.node.priorityClassName | default "system-node-critical" }} + tolerations: + {{- if .Values.node.tolerateAllTaints }} + - operator: Exists + {{- else }} + {{- with .Values.node.tolerations }} + {{- toYaml . | nindent 8 }} + {{- end }} + - key: "ebs.csi.aws.com/agent-not-ready" + operator: "Exists" + {{- end }} + hostNetwork: {{ .Values.node.hostNetwork }} + {{- with .Values.node.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: ebs-plugin + image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.image.repository (default (printf "v%s" .Chart.AppVersion) (toString .Values.image.tag)) }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - node + - --endpoint=$(CSI_ENDPOINT) + {{- with .Values.node.reservedVolumeAttachments }} + - --reserved-volume-attachments={{ . }} + {{- end }} + {{- with .Values.node.volumeAttachLimit }} + - --volume-attach-limit={{ . }} + {{- end }} + {{- with .Values.node.loggingFormat }} + - --logging-format={{ . }} + {{- end }} + - --v={{ .Values.node.logLevel }} + {{- if .Values.node.otelTracing }} + - --enable-otel-tracing=true + {{- end}} + {{- range .Values.node.additionalArgs }} + - {{ . }} + {{- end }} + env: + - name: CSI_ENDPOINT + value: unix:/csi/csi.sock + - name: CSI_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + {{- if .Values.proxy.http_proxy }} + {{- include "aws-ebs-csi-driver.http-proxy" . | nindent 12 }} + {{- end }} + {{- with .Values.node.otelTracing }} + - name: OTEL_SERVICE_NAME + value: {{ .otelServiceName }} + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: {{ .otelExporterEndpoint }} + {{- end }} + {{- with .Values.node.env }} + {{- . | toYaml | nindent 12 }} + {{- end }} + {{- with .Values.controller.envFrom }} + envFrom: + {{- . | toYaml | nindent 12 }} + {{- end }} + volumeMounts: + - name: kubelet-dir + mountPath: {{ .Values.node.kubeletPath }} + mountPropagation: "Bidirectional" + - name: plugin-dir + mountPath: /csi + - name: device-dir + mountPath: /dev + {{- with .Values.node.volumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: healthz + containerPort: 9808 + protocol: TCP + livenessProbe: + httpGet: + path: /healthz + port: healthz + initialDelaySeconds: 10 + timeoutSeconds: 3 + periodSeconds: 10 + failureThreshold: 5 + {{- with .Values.node.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.node.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + lifecycle: + preStop: + exec: + command: ["/bin/aws-ebs-csi-driver", "pre-stop-hook"] + - name: node-driver-registrar + image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.nodeDriverRegistrar.image.repository .Values.sidecars.nodeDriverRegistrar.image.tag }} + imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.nodeDriverRegistrar.image.pullPolicy }} + args: + - --csi-address=$(ADDRESS) + - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) + - --v={{ .Values.sidecars.nodeDriverRegistrar.logLevel }} + {{- range .Values.sidecars.nodeDriverRegistrar.additionalArgs }} + - {{ . }} + {{- end }} + env: + - name: ADDRESS + value: /csi/csi.sock + - name: DRIVER_REG_SOCK_PATH + value: {{ printf "%s/plugins/ebs.csi.aws.com/csi.sock" (trimSuffix "/" .Values.node.kubeletPath) }} + {{- if .Values.proxy.http_proxy }} + {{- include "aws-ebs-csi-driver.http-proxy" . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.nodeDriverRegistrar.env }} + {{- . | toYaml | nindent 12 }} + {{- end }} + {{- with .Values.controller.envFrom }} + envFrom: + {{- . | toYaml | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.nodeDriverRegistrar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: plugin-dir + mountPath: /csi + - name: registration-dir + mountPath: /registration + - name: probe-dir + mountPath: {{ printf "%s/plugins/ebs.csi.aws.com/" (trimSuffix "/" .Values.node.kubeletPath) }} + {{- with default .Values.node.resources .Values.sidecars.nodeDriverRegistrar.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.nodeDriverRegistrar.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + - name: liveness-probe + image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.livenessProbe.image.repository .Values.sidecars.livenessProbe.image.tag }} + imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.livenessProbe.image.pullPolicy }} + args: + - --csi-address=/csi/csi.sock + {{- range .Values.sidecars.livenessProbe.additionalArgs }} + - {{ . }} + {{- end }} + {{- with .Values.controller.envFrom }} + envFrom: + {{- . | toYaml | nindent 12 }} + {{- end }} + volumeMounts: + - name: plugin-dir + mountPath: /csi + {{- with default .Values.node.resources .Values.sidecars.livenessProbe.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.livenessProbe.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- range .Values.imagePullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} + volumes: + - name: kubelet-dir + hostPath: + path: {{ .Values.node.kubeletPath }} + type: Directory + - name: plugin-dir + hostPath: + path: {{ printf "%s/plugins/ebs.csi.aws.com/" (trimSuffix "/" .Values.node.kubeletPath) }} + type: DirectoryOrCreate + - name: registration-dir + hostPath: + path: {{ printf "%s/plugins_registry/" (trimSuffix "/" .Values.node.kubeletPath) }} + type: Directory + - name: device-dir + hostPath: + path: /dev + type: Directory + - name: probe-dir + {{- if .Values.node.probeDirVolume }} + {{- toYaml .Values.node.probeDirVolume | nindent 10 }} + {{- else }} + emptyDir: {} + {{- end }} + {{- with .Values.node.volumes }} + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/aws-ebs-csi-driver/templates/clusterrole-attacher.yaml b/backing-services/aws-ebs-csi-driver/templates/clusterrole-attacher.yaml new file mode 100644 index 0000000..bff6577 --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/clusterrole-attacher.yaml @@ -0,0 +1,26 @@ +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: ebs-external-attacher-role + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} +rules: + - apiGroups: [ "" ] + resources: [ "persistentvolumes" ] + verbs: [ "get", "list", "watch", "update", "patch" ] + - apiGroups: [ "" ] + resources: [ "nodes" ] + verbs: [ "get", "list", "watch" ] + - apiGroups: [ "csi.storage.k8s.io" ] + resources: [ "csinodeinfos" ] + verbs: [ "get", "list", "watch" ] + - apiGroups: [ "storage.k8s.io" ] + resources: [ "volumeattachments" ] + verbs: [ "get", "list", "watch", "update", "patch" ] + - apiGroups: [ "storage.k8s.io" ] + resources: [ "volumeattachments/status" ] + verbs: [ "patch" ] + {{- with .Values.sidecars.attacher.additionalClusterRoleRules }} + {{- . | toYaml | nindent 2 }} + {{- end }} diff --git a/backing-services/aws-ebs-csi-driver/templates/clusterrole-csi-node.yaml b/backing-services/aws-ebs-csi-driver/templates/clusterrole-csi-node.yaml new file mode 100644 index 0000000..2b7295a --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/clusterrole-csi-node.yaml @@ -0,0 +1,17 @@ +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: ebs-csi-node-role + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "patch"] + - apiGroups: ["storage.k8s.io"] + resources: ["volumeattachments"] + verbs: ["get", "list", "watch"] + - apiGroups: ["storage.k8s.io"] + resources: ["csinodes"] + verbs: ["get"] diff --git a/backing-services/aws-ebs-csi-driver/templates/clusterrole-provisioner.yaml b/backing-services/aws-ebs-csi-driver/templates/clusterrole-provisioner.yaml new file mode 100644 index 0000000..cb69cc8 --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/clusterrole-provisioner.yaml @@ -0,0 +1,41 @@ +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: ebs-external-provisioner-role + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} +rules: + - apiGroups: [ "" ] + resources: [ "persistentvolumes" ] + verbs: [ "get", "list", "watch", "create", "patch", "delete" ] + - apiGroups: [ "" ] + resources: [ "persistentvolumeclaims" ] + verbs: [ "get", "list", "watch", "update" ] + - apiGroups: [ "storage.k8s.io" ] + resources: [ "storageclasses" ] + verbs: [ "get", "list", "watch" ] + - apiGroups: [ "" ] + resources: [ "events" ] + verbs: [ "list", "watch", "create", "update", "patch" ] + - apiGroups: [ "snapshot.storage.k8s.io" ] + resources: [ "volumesnapshots" ] + verbs: [ "get", "list" ] + - apiGroups: [ "snapshot.storage.k8s.io" ] + resources: [ "volumesnapshotcontents" ] + verbs: [ "get", "list" ] + - apiGroups: [ "storage.k8s.io" ] + resources: [ "csinodes" ] + verbs: [ "get", "list", "watch" ] + - apiGroups: [ "" ] + resources: [ "nodes" ] + verbs: [ "get", "list", "watch" ] + - apiGroups: [ "storage.k8s.io" ] + resources: [ "volumeattachments" ] + verbs: [ "get", "list", "watch" ] + - apiGroups: [ "storage.k8s.io" ] + resources: [ "volumeattributesclasses" ] + verbs: [ "get" ] + {{- with .Values.sidecars.provisioner.additionalClusterRoleRules }} + {{- . | toYaml | nindent 2 }} + {{- end }} diff --git a/backing-services/aws-ebs-csi-driver/templates/clusterrole-resizer.yaml b/backing-services/aws-ebs-csi-driver/templates/clusterrole-resizer.yaml new file mode 100644 index 0000000..81858af --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/clusterrole-resizer.yaml @@ -0,0 +1,37 @@ +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: ebs-external-resizer-role + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} +rules: + # The following rule should be uncommented for plugins that require secrets + # for provisioning. + # - apiGroups: [""] + # resources: ["secrets"] + # verbs: ["get", "list", "watch"] + - apiGroups: [ "" ] + resources: [ "persistentvolumes" ] + verbs: [ "get", "list", "watch", "update", "patch" ] + - apiGroups: [ "" ] + resources: [ "persistentvolumeclaims" ] + verbs: [ "get", "list", "watch" ] + - apiGroups: [ "" ] + resources: [ "persistentvolumeclaims/status" ] + verbs: [ "update", "patch" ] + - apiGroups: [ "storage.k8s.io" ] + resources: [ "storageclasses" ] + verbs: [ "get", "list", "watch" ] + - apiGroups: [ "" ] + resources: [ "events" ] + verbs: [ "list", "watch", "create", "update", "patch" ] + - apiGroups: [ "" ] + resources: [ "pods" ] + verbs: [ "get", "list", "watch" ] + - apiGroups: [ "storage.k8s.io" ] + resources: [ "volumeattributesclasses" ] + verbs: [ "get", "list", "watch" ] + {{- with .Values.sidecars.resizer.additionalClusterRoleRules }} + {{- . | toYaml | nindent 2 }} + {{- end }} diff --git a/backing-services/aws-ebs-csi-driver/templates/clusterrole-snapshotter.yaml b/backing-services/aws-ebs-csi-driver/templates/clusterrole-snapshotter.yaml new file mode 100644 index 0000000..697e818 --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/clusterrole-snapshotter.yaml @@ -0,0 +1,30 @@ +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: ebs-external-snapshotter-role + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} +rules: + - apiGroups: [ "" ] + resources: [ "events" ] + verbs: [ "list", "watch", "create", "update", "patch" ] + # Secret permission is optional. + # Enable it if your driver needs secret. + # For example, `csi.storage.k8s.io/snapshotter-secret-name` is set in VolumeSnapshotClass. + # See https://kubernetes-csi.github.io/docs/secrets-and-credentials.html for more details. + # - apiGroups: [ "" ] + # resources: [ "secrets" ] + # verbs: [ "get", "list" ] + - apiGroups: [ "snapshot.storage.k8s.io" ] + resources: [ "volumesnapshotclasses" ] + verbs: [ "get", "list", "watch" ] + - apiGroups: [ "snapshot.storage.k8s.io" ] + resources: [ "volumesnapshotcontents" ] + verbs: [ "create", "get", "list", "watch", "update", "delete", "patch" ] + - apiGroups: [ "snapshot.storage.k8s.io" ] + resources: [ "volumesnapshotcontents/status" ] + verbs: [ "update", "patch" ] + {{- with .Values.sidecars.snapshotter.additionalClusterRoleRules }} + {{- . | toYaml | nindent 2 }} + {{- end }} diff --git a/backing-services/aws-ebs-csi-driver/templates/clusterrolebinding-attacher.yaml b/backing-services/aws-ebs-csi-driver/templates/clusterrolebinding-attacher.yaml new file mode 100644 index 0000000..bb23044 --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/clusterrolebinding-attacher.yaml @@ -0,0 +1,15 @@ +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: ebs-csi-attacher-binding + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: {{ .Values.controller.serviceAccount.name }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: ebs-external-attacher-role + apiGroup: rbac.authorization.k8s.io diff --git a/backing-services/aws-ebs-csi-driver/templates/clusterrolebinding-csi-node.yaml b/backing-services/aws-ebs-csi-driver/templates/clusterrolebinding-csi-node.yaml new file mode 100644 index 0000000..8615ad4 --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/clusterrolebinding-csi-node.yaml @@ -0,0 +1,15 @@ +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: ebs-csi-node-getter-binding + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: {{ .Values.node.serviceAccount.name }} + namespace: {{ .Values.node.namespaceOverride | default .Release.Namespace }} +roleRef: + kind: ClusterRole + name: ebs-csi-node-role + apiGroup: rbac.authorization.k8s.io diff --git a/backing-services/aws-ebs-csi-driver/templates/clusterrolebinding-provisioner.yaml b/backing-services/aws-ebs-csi-driver/templates/clusterrolebinding-provisioner.yaml new file mode 100644 index 0000000..9d2749a --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/clusterrolebinding-provisioner.yaml @@ -0,0 +1,15 @@ +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: ebs-csi-provisioner-binding + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: {{ .Values.controller.serviceAccount.name }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: ebs-external-provisioner-role + apiGroup: rbac.authorization.k8s.io diff --git a/backing-services/aws-ebs-csi-driver/templates/clusterrolebinding-resizer.yaml b/backing-services/aws-ebs-csi-driver/templates/clusterrolebinding-resizer.yaml new file mode 100644 index 0000000..88cb47d --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/clusterrolebinding-resizer.yaml @@ -0,0 +1,15 @@ +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: ebs-csi-resizer-binding + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: {{ .Values.controller.serviceAccount.name }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: ebs-external-resizer-role + apiGroup: rbac.authorization.k8s.io diff --git a/backing-services/aws-ebs-csi-driver/templates/clusterrolebinding-snapshotter.yaml b/backing-services/aws-ebs-csi-driver/templates/clusterrolebinding-snapshotter.yaml new file mode 100644 index 0000000..2d42905 --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/clusterrolebinding-snapshotter.yaml @@ -0,0 +1,15 @@ +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: ebs-csi-snapshotter-binding + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: {{ .Values.controller.serviceAccount.name }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: ebs-external-snapshotter-role + apiGroup: rbac.authorization.k8s.io diff --git a/backing-services/aws-ebs-csi-driver/templates/controller.yaml b/backing-services/aws-ebs-csi-driver/templates/controller.yaml new file mode 100644 index 0000000..6b393f4 --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/controller.yaml @@ -0,0 +1,519 @@ +# Controller Service +kind: Deployment +apiVersion: apps/v1 +metadata: + name: ebs-csi-controller + namespace: {{ .Release.Namespace }} + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} + {{- with .Values.controller.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.controller.replicaCount }} + {{- if or (kindIs "float64" .Values.controller.revisionHistoryLimit) (kindIs "int64" .Values.controller.revisionHistoryLimit) }} + revisionHistoryLimit: {{ .Values.controller.revisionHistoryLimit }} + {{- end }} + {{- with .Values.controller.updateStrategy }} + strategy: + {{- toYaml . | nindent 4 }} + {{- end }} + selector: + matchLabels: + app: ebs-csi-controller + {{- include "aws-ebs-csi-driver.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + app: ebs-csi-controller + {{- include "aws-ebs-csi-driver.labels" . | nindent 8 }} + {{- if .Values.controller.podLabels }} + {{- toYaml .Values.controller.podLabels | nindent 8 }} + {{- end }} + {{- if .Values.controller.podAnnotations }} + annotations: + {{- tpl ( .Values.controller.podAnnotations | toYaml ) . | nindent 8 }} + {{- end }} + spec: + nodeSelector: + kubernetes.io/os: linux + {{- with .Values.controller.nodeSelector }} + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ .Values.controller.serviceAccount.name }} + priorityClassName: {{ .Values.controller.priorityClassName }} + {{- with default .Values.controller.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + tolerations: + {{- with .Values.controller.tolerations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.controller.topologySpreadConstraints }} + {{- $tscLabelSelector := dict "labelSelector" ( dict "matchLabels" ( dict "app" "ebs-csi-controller" ) ) }} + {{- $constraints := list }} + {{- range .Values.controller.topologySpreadConstraints }} + {{- $constraints = mustAppend $constraints (mergeOverwrite . $tscLabelSelector) }} + {{- end }} + topologySpreadConstraints: + {{- $constraints | toYaml | nindent 8 }} + {{- end }} + {{- with .Values.controller.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.initContainers }} + initContainers: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: ebs-plugin + image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.image.repository (default (printf "v%s" .Chart.AppVersion) (.Values.image.tag | toString)) }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + {{- if ne .Release.Name "kustomize" }} + - controller + {{- else }} + # - {all,controller,node} # specify the driver mode + {{- end }} + - --endpoint=$(CSI_ENDPOINT) + {{- if .Values.controller.extraVolumeTags }} + {{- include "aws-ebs-csi-driver.extra-volume-tags" . | nindent 12 }} + {{- end }} + {{- with (tpl (default "" .Values.controller.k8sTagClusterId) . ) }} + - --k8s-tag-cluster-id={{ . }} + {{- end }} + {{- if and (.Values.controller.enableMetrics) (not .Values.controller.httpEndpoint) }} + - --http-endpoint=0.0.0.0:3301 + {{- end}} + {{- with .Values.controller.httpEndpoint }} + - --http-endpoint={{ . }} + {{- end }} + {{- if .Values.controller.sdkDebugLog }} + - --aws-sdk-debug-log=true + {{- end}} + {{- if .Values.controller.batching }} + - --batching=true + {{- end}} + {{- with .Values.controller.loggingFormat }} + - --logging-format={{ . }} + {{- end }} + {{- with .Values.controller.userAgentExtra }} + - --user-agent-extra={{ . }} + {{- end }} + {{- if .Values.controller.otelTracing }} + - --enable-otel-tracing=true + {{- end}} + - --v={{ .Values.controller.logLevel }} + {{- range .Values.controller.additionalArgs }} + - {{ . }} + {{- end }} + env: + - name: CSI_ENDPOINT + value: unix:///var/lib/csi/sockets/pluginproxy/csi.sock + - name: CSI_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + {{- with .Values.awsAccessSecret }} + - name: AWS_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: {{ .name }} + key: {{ .keyId }} + optional: true + - name: AWS_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: {{ .name }} + key: {{ .accessKey }} + optional: true + {{- end }} + - name: AWS_EC2_ENDPOINT + valueFrom: + configMapKeyRef: + name: aws-meta + key: endpoint + optional: true + {{- with .Values.controller.region }} + - name: AWS_REGION + value: {{ . }} + {{- end }} + {{- if .Values.proxy.http_proxy }} + {{- include "aws-ebs-csi-driver.http-proxy" . | nindent 12 }} + {{- end }} + {{- with .Values.controller.env }} + {{- . | toYaml | nindent 12 }} + {{- end }} + {{- with .Values.controller.otelTracing }} + - name: OTEL_SERVICE_NAME + value: {{ .otelServiceName }} + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: {{ .otelExporterEndpoint }} + {{- end }} + {{- with .Values.controller.envFrom }} + envFrom: + {{- . | toYaml | nindent 12 }} + {{- end }} + volumeMounts: + - name: socket-dir + mountPath: /var/lib/csi/sockets/pluginproxy/ + {{- with .Values.controller.volumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: healthz + containerPort: 9808 + protocol: TCP + {{- if .Values.controller.enableMetrics }} + - name: metrics + containerPort: 3301 + protocol: TCP + {{- end}} + livenessProbe: + httpGet: + path: /healthz + port: healthz + initialDelaySeconds: 10 + timeoutSeconds: 3 + periodSeconds: 10 + failureThreshold: 5 + readinessProbe: + httpGet: + path: /healthz + port: healthz + initialDelaySeconds: 10 + timeoutSeconds: 3 + periodSeconds: 10 + failureThreshold: 5 + {{- with .Values.controller.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.controller.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + - name: csi-provisioner + image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.provisioner.image.repository .Values.sidecars.provisioner.image.tag }} + imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.provisioner.image.pullPolicy }} + args: + {{- if not (regexMatch "(-timeout)" (join " " .Values.sidecars.provisioner.additionalArgs)) }} + - --timeout=60s + {{- end }} + - --csi-address=$(ADDRESS) + - --v={{ .Values.sidecars.provisioner.logLevel }} + - --feature-gates=Topology=true + {{- if .Values.controller.extraCreateMetadata }} + - --extra-create-metadata + {{- end}} + - --leader-election={{ .Values.sidecars.provisioner.leaderElection.enabled | required "leader election state for csi-provisioner is required, must be set to true || false." }} + {{- if .Values.sidecars.provisioner.leaderElection.enabled }} + {{- if .Values.sidecars.provisioner.leaderElection.leaseDuration }} + - --leader-election-lease-duration={{ .Values.sidecars.provisioner.leaderElection.leaseDuration }} + {{- end }} + {{- if .Values.sidecars.provisioner.leaderElection.renewDeadline}} + - --leader-election-renew-deadline={{ .Values.sidecars.provisioner.leaderElection.renewDeadline }} + {{- end }} + {{- if .Values.sidecars.provisioner.leaderElection.retryPeriod }} + - --leader-election-retry-period={{ .Values.sidecars.provisioner.leaderElection.retryPeriod }} + {{- end }} + {{- end }} + - --default-fstype={{ .Values.controller.defaultFsType }} + {{- if not (regexMatch "(-kube-api-qps)|(-kube-api-burst)|(-worker-threads)" (join " " .Values.sidecars.provisioner.additionalArgs)) }} + - --kube-api-qps=20 + - --kube-api-burst=100 + - --worker-threads=100 + {{- end }} + {{- if not (regexMatch "(-retry-interval-max)" (join " " .Values.sidecars.provisioner.additionalArgs)) }} + - --retry-interval-max=30m + {{- end }} + {{- range .Values.sidecars.provisioner.additionalArgs }} + - {{ . }} + {{- end }} + env: + - name: ADDRESS + value: /var/lib/csi/sockets/pluginproxy/csi.sock + {{- if .Values.proxy.http_proxy }} + {{- include "aws-ebs-csi-driver.http-proxy" . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.provisioner.env }} + {{- . | toYaml | nindent 12 }} + {{- end }} + {{- with .Values.controller.envFrom }} + envFrom: + {{- . | toYaml | nindent 12 }} + {{- end }} + volumeMounts: + - name: socket-dir + mountPath: /var/lib/csi/sockets/pluginproxy/ + {{- with default .Values.controller.resources .Values.sidecars.provisioner.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.provisioner.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + - name: csi-attacher + image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.attacher.image.repository .Values.sidecars.attacher.image.tag }} + imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.attacher.image.pullPolicy }} + args: + {{- if not (regexMatch "(-timeout)" (join " " .Values.sidecars.attacher.additionalArgs)) }} + - --timeout=60s + {{- end }} + - --csi-address=$(ADDRESS) + - --v={{ .Values.sidecars.attacher.logLevel }} + - --leader-election={{ .Values.sidecars.attacher.leaderElection.enabled | required "leader election state for csi-attacher is required, must be set to true || false." }} + {{- if .Values.sidecars.attacher.leaderElection.enabled }} + {{- if .Values.sidecars.attacher.leaderElection.leaseDuration }} + - --leader-election-lease-duration={{ .Values.sidecars.attacher.leaderElection.leaseDuration }} + {{- end }} + {{- if .Values.sidecars.attacher.leaderElection.renewDeadline}} + - --leader-election-renew-deadline={{ .Values.sidecars.attacher.leaderElection.renewDeadline }} + {{- end }} + {{- if .Values.sidecars.attacher.leaderElection.retryPeriod }} + - --leader-election-retry-period={{ .Values.sidecars.attacher.leaderElection.retryPeriod }} + {{- end }} + {{- end }} + {{- if not (regexMatch "(-kube-api-qps)|(-kube-api-burst)|(-worker-threads)" (join " " .Values.sidecars.attacher.additionalArgs)) }} + - --kube-api-qps=20 + - --kube-api-burst=100 + - --worker-threads=100 + {{- end }} + {{- if not (regexMatch "(-retry-interval-max)" (join " " .Values.sidecars.attacher.additionalArgs)) }} + - --retry-interval-max=5m + {{- end }} + {{- range .Values.sidecars.attacher.additionalArgs }} + - {{ . }} + {{- end }} + env: + - name: ADDRESS + value: /var/lib/csi/sockets/pluginproxy/csi.sock + {{- if .Values.proxy.http_proxy }} + {{- include "aws-ebs-csi-driver.http-proxy" . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.attacher.env }} + {{- . | toYaml | nindent 12 }} + {{- end }} + {{- with .Values.controller.envFrom }} + envFrom: + {{- . | toYaml | nindent 12 }} + {{- end }} + volumeMounts: + - name: socket-dir + mountPath: /var/lib/csi/sockets/pluginproxy/ + {{- with default .Values.controller.resources .Values.sidecars.attacher.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.attacher.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if or .Values.sidecars.snapshotter.forceEnable (.Capabilities.APIVersions.Has "snapshot.storage.k8s.io/v1beta1") (.Capabilities.APIVersions.Has "snapshot.storage.k8s.io/v1") }} + - name: csi-snapshotter + image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.snapshotter.image.repository .Values.sidecars.snapshotter.image.tag }} + imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.snapshotter.image.pullPolicy }} + args: + - --csi-address=$(ADDRESS) + - --leader-election=true + {{- if .Values.controller.extraCreateMetadata }} + - --extra-create-metadata + {{- end}} + {{- if not (regexMatch "(-kube-api-qps)|(-kube-api-burst)|(-worker-threads)" (join " " .Values.sidecars.snapshotter.additionalArgs)) }} + - --kube-api-qps=20 + - --kube-api-burst=100 + - --worker-threads=100 + {{- end }} + {{- if not (regexMatch "(-retry-interval-max)" (join " " .Values.sidecars.snapshotter.additionalArgs)) }} + - --retry-interval-max=30m + {{- end }} + {{- range .Values.sidecars.snapshotter.additionalArgs }} + - {{ . }} + {{- end }} + env: + - name: ADDRESS + value: /var/lib/csi/sockets/pluginproxy/csi.sock + {{- if .Values.proxy.http_proxy }} + {{- include "aws-ebs-csi-driver.http-proxy" . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.snapshotter.env }} + {{- . | toYaml | nindent 12 }} + {{- end }} + {{- with .Values.controller.envFrom }} + envFrom: + {{- . | toYaml | nindent 12 }} + {{- end }} + volumeMounts: + - name: socket-dir + mountPath: /var/lib/csi/sockets/pluginproxy/ + {{- with default .Values.controller.resources .Values.sidecars.snapshotter.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.snapshotter.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} + {{- if (.Values.controller.volumeModificationFeature).enabled }} + - name: volumemodifier + image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.volumemodifier.image.repository .Values.sidecars.volumemodifier.image.tag }} + imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.volumemodifier.image.pullPolicy }} + args: + {{- if not (regexMatch "(-timeout)" (join " " .Values.sidecars.volumemodifier.additionalArgs)) }} + - --timeout=60s + {{- end }} + - --csi-address=$(ADDRESS) + - --v={{ .Values.sidecars.volumemodifier.logLevel }} + - --leader-election={{ .Values.sidecars.volumemodifier.leaderElection.enabled | required "leader election state for csi-volumemodifier is required, must be set to true || false." }} + {{- if .Values.sidecars.volumemodifier.leaderElection.enabled }} + {{- if .Values.sidecars.volumemodifier.leaderElection.leaseDuration }} + - --leader-election-lease-duration={{ .Values.sidecars.volumemodifier.leaderElection.leaseDuration }} + {{- end }} + {{- if .Values.sidecars.volumemodifier.leaderElection.renewDeadline}} + - --leader-election-renew-deadline={{ .Values.sidecars.volumemodifier.leaderElection.renewDeadline }} + {{- end }} + {{- if .Values.sidecars.volumemodifier.leaderElection.retryPeriod }} + - --leader-election-retry-period={{ .Values.sidecars.volumemodifier.leaderElection.retryPeriod }} + {{- end }} + {{- end }} + {{- range .Values.sidecars.volumemodifier.additionalArgs }} + - {{ . }} + {{- end }} + env: + - name: ADDRESS + value: /var/lib/csi/sockets/pluginproxy/csi.sock + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if .Values.proxy.http_proxy }} + {{- include "aws-ebs-csi-driver.http-proxy" . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.volumemodifier.env }} + {{- . | toYaml | nindent 12 }} + {{- end }} + {{- with .Values.controller.envFrom }} + envFrom: + {{- . | toYaml | nindent 12 }} + {{- end }} + volumeMounts: + - name: socket-dir + mountPath: /var/lib/csi/sockets/pluginproxy/ + {{- with default .Values.controller.resources .Values.sidecars.volumemodifier.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.volumemodifier.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} + - name: csi-resizer + image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.resizer.image.repository .Values.sidecars.resizer.image.tag }} + imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.resizer.image.pullPolicy }} + args: + {{- if not (regexMatch "(-timeout)" (join " " .Values.sidecars.resizer.additionalArgs)) }} + - --timeout=60s + {{- end }} + - --csi-address=$(ADDRESS) + - --v={{ .Values.sidecars.resizer.logLevel }} + - --handle-volume-inuse-error=false + {{- with .Values.sidecars.resizer.leaderElection }} + - --leader-election={{ .enabled | default true }} + {{- if .leaseDuration }} + - --leader-election-lease-duration={{ .leaseDuration }} + {{- end }} + {{- if .renewDeadline }} + - --leader-election-renew-deadline={{ .renewDeadline }} + {{- end }} + {{- if .retryPeriod }} + - --leader-election-retry-period={{ .retryPeriod }} + {{- end }} + {{- end }} + {{- if not (regexMatch "(-kube-api-qps)|(-kube-api-burst)|(-workers)" (join " " .Values.sidecars.resizer.additionalArgs)) }} + - --kube-api-qps=20 + - --kube-api-burst=100 + - --workers=100 + {{- end }} + {{- if not (regexMatch "(-retry-interval-max)" (join " " .Values.sidecars.resizer.additionalArgs)) }} + - --retry-interval-max=30m + {{- end }} + {{- range .Values.sidecars.resizer.additionalArgs }} + - {{ . }} + {{- end }} + env: + - name: ADDRESS + value: /var/lib/csi/sockets/pluginproxy/csi.sock + {{- if .Values.proxy.http_proxy }} + {{- include "aws-ebs-csi-driver.http-proxy" . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.resizer.env }} + {{- . | toYaml | nindent 12 }} + {{- end }} + {{- with .Values.controller.envFrom }} + envFrom: + {{- . | toYaml | nindent 12 }} + {{- end }} + volumeMounts: + - name: socket-dir + mountPath: /var/lib/csi/sockets/pluginproxy/ + {{- with default .Values.controller.resources .Values.sidecars.resizer.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.resizer.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + - name: liveness-probe + image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.livenessProbe.image.repository .Values.sidecars.livenessProbe.image.tag }} + imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.livenessProbe.image.pullPolicy }} + args: + - --csi-address=/csi/csi.sock + {{- range .Values.sidecars.livenessProbe.additionalArgs }} + - {{ . }} + {{- end }} + {{- with .Values.controller.envFrom }} + envFrom: + {{- . | toYaml | nindent 12 }} + {{- end }} + volumeMounts: + - name: socket-dir + mountPath: /csi + {{- with default .Values.controller.resources .Values.sidecars.livenessProbe.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.livenessProbe.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- range .Values.imagePullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} + volumes: + - name: socket-dir + {{- if .Values.controller.socketDirVolume }} + {{- toYaml .Values.controller.socketDirVolume | nindent 10 }} + {{- else }} + emptyDir: {} + {{- end }} + {{- with .Values.controller.volumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.controller.dnsConfig }} + dnsConfig: + {{- toYaml .Values.controller.dnsConfig | nindent 4 }} + {{- end }} diff --git a/backing-services/aws-ebs-csi-driver/templates/csidriver.yaml b/backing-services/aws-ebs-csi-driver/templates/csidriver.yaml new file mode 100644 index 0000000..a46d4b5 --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/csidriver.yaml @@ -0,0 +1,12 @@ +apiVersion: {{ ternary "storage.k8s.io/v1" "storage.k8s.io/v1beta1" (semverCompare ">=1.18.0-0" .Capabilities.KubeVersion.Version) }} +kind: CSIDriver +metadata: + name: ebs.csi.aws.com + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} +spec: + attachRequired: true + podInfoOnMount: false + {{- if not .Values.useOldCSIDriver }} + fsGroupPolicy: File + {{- end }} diff --git a/backing-services/aws-ebs-csi-driver/templates/ebs-csi-default-sc.yaml b/backing-services/aws-ebs-csi-driver/templates/ebs-csi-default-sc.yaml new file mode 100644 index 0000000..a585957 --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/ebs-csi-default-sc.yaml @@ -0,0 +1,11 @@ +{{- if .Values.defaultStorageClass.enabled }} +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: ebs-csi-default-sc + annotations: + storageclass.kubernetes.io/is-default-class: "true" +provisioner: ebs.csi.aws.com +volumeBindingMode: WaitForFirstConsumer +allowVolumeExpansion: true +{{- end }} diff --git a/backing-services/aws-ebs-csi-driver/templates/metrics.yaml b/backing-services/aws-ebs-csi-driver/templates/metrics.yaml new file mode 100644 index 0000000..d68bd7a --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/metrics.yaml @@ -0,0 +1,42 @@ +{{- if .Values.controller.enableMetrics -}} +--- +apiVersion: v1 +kind: Service +metadata: + name: ebs-csi-controller + namespace: {{ .Release.Namespace }} + labels: + app: ebs-csi-controller +spec: + selector: + app: ebs-csi-controller + ports: + - name: metrics + port: 3301 + targetPort: 3301 + type: ClusterIP +--- +{{- if or .Values.controller.serviceMonitor.forceEnable (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1") }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: ebs-csi-controller + namespace: {{ .Release.Namespace }} + labels: + app: ebs-csi-controller + {{- if .Values.controller.serviceMonitor.labels }} + {{- toYaml .Values.controller.serviceMonitor.labels | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + app: ebs-csi-controller + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + endpoints: + - targetPort: 3301 + path: /metrics + interval: {{ .Values.controller.serviceMonitor.interval | default "15s"}} +{{- end }} +{{- end }} diff --git a/backing-services/aws-ebs-csi-driver/templates/node-windows.yaml b/backing-services/aws-ebs-csi-driver/templates/node-windows.yaml new file mode 100644 index 0000000..9a2c2c8 --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/node-windows.yaml @@ -0,0 +1,13 @@ +{{$defaultArgs := dict + "NodeName" "ebs-csi-node" +}} +{{- include "node-windows" (deepCopy $ | mustMerge $defaultArgs) -}} +{{- range $name, $values := .Values.additionalDaemonSets }} +{{$args := dict + "NodeName" (printf "ebs-csi-node-%s" $name) + "Values" (dict + "node" (deepCopy $.Values.node | mustMerge $values) + ) +}} +{{- include "node-windows" (deepCopy $ | mustMerge $args) -}} +{{- end }} diff --git a/backing-services/aws-ebs-csi-driver/templates/node.yaml b/backing-services/aws-ebs-csi-driver/templates/node.yaml new file mode 100644 index 0000000..a891513 --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/node.yaml @@ -0,0 +1,46 @@ +{{$defaultArgs := dict + "NodeName" "ebs-csi-node" +}} +{{- include "node" (deepCopy $ | mustMerge $defaultArgs) -}} +{{- range $name, $values := .Values.additionalDaemonSets }} +{{$args := dict + "NodeName" (printf "ebs-csi-node-%s" $name) + "Values" (dict + "node" (deepCopy $.Values.node | mustMerge $values) + ) +}} +{{- include "node" (deepCopy $ | mustMerge $args) -}} +{{- end }} +{{- if .Values.a1CompatibilityDaemonSet }} +{{$args := dict + "NodeName" "ebs-csi-node-a1compat" + "Values" (dict + "image" (dict + "tag" (printf "%s-a1compat" (default (printf "v%s" .Chart.AppVersion) (.Values.image.tag | toString))) + ) + "node" (dict + "affinity" (dict + "nodeAffinity" (dict + "requiredDuringSchedulingIgnoredDuringExecution" (dict + "nodeSelectorTerms" (list + (dict "matchExpressions" (list + (dict + "key" "eks.amazonaws.com/compute-type" + "operator" "NotIn" + "values" (list "fargate") + ) + (dict + "key" "node.kubernetes.io/instance-type" + "operator" "In" + "values" (list "a1.medium" "a1.large" "a1.xlarge" "a1.2xlarge" "a1.4xlarge") + ) + )) + ) + ) + ) + ) + ) + ) +}} +{{- include "node" (deepCopy $ | mustMerge $args) -}} +{{- end }} diff --git a/backing-services/aws-ebs-csi-driver/templates/poddisruptionbudget-controller.yaml b/backing-services/aws-ebs-csi-driver/templates/poddisruptionbudget-controller.yaml new file mode 100644 index 0000000..0a1e97c --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/poddisruptionbudget-controller.yaml @@ -0,0 +1,17 @@ +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: ebs-csi-controller + namespace: {{ .Release.Namespace }} + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + app: ebs-csi-controller + {{- include "aws-ebs-csi-driver.selectorLabels" . | nindent 6 }} + {{- if le (.Values.controller.replicaCount | int) 2 }} + maxUnavailable: 1 + {{- else }} + minAvailable: 2 + {{- end }} diff --git a/backing-services/aws-ebs-csi-driver/templates/role-leases.yaml b/backing-services/aws-ebs-csi-driver/templates/role-leases.yaml new file mode 100644 index 0000000..1ec62bb --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/role-leases.yaml @@ -0,0 +1,11 @@ +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + namespace: {{ .Release.Namespace }} + name: ebs-csi-leases-role + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} +rules: +- apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["get", "watch", "list", "delete", "update", "create"] diff --git a/backing-services/aws-ebs-csi-driver/templates/rolebinding-leases.yaml b/backing-services/aws-ebs-csi-driver/templates/rolebinding-leases.yaml new file mode 100644 index 0000000..88fded8 --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/rolebinding-leases.yaml @@ -0,0 +1,15 @@ +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: ebs-csi-leases-rolebinding + namespace: {{ .Release.Namespace }} + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} +subjects: +- kind: ServiceAccount + name: {{ .Values.controller.serviceAccount.name }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: Role + name: ebs-csi-leases-role + apiGroup: rbac.authorization.k8s.io diff --git a/backing-services/aws-ebs-csi-driver/templates/serviceaccount-csi-controller.yaml b/backing-services/aws-ebs-csi-driver/templates/serviceaccount-csi-controller.yaml new file mode 100644 index 0000000..d819f54 --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/serviceaccount-csi-controller.yaml @@ -0,0 +1,21 @@ +{{- if .Values.controller.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.controller.serviceAccount.name }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} + {{- with .Values.controller.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if eq .Release.Name "kustomize" }} + #Enable if EKS IAM roles for service accounts (IRSA) is used. See https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html for details. + #annotations: + # eks.amazonaws.com/role-arn: arn::iam:::role/ebs-csi-role + {{- end }} +{{- if .Values.controller.serviceAccount.automountServiceAccountToken }} +automountServiceAccountToken: {{ .Values.controller.serviceAccount.automountServiceAccountToken }} +{{- end }} +{{- end -}} diff --git a/backing-services/aws-ebs-csi-driver/templates/serviceaccount-csi-node.yaml b/backing-services/aws-ebs-csi-driver/templates/serviceaccount-csi-node.yaml new file mode 100644 index 0000000..1182460 --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/serviceaccount-csi-node.yaml @@ -0,0 +1,16 @@ +{{- if .Values.node.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.node.serviceAccount.name }} + namespace: {{ .Values.node.namespaceOverride | default .Release.Namespace }} + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} + {{- with .Values.node.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- if .Values.node.serviceAccount.automountServiceAccountToken }} +automountServiceAccountToken: {{ .Values.node.serviceAccount.automountServiceAccountToken }} +{{- end }} +{{- end -}} diff --git a/backing-services/aws-ebs-csi-driver/templates/storageclass.yaml b/backing-services/aws-ebs-csi-driver/templates/storageclass.yaml new file mode 100644 index 0000000..847f5e2 --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/storageclass.yaml @@ -0,0 +1,15 @@ +{{- range .Values.storageClasses }} +--- +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: {{ .name }} + {{- with .annotations }} + annotations: {{- . | toYaml | trim | nindent 4 }} + {{- end }} + {{- with .labels }} + labels: {{- . | toYaml | trim | nindent 4 }} + {{- end }} +provisioner: ebs.csi.aws.com +{{ omit (dict "volumeBindingMode" "WaitForFirstConsumer" | merge .) "name" "annotations" "labels" | toYaml }} +{{- end }} diff --git a/backing-services/aws-ebs-csi-driver/templates/tests/helm-tester.yaml b/backing-services/aws-ebs-csi-driver/templates/tests/helm-tester.yaml new file mode 100644 index 0000000..08113b7 --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/tests/helm-tester.yaml @@ -0,0 +1,238 @@ +{{- if .Values.helmTester.enabled -}} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: ebs-csi-driver-test + annotations: + "helm.sh/hook": test + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded,hook-failed +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: ebs-csi-driver-test + annotations: + "helm.sh/hook": test + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded,hook-failed +rules: + - apiGroups: [ "" ] + resources: + - events + - nodes + - pods + - replicationcontrollers + - serviceaccounts + - configmaps + - persistentvolumes + - persistentvolumeclaims + verbs: [ "list" ] + - apiGroups: [ "" ] + resources: + - services + - nodes + - nodes/proxy + - persistentvolumes + - persistentvolumeclaims + - pods + - pods/log + verbs: [ "get" ] + - apiGroups: [ "" ] + resources: + - namespaces + - persistentvolumes + - persistentvolumeclaims + - pods + - pods/exec + verbs: [ "create" ] + - apiGroups: [ "" ] + resources: + - namespaces + - persistentvolumes + - persistentvolumeclaims + - pods + verbs: [ "delete" ] + - apiGroups: [ "" ] + resources: + - persistentvolumeclaims + verbs: [ "update" ] + - apiGroups: [ "" ] + resources: + - pods/ephemeralcontainers + verbs: [ "patch" ] + - apiGroups: [ "" ] + resources: + - serviceaccounts + - configmaps + verbs: [ "watch" ] + - apiGroups: [ "apps" ] + resources: + - replicasets + - daemonsets + verbs: [ "list" ] + - apiGroups: [ "storage.k8s.io" ] + resources: + - storageclasses + verbs: [ "create" ] + - apiGroups: [ "storage.k8s.io" ] + resources: + - storageclasses + - csinodes + verbs: [ "get" ] + - apiGroups: [ "storage.k8s.io" ] + resources: + - storageclasses + verbs: [ "delete" ] + - apiGroups: [ "snapshot.storage.k8s.io" ] + resources: + - volumesnapshots + - volumesnapshotclasses + - volumesnapshotcontents + verbs: [ "create" ] + - apiGroups: [ "snapshot.storage.k8s.io" ] + resources: + - volumesnapshots + - volumesnapshotclasses + - volumesnapshotcontents + verbs: [ "get" ] + - apiGroups: [ "snapshot.storage.k8s.io" ] + resources: + - volumesnapshotcontents + verbs: [ "update" ] + - apiGroups: [ "snapshot.storage.k8s.io" ] + resources: + - volumesnapshots + - volumesnapshotclasses + - volumesnapshotcontents + verbs: [ "delete" ] + - apiGroups: [ "authorization.k8s.io" ] + resources: + - clusterroles + verbs: [ "list" ] + - apiGroups: [ "authorization.k8s.io" ] + resources: + - subjectaccessreviews + verbs: [ "create" ] + - apiGroups: [ "rbac.authorization.k8s.io" ] + resources: + - clusterroles + verbs: [ "list" ] + - apiGroups: [ "rbac.authorization.k8s.io" ] + resources: + - clusterrolebindings + verbs: [ "create" ] + - apiGroups: [ "apiextensions.k8s.io" ] + resources: + - customresourcedefinitions + verbs: [ "get" ] +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: ebs-csi-driver-test + annotations: + "helm.sh/hook": test + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded,hook-failed +subjects: + - kind: ServiceAccount + name: ebs-csi-driver-test + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: ebs-csi-driver-test + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: v1 +kind: ConfigMap +data: + manifests.yaml: | + ShortName: ebs + StorageClass: + FromFile: storageclass.yaml + SnapshotClass: + FromName: true + DriverInfo: + Name: ebs.csi.aws.com + SupportedSizeRange: + Min: 1Gi + Max: 16Ti + SupportedFsType: + xfs: {} + ext4: {} + SupportedMountOption: + dirsync: {} + TopologyKeys: ["topology.ebs.csi.aws.com/zone"] + Capabilities: + persistence: true + fsGroup: true + block: true + exec: true + snapshotDataSource: true + pvcDataSource: false + multipods: true + controllerExpansion: true + nodeExpansion: true + volumeLimits: true + topology: true + storageclass.yaml: | + kind: StorageClass + apiVersion: storage.k8s.io/v1 + metadata: + name: ebs.csi.aws.com + provisioner: ebs.csi.aws.com + volumeBindingMode: WaitForFirstConsumer +metadata: + name: ebs-csi-driver-test + annotations: + "helm.sh/hook": test + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded,hook-failed +--- +apiVersion: v1 +kind: Pod +metadata: + name: ebs-csi-driver-test + annotations: + "helm.sh/hook": test + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded,hook-failed + "ignore-check.kube-linter.io/run-as-non-root": "kubetest2 image runs as root" + "ignore-check.kube-linter.io/no-read-only-root-fs": "test pod requires privileged access" +spec: + containers: + - name: kubetest2 + image: {{ .Values.helmTester.image }} + resources: + requests: + cpu: 2000m + memory: 4Gi + limits: + memory: 4Gi + command: [ "/bin/sh", "-c" ] + args: + - | + cp /etc/config/storageclass.yaml /workspace/storageclass.yaml + kubectl config set-cluster cluster --server=https://kubernetes.default --certificate-authority=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt + kubectl config set-context kubetest2 --cluster=cluster + kubectl config set-credentials sa --token=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) + kubectl config set-context kubetest2 --user=sa && kubectl config use-context kubetest2 + export FOCUS_REGEX='\bebs.csi.aws.com\b.+(validate content|resize volume|offline PVC|AllowedTopologies|store data' + if kubectl get crd volumesnapshots.snapshot.storage.k8s.io; then + FOCUS_REGEX="${FOCUS_REGEX}|snapshot fields)" + else + FOCUS_REGEX="${FOCUS_REGEX})" + fi + export KUBE_VERSION=$(kubectl version --output json | jq -r '.serverVersion.major + "." + .serverVersion.minor') + kubetest2 noop --run-id='e2e-kubernetes' --test=ginkgo -- --test-package-version="$(curl -L https://dl.k8s.io/release/stable-${KUBE_VERSION}.txt)" --skip-regex='[Disruptive]|[Serial]' --focus-regex="$FOCUS_REGEX" --parallel=25 --test-args='-storage.testdriver=/etc/config/manifests.yaml' + volumeMounts: + - name: config-vol + mountPath: /etc/config + # kubekins-e2e v1 image is linux amd64 only. + nodeSelector: + kubernetes.io/os: linux + kubernetes.io/arch: amd64 + serviceAccountName: ebs-csi-driver-test + volumes: + - name: config-vol + configMap: + name: ebs-csi-driver-test + restartPolicy: Never +{{- end }} diff --git a/backing-services/aws-ebs-csi-driver/templates/volumesnapshotclass.yaml b/backing-services/aws-ebs-csi-driver/templates/volumesnapshotclass.yaml new file mode 100644 index 0000000..08e0084 --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/templates/volumesnapshotclass.yaml @@ -0,0 +1,20 @@ +{{- if or .Values.sidecars.snapshotter.forceEnable (.Capabilities.APIVersions.Has "snapshot.storage.k8s.io/v1beta1") (.Capabilities.APIVersions.Has "snapshot.storage.k8s.io/v1") }} +{{- range .Values.volumeSnapshotClasses }} +--- +kind: VolumeSnapshotClass +apiVersion: snapshot.storage.k8s.io/v1 +metadata: + name: {{ .name }} + {{- with .annotations }} + annotations: {{- . | toYaml | trim | nindent 4 }} + {{- end }} + {{- with .labels }} + labels: {{- . | toYaml | trim | nindent 4 }} + {{- end }} +driver: ebs.csi.aws.com +deletionPolicy: {{ .deletionPolicy }} +{{- with .parameters }} +parameters: {{- . | toYaml | trim | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/aws-ebs-csi-driver/values.yaml b/backing-services/aws-ebs-csi-driver/values.yaml new file mode 100644 index 0000000..6b7216f --- /dev/null +++ b/backing-services/aws-ebs-csi-driver/values.yaml @@ -0,0 +1,482 @@ +# Default values for aws-ebs-csi-driver. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +image: + repository: public.ecr.aws/ebs-csi-driver/aws-ebs-csi-driver + # Overrides the image tag whose default is v{{ .Chart.AppVersion }} + tag: "" + pullPolicy: IfNotPresent +# -- Custom labels to add into metadata +customLabels: {} +# k8s-app: aws-ebs-csi-driver + +sidecars: + provisioner: + env: [] + image: + pullPolicy: IfNotPresent + repository: public.ecr.aws/eks-distro/kubernetes-csi/external-provisioner + tag: "v5.0.1-eks-1-30-8" + logLevel: 2 + # Additional parameters provided by external-provisioner. + additionalArgs: [] + # Grant additional permissions to external-provisioner + additionalClusterRoleRules: + resources: {} + # Tune leader lease election for csi-provisioner. + # Leader election is on by default. + leaderElection: + enabled: true + # Optional values to tune lease behavior. + # The arguments provided must be in an acceptable time.ParseDuration format. + # Ref: https://pkg.go.dev/flag#Duration + # leaseDuration: "15s" + # renewDeadline: "10s" + # retryPeriod: "5s" + securityContext: + seccompProfile: + type: RuntimeDefault + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + attacher: + env: [] + image: + pullPolicy: IfNotPresent + repository: public.ecr.aws/eks-distro/kubernetes-csi/external-attacher + tag: "v4.6.1-eks-1-30-8" + # Tune leader lease election for csi-attacher. + # Leader election is on by default. + leaderElection: + enabled: true + # Optional values to tune lease behavior. + # The arguments provided must be in an acceptable time.ParseDuration format. + # Ref: https://pkg.go.dev/flag#Duration + # leaseDuration: "15s" + # renewDeadline: "10s" + # retryPeriod: "5s" + logLevel: 2 + # Additional parameters provided by external-attacher. + additionalArgs: [] + # Grant additional permissions to external-attacher + additionalClusterRoleRules: [] + resources: {} + securityContext: + seccompProfile: + type: RuntimeDefault + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + snapshotter: + # Enables the snapshotter sidecar even if the snapshot CRDs are not installed + forceEnable: false + env: [] + image: + pullPolicy: IfNotPresent + repository: public.ecr.aws/eks-distro/kubernetes-csi/external-snapshotter/csi-snapshotter + tag: "v8.0.1-eks-1-30-8" + logLevel: 2 + # Additional parameters provided by csi-snapshotter. + additionalArgs: [] + # Grant additional permissions to csi-snapshotter + additionalClusterRoleRules: [] + resources: {} + securityContext: + seccompProfile: + type: RuntimeDefault + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + livenessProbe: + image: + pullPolicy: IfNotPresent + repository: public.ecr.aws/eks-distro/kubernetes-csi/livenessprobe + tag: "v2.13.0-eks-1-30-8" + # Additional parameters provided by livenessprobe. + additionalArgs: [] + resources: {} + securityContext: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + resizer: + env: [] + image: + pullPolicy: IfNotPresent + repository: public.ecr.aws/eks-distro/kubernetes-csi/external-resizer + tag: "v1.11.1-eks-1-30-8" + # Tune leader lease election for csi-resizer. + # Leader election is on by default. + leaderElection: + enabled: true + # Optional values to tune lease behavior. + # The arguments provided must be in an acceptable time.ParseDuration format. + # Ref: https://pkg.go.dev/flag#Duration + # leaseDuration: "15s" + # renewDeadline: "10s" + # retryPeriod: "5s" + logLevel: 2 + # Additional parameters provided by external-resizer. + additionalArgs: [] + # Grant additional permissions to external-resizer + additionalClusterRoleRules: [] + resources: {} + securityContext: + seccompProfile: + type: RuntimeDefault + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + nodeDriverRegistrar: + env: [] + image: + pullPolicy: IfNotPresent + repository: public.ecr.aws/eks-distro/kubernetes-csi/node-driver-registrar + tag: "v2.11.0-eks-1-30-8" + logLevel: 2 + # Additional parameters provided by node-driver-registrar. + additionalArgs: [] + resources: {} + securityContext: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + livenessProbe: + exec: + command: + - /csi-node-driver-registrar + - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) + - --mode=kubelet-registration-probe + initialDelaySeconds: 30 + periodSeconds: 90 + timeoutSeconds: 15 + volumemodifier: + env: [] + image: + pullPolicy: IfNotPresent + repository: public.ecr.aws/ebs-csi-driver/volume-modifier-for-k8s + tag: "v0.3.0" + leaderElection: + enabled: true + # Optional values to tune lease behavior. + # The arguments provided must be in an acceptable time.ParseDuration format. + # Ref: https://pkg.go.dev/flag#Duration + # leaseDuration: "15s" + # renewDeadline: "10s" + # retryPeriod: "5s" + logLevel: 2 + # Additional parameters provided by volume-modifier-for-k8s. + additionalArgs: [] + resources: {} + securityContext: + seccompProfile: + type: RuntimeDefault + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false +proxy: + http_proxy: + no_proxy: +imagePullSecrets: [] +nameOverride: +fullnameOverride: +awsAccessSecret: + name: aws-secret + keyId: key_id + accessKey: access_key +controller: + batching: true + volumeModificationFeature: + enabled: false + # Additional parameters provided by aws-ebs-csi-driver controller. + additionalArgs: [] + sdkDebugLog: false + loggingFormat: text + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 + preference: + matchExpressions: + - key: eks.amazonaws.com/compute-type + operator: NotIn + values: + - fargate + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - ebs-csi-controller + topologyKey: kubernetes.io/hostname + weight: 100 + # The default filesystem type of the volume to provision when fstype is unspecified in the StorageClass. + # If the default is not set and fstype is unset in the StorageClass, then no fstype will be set + defaultFsType: ext4 + env: [] + # Use envFrom to reference ConfigMaps and Secrets across all containers in the deployment + envFrom: [] + # If set, add pv/pvc metadata to plugin create requests as parameters. + extraCreateMetadata: true + # Extra volume tags to attach to each dynamically provisioned volume. + # --- + # extraVolumeTags: + # key1: value1 + # key2: value2 + extraVolumeTags: {} + httpEndpoint: + # (deprecated) The TCP network address where the prometheus metrics endpoint + # will run (example: `:8080` which corresponds to port 8080 on local host). + # The default is empty string, which means metrics endpoint is disabled. + # --- + enableMetrics: false + serviceMonitor: + # Enables the ServiceMonitor resource even if the prometheus-operator CRDs are not installed + forceEnable: false + # Additional labels for ServiceMonitor object + labels: + release: prometheus + interval: "15s" + # If set to true, AWS API call metrics will be exported to the following + # TCP endpoint: "0.0.0.0:3301" + # --- + # ID of the Kubernetes cluster used for tagging provisioned EBS volumes (optional). + k8sTagClusterId: + logLevel: 2 + userAgentExtra: "helm" + nodeSelector: {} + deploymentAnnotations: {} + podAnnotations: {} + podLabels: {} + priorityClassName: system-cluster-critical + # AWS region to use. If not specified then the region will be looked up via the AWS EC2 metadata + # service. + # --- + # region: us-east-1 + region: + replicaCount: 2 + revisionHistoryLimit: 10 + socketDirVolume: + emptyDir: {} + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + # type: RollingUpdate + # rollingUpdate: + # maxSurge: 0 + # maxUnavailable: 1 + resources: + requests: + cpu: 10m + memory: 40Mi + limits: + memory: 256Mi + serviceAccount: + # A service account will be created for you if set to true. Set to false if you want to use your own. + create: true + name: ebs-csi-controller-sa + annotations: {} + ## Enable if EKS IAM for SA is used + # eks.amazonaws.com/role-arn: arn::iam:::role/ebs-csi-role + automountServiceAccountToken: true + tolerations: + - key: CriticalAddonsOnly + operator: Exists + - effect: NoExecute + operator: Exists + tolerationSeconds: 300 + # TSCs without the label selector stanza + # + # Example: + # + # topologySpreadConstraints: + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: ScheduleAnyway + # - maxSkew: 1 + # topologyKey: kubernetes.io/hostname + # whenUnsatisfiable: ScheduleAnyway + topologySpreadConstraints: [] + # securityContext on the controller pod + securityContext: + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + # Add additional volume mounts on the controller with controller.volumes and controller.volumeMounts + volumes: [] + # Add additional volumes to be mounted onto the controller: + # - name: custom-dir + # hostPath: + # path: /path/to/dir + # type: Directory + volumeMounts: [] + # And add mount paths for those additional volumes: + # - name: custom-dir + # mountPath: /mount/path + # --- + # securityContext on the controller container (see sidecars for securityContext on sidecar containers) + containerSecurityContext: + seccompProfile: + type: RuntimeDefault + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + initContainers: [] + # containers to be run before the controller's container starts. + # + # Example: + # + # - name: wait + # image: busybox + # command: [ 'sh', '-c', "sleep 20" ] + # Enable opentelemetry tracing for the plugin running on the daemonset + otelTracing: {} + # otelServiceName: ebs-csi-controller + # otelExporterEndpoint: "http://localhost:4317" + + # Enable dnsConfig for the controller and node pods + dnsConfig: {} +node: + env: [] + envFrom: [] + kubeletPath: /var/lib/kubelet + loggingFormat: text + logLevel: 2 + priorityClassName: + additionalArgs: [] + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: eks.amazonaws.com/compute-type + operator: NotIn + values: + - fargate + - key: node.kubernetes.io/instance-type + operator: NotIn + values: + - a1.medium + - a1.large + - a1.xlarge + - a1.2xlarge + - a1.4xlarge + nodeSelector: {} + daemonSetAnnotations: {} + podAnnotations: {} + podLabels: {} + terminationGracePeriodSeconds: 30 + tolerateAllTaints: true + tolerations: + - operator: Exists + effect: NoExecute + tolerationSeconds: 300 + resources: + requests: + cpu: 10m + memory: 40Mi + limits: + memory: 256Mi + revisionHistoryLimit: 10 + probeDirVolume: + emptyDir: {} + serviceAccount: + create: true + name: ebs-csi-node-sa + annotations: {} + ## Enable if EKS IAM for SA is used + # eks.amazonaws.com/role-arn: arn::iam:::role/ebs-csi-role + automountServiceAccountToken: true + # Enable the linux daemonset creation + enableLinux: true + enableWindows: false + # The number of attachment slots to reserve for system use (and not to be used for CSI volumes) + # When this parameter is not specified (or set to -1), the EBS CSI Driver will attempt to determine the number of reserved slots via heuristic + # Cannot be specified at the same time as `node.volumeAttachLimit` + reservedVolumeAttachments: + # The "maximum number of attachable volumes" per node + # Cannot be specified at the same time as `node.reservedVolumeAttachments` + volumeAttachLimit: + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: "10%" + hostNetwork: false + # securityContext on the node pod + securityContext: + # The node pod must be run as root to bind to the registration/driver sockets + runAsNonRoot: false + runAsUser: 0 + runAsGroup: 0 + fsGroup: 0 + # allows you to deploy aws-ebs-csi-node daemonset to separate namespace (make sure namespace exists before deploy) + namespaceOverride: "" + # Add additional volume mounts on the node pods with node.volumes and node.volumeMounts + volumes: [] + # Add additional volumes to be mounted onto the node pods: + # - name: custom-dir + # hostPath: + # path: /path/to/dir + # type: Directory + volumeMounts: [] + # And add mount paths for those additional volumes: + # - name: custom-dir + # mountPath: /mount/path + # --- + # securityContext on the node container (see sidecars for securityContext on sidecar containers) + # Privileged containers always run as `Unconfined`, which means that they are not restricted by a seccomp profile. + containerSecurityContext: + readOnlyRootFilesystem: true + privileged: true + # Enable opentelemetry tracing for the plugin running on the daemonset + otelTracing: {} + # otelServiceName: ebs-csi-node + # otelExporterEndpoint: "http://localhost:4317" +additionalDaemonSets: +# Additional node DaemonSets, using the node config structure +# See docs/additional-daemonsets.md for more information +# +# example: +# nodeSelector: +# node.kubernetes.io/instance-type: c5.large +# volumeAttachLimit: 15 + +# Enable compatibility for the A1 instance family via use of an AL2-based image in a separate DaemonSet +# a1CompatibilityDaemonSet: true +storageClasses: [] +# Add StorageClass resources like: +# - name: ebs-sc +# # annotation metadata +# annotations: +# storageclass.kubernetes.io/is-default-class: "true" +# # label metadata +# labels: +# my-label-is: supercool +# # defaults to WaitForFirstConsumer +# volumeBindingMode: WaitForFirstConsumer +# # defaults to Delete +# reclaimPolicy: Retain +# parameters: +# encrypted: "true" + +defaultStorageClass: + enabled: false +volumeSnapshotClasses: [] +# Add VolumeSnapshotClass resources like: +# - name: ebs-vsc +# # annotation metadata +# annotations: +# snapshot.storage.kubernetes.io/is-default-class: "true" +# # label metadata +# labels: +# my-label-is: supercool +# # deletionPolicy must be specified +# deletionPolicy: Delete +# parameters: + +# Use old CSIDriver without an fsGroupPolicy set +# Intended for use with older clusters that cannot easily replace the CSIDriver object +# This parameter should always be false for new installations +useOldCSIDriver: false +helmTester: + enabled: true + # Supply a custom image to the ebs-csi-driver-test pod in helm-tester.yaml + image: "gcr.io/k8s-staging-test-infra/kubekins-e2e:v20240611-597c402033-master" diff --git a/backing-services/aws-efs-csi-driver/.helmignore b/backing-services/aws-efs-csi-driver/.helmignore new file mode 100644 index 0000000..50af031 --- /dev/null +++ b/backing-services/aws-efs-csi-driver/.helmignore @@ -0,0 +1,22 @@ +# 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 +.vscode/ diff --git a/backing-services/aws-efs-csi-driver/CHANGELOG.md b/backing-services/aws-efs-csi-driver/CHANGELOG.md new file mode 100644 index 0000000..b83549d --- /dev/null +++ b/backing-services/aws-efs-csi-driver/CHANGELOG.md @@ -0,0 +1,245 @@ +# Helm chart +# v3.1.5 +* Bump app/driver version to `v2.1.4` +# v3.1.4 +* Bump app/driver version to `v2.1.3` +# v3.1.3 +* Bump app/driver version to `v2.1.2` +# v3.1.2 +* Bump app/driver version to `v2.1.1` +# v3.1.1 +* Bump app/driver version to `v2.1.0` +# v3.1.0 +* Bump app/driver version to `v2.0.9` +# v3.0.9 +* Bump app/driver version to `v2.0.8` +# v3.0.8 +* Bump app/driver version to `v2.0.7` +# v3.0.7 +* Bump app/driver version to `v2.0.6` +# v3.0.6 +* Bump app/driver version to `v2.0.5` +# v3.0.5 +* Bump app/driver version to `v2.0.4` +# v3.0.4 +* Bump app/driver version to `v2.0.3` +# v3.0.3 +* Bump app/driver version to `v2.0.2` +# v3.0.2 +* Update Helm to use the image from Public ECR rather than DockerHub +# v3.0.1 +* Bump app/driver version to `v2.0.1` +# v3.0.0 +* Bump app/driver version to `v2.0.0` +# v2.5.7 +* Bump app/driver version to `v1.7.7` +# v2.5.6 +* Bump app/driver version to `v1.7.6` +# v2.5.5 +* Bump app/driver version to `v1.7.5` +# v2.5.4 +* Bump app/driver version to `v1.7.4` +# v2.5.3 +* Bump app/driver version to `v1.7.3` +# v2.5.2 +* Bump app/driver version to `v1.7.2` +# v2.5.1 +* Bump app/driver version to `v1.7.1` +# v2.5.0 +* Bump app/driver version to `v1.7.0` +# v2.4.9 +* Bump app/driver version to `v1.6.0` +# v2.4.8 +* Bump app/driver version to `v1.5.9` +# v2.4.7 +* Bump app/driver version to `v1.5.8` +# v2.4.6 +* Bump app/driver version to `v1.5.7` +# v2.4.5 +* Bump helm version for change of state-dir path to avoid losing track of state files which exists already to `v2.4.5` +# v2.4.4 +* Bump helm version to pick the latest side-car images `v2.4.4` +# v2.4.3 +* Bump app/driver version to `v1.5.6` +# v2.4.2 +* Bump app/driver version to `v1.5.5` +# v2.4.1 +* Bump app/driver version to `v1.5.4` +# v2.4.0 +* Bump app/driver version to `v1.5.3` +# v2.3.9 +* Bump app/driver version to `v1.5.2` +# v2.3.8 +* Bump app/driver version to `v1.5.1` +# v2.3.7 +* Bump app/driver version to `v1.5.0` +# v2.3.6 +* Bump app/driver version to `v1.4.9` +# v2.3.5 +* Bump app/driver version to `v1.4.8` + +# v2.3.4 +* Bump app/driver version to `v1.4.7` + +# v2.3.3 +* Bump app/driver version to `v1.4.6` + +# v2.3.2 +* Bump app/driver version to `v1.4.5` + +# v2.3.1 +* Bump app/driver version to `v1.4.4` + +# v2.3.0 +* Bump app/driver version to `v1.4.3` + +# v2.2.9 +* Bump app/driver version to `v1.4.2` + +# v2.2.8 +* Bump app/driver version to `v1.4.1` + +# v2.2.7 +* Bump app/driver version to `v1.4.0` +# v2.2.6 +* Bump app/driver version to `v1.3.8` + +# v2.2.5 +* Bump app/driver version to `v1.3.7` + +# v2.2.4 +* Add STS regional endpoints flag to fix PV creation on private EKS + +# v2.2.3 +* Bump app/driver version to `v1.3.6` + +# v2.2.2 +* Add controller.volMetricsOptIn for emitting volume metrics +* Update ECR sidecars to 1-18-13 + +# v2.2.1 +* Bump app/driver version to `v1.3.5` + +# v2.2.0 +* Allow health ports to be configured +* Add Missing "patch" permission for "events" + +# v2.1.6 +* Bump app/driver version to `v1.3.4` + +# v2.1.5 +* Bump app/driver version to `v1.3.3` + +# v2.1.4 +* Add node.serviceAccount values for creating and/or specifying daemonset service account + +# v2.1.3 +* Bump app/driver version to `v1.3.2` + +# v2.1.2 +* Add extra-create-metadata + +# v2.1.1 +* Update app/driver version to `v1.3.1` + +# v2.1.0 + +## New features +* Update app/driver version to `v1.3.0` + +## Bug fixes +* Put comments back in place inside the values file ([#475](https://github.com/kubernetes-sigs/aws-efs-csi-driver/pull/475), [@pierluigilenoci](https://github.com/pierluigilenoci)) + +# v2.0.1 + +## Bug fixes +* Helm chart: fix reclaimPolicy and volumeBindingMode ([#464](https://github.com/kubernetes-sigs/aws-efs-csi-driver/pull/464), [@devinsmith911](https://github.com/devinsmith911)) + + +# v2.0.0 + +## Breaking changes + +Multiple changes in values file at `sidecars`, `controller` and `node` + +--- +```yaml +sidecars: + xxxxxxxxx: + repository: + tag: +``` + +Moving to + +```yaml +sidecars: + xxxxxxxxx: + image: + repository: + tag: +``` + +--- +```yaml +podAnnotations: +resources: +nodeSelector: +tolerations: +affinity: +``` + +Moving to + +```yaml +controller: + podAnnotations: + resources: + nodeSelector: + tolerations: + affinity: +``` + +--- +```yaml +hostAliases: +dnsPolicy: +dnsConfig: +``` + +Moving to + +```yaml +node: + hostAliases: + dnsPolicy: + dnsConfig: +``` + +--- +```yaml +serviceAccount: + controller: +``` + +Moving to + +```yaml +controller: + serviceAccount: +``` + +## New features + +* Chart API `v2` (requires Helm 3) +* Set `resources` and `imagePullPolicy` fields independently for containers +* Set `logLevel`, `affinity`, `nodeSelector`, `podAnnotations` and `tolerations` fields independently +for Controller deployment and Node daemonset +* Set `reclaimPolicy` and `volumeBindingMode` fields in storage class + +## Fixes + +* Fixing Controller deployment using `podAnnotations` and `tolerations` values from Node daemonset +* Let the user define the whole `tolerations` array, default to `- operator: Exists` +* Default `logLevel` lowered from `5` to `2` +* Default `imagePullPolicy` everywhere set to `IfNotPresent` \ No newline at end of file diff --git a/backing-services/aws-efs-csi-driver/Chart.yaml b/backing-services/aws-efs-csi-driver/Chart.yaml new file mode 100644 index 0000000..163c703 --- /dev/null +++ b/backing-services/aws-efs-csi-driver/Chart.yaml @@ -0,0 +1,18 @@ +apiVersion: v2 +appVersion: 2.1.4 +description: A Helm chart for AWS EFS CSI Driver +home: https://github.com/kubernetes-sigs/aws-efs-csi-driver +keywords: +- aws +- efs +- csi +kubeVersion: '>=1.17.0-0' +maintainers: +- name: leakingtapan + url: https://github.com/leakingtapan +- name: krmichel + url: https://github.com/krmichel +name: aws-efs-csi-driver +sources: +- https://github.com/kubernetes-sigs/aws-efs-csi-driver +version: 3.1.5 diff --git a/backing-services/aws-efs-csi-driver/auction-stage-eks.values.yaml b/backing-services/aws-efs-csi-driver/auction-stage-eks.values.yaml new file mode 100644 index 0000000..52521cd --- /dev/null +++ b/backing-services/aws-efs-csi-driver/auction-stage-eks.values.yaml @@ -0,0 +1,28 @@ +controller: + serviceAccount: + create: true + name: efs-csi-node-sa + +node: + # Specifies whether a service account should be created + serviceAccount: + create: true + name: efs-csi-node-sa + annotations: + ## Enable if EKS IAM for SA is used + eks.amazonaws.com/role-arn: "arn:aws:iam::667294666490:role/auction-cluster-20241126163757775000000001" + +storageClasses: +- name: efs-sc + annotations: + storageclass.kubernetes.io/is-default-class: "true" + mountOptions: + - tls + parameters: + provisioningMode: efs-ap + fileSystemId: fs-09f60032cda93f18a + directoryPerms: "700" + gidRangeStart: "1000" + gidRangeEnd: "2000" + reclaimPolicy: Delete + volumeBindingMode: Immediate diff --git a/backing-services/aws-efs-csi-driver/school-stage-eks.values.yaml b/backing-services/aws-efs-csi-driver/school-stage-eks.values.yaml new file mode 100644 index 0000000..2249290 --- /dev/null +++ b/backing-services/aws-efs-csi-driver/school-stage-eks.values.yaml @@ -0,0 +1,28 @@ +controller: + serviceAccount: + create: true + name: efs-csi-node-sa + +node: + # Specifies whether a service account should be created + serviceAccount: + create: true + name: efs-csi-node-sa + annotations: + ## Enable if EKS IAM for SA is used + eks.amazonaws.com/role-arn: "arn:aws:iam::889565812003:role/schoolbuses-cluster-20241110104436981500000002" + +storageClasses: +- name: efs-sc + annotations: + storageclass.kubernetes.io/is-default-class: "true" + mountOptions: + - tls + parameters: + provisioningMode: efs-ap + fileSystemId: fs-0a434a5de93866ab1 + directoryPerms: "700" + gidRangeStart: "1000" + gidRangeEnd: "2000" + reclaimPolicy: Delete + volumeBindingMode: Immediate diff --git a/backing-services/aws-efs-csi-driver/schoolbuses.values.yaml b/backing-services/aws-efs-csi-driver/schoolbuses.values.yaml new file mode 100644 index 0000000..38d9c6a --- /dev/null +++ b/backing-services/aws-efs-csi-driver/schoolbuses.values.yaml @@ -0,0 +1,28 @@ +controller: + serviceAccount: + create: true + name: efs-csi-controller-sa + +node: + # Specifies whether a service account should be created + serviceAccount: + create: true + name: efs-csi-node-sa + annotations: + ## Enable if EKS IAM for SA is used + eks.amazonaws.com/role-arn: arn:aws:iam::889565812003:role/schoolbuses_Cluster_IAM + +storageClasses: +- name: efs-sc + annotations: + storageclass.kubernetes.io/is-default-class: "true" + mountOptions: + - tls + parameters: + provisioningMode: efs-ap + fileSystemId: fs-08694c721b539abe2 + directoryPerms: "700" + gidRangeStart: "1000" + gidRangeEnd: "2000" + reclaimPolicy: Delete + volumeBindingMode: Immediate diff --git a/backing-services/aws-efs-csi-driver/templates/NOTES.txt b/backing-services/aws-efs-csi-driver/templates/NOTES.txt new file mode 100644 index 0000000..66f4d12 --- /dev/null +++ b/backing-services/aws-efs-csi-driver/templates/NOTES.txt @@ -0,0 +1,3 @@ +To verify that aws-efs-csi-driver has started, run: + + kubectl get pod -n {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "aws-efs-csi-driver.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" diff --git a/backing-services/aws-efs-csi-driver/templates/_helpers.tpl b/backing-services/aws-efs-csi-driver/templates/_helpers.tpl new file mode 100644 index 0000000..ab6b4e0 --- /dev/null +++ b/backing-services/aws-efs-csi-driver/templates/_helpers.tpl @@ -0,0 +1,56 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "aws-efs-csi-driver.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "aws-efs-csi-driver.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "aws-efs-csi-driver.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "aws-efs-csi-driver.labels" -}} +app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} +helm.sh/chart: {{ include "aws-efs-csi-driver.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Create a string out of the map for controller tags flag +*/}} +{{- define "aws-efs-csi-driver.tags" -}} +{{- $tags := list -}} +{{ range $key, $val := . }} +{{- $tags = print $key ":" $val | append $tags -}} +{{- end -}} +{{- join " " $tags -}} +{{- end -}} diff --git a/backing-services/aws-efs-csi-driver/templates/controller-deployment.yaml b/backing-services/aws-efs-csi-driver/templates/controller-deployment.yaml new file mode 100644 index 0000000..4753b16 --- /dev/null +++ b/backing-services/aws-efs-csi-driver/templates/controller-deployment.yaml @@ -0,0 +1,193 @@ +{{- if .Values.controller.create }} +# Controller Service +kind: Deployment +apiVersion: apps/v1 +metadata: + name: {{ .Values.controller.name }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} + {{- with .Values.controller.additionalLabels }} + {{ toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.controller.replicaCount }} + selector: + matchLabels: + app: {{ .Values.controller.name }} + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + {{- with .Values.controller.updateStrategy }} + strategy: + {{ toYaml . | nindent 4 }} + {{- end }} + template: + metadata: + labels: + app: {{ .Values.controller.name }} + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + {{- with .Values.controller.podLabels }} + {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.podAnnotations }} + annotations: {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if hasKey .Values.controller "hostNetwork" }} + hostNetwork: {{ .Values.controller.hostNetwork }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- range .Values.imagePullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} + nodeSelector: + kubernetes.io/os: linux + {{- with .Values.controller.nodeSelector }} + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ .Values.controller.serviceAccount.name }} + priorityClassName: {{ .Values.controller.priorityClassName | default "system-cluster-critical" }} + {{- with .Values.controller.tolerations }} + tolerations: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.controller.dnsPolicy }} + dnsPolicy: {{ .Values.controller.dnsPolicy }} + {{- end }} + {{- with .Values.controller.dnsConfig }} + dnsConfig: {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: efs-plugin + {{- with .Values.controller.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + image: {{ printf "%s:%s" .Values.image.repository (default (printf "v%s" .Chart.AppVersion) (toString .Values.image.tag)) }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - --endpoint=$(CSI_ENDPOINT) + - --logtostderr + {{- if .Values.controller.tags }} + - --tags={{ include "aws-efs-csi-driver.tags" .Values.controller.tags }} + {{- end }} + - --v={{ .Values.controller.logLevel }} + - --delete-access-point-root-dir={{ hasKey .Values.controller "deleteAccessPointRootDir" | ternary .Values.controller.deleteAccessPointRootDir false }} + env: + - name: CSI_ENDPOINT + value: unix:///var/lib/csi/sockets/pluginproxy/csi.sock + {{- if .Values.controller.regionalStsEndpoints }} + - name: AWS_STS_REGIONAL_ENDPOINTS + value: regional + {{- end }} + - name: CSI_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + {{- if .Values.useFIPS }} + - name: AWS_USE_FIPS_ENDPOINT + value: "true" + {{- end }} + - name: PORT_RANGE_UPPER_BOUND + value: "{{ .Values.portRangeUpperBound }}" + {{- with .Values.controller.env }} + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: socket-dir + mountPath: /var/lib/csi/sockets/pluginproxy/ + {{- with .Values.controller.volumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: healthz + containerPort: {{ .Values.controller.healthPort }} + protocol: TCP + livenessProbe: + httpGet: + path: /healthz + port: healthz + initialDelaySeconds: 10 + timeoutSeconds: 3 + periodSeconds: 10 + failureThreshold: 5 + {{- with .Values.controller.resources }} + resources: {{ toYaml . | nindent 12 }} + {{- end }} + - name: csi-provisioner + image: {{ printf "%s:%s" .Values.sidecars.csiProvisioner.image.repository .Values.sidecars.csiProvisioner.image.tag }} + imagePullPolicy: {{ .Values.sidecars.csiProvisioner.image.pullPolicy }} + args: + - --csi-address=$(ADDRESS) + - --v={{ .Values.controller.logLevel }} + - --feature-gates=Topology=true + {{- if .Values.controller.extraCreateMetadata }} + - --extra-create-metadata + {{- end }} + - --leader-election + {{- if hasKey .Values.controller "leaderElectionRenewDeadline" }} + - --leader-election-renew-deadline={{ .Values.controller.leaderElectionRenewDeadline }} + {{- end }} + {{- if hasKey .Values.controller "leaderElectionLeaseDuration" }} + - --leader-election-lease-duration={{ .Values.controller.leaderElectionLeaseDuration }} + {{- end }} + {{- range .Values.sidecars.csiProvisioner.additionalArgs }} + - {{ . }} + {{- end }} + env: + - name: ADDRESS + value: /var/lib/csi/sockets/pluginproxy/csi.sock + volumeMounts: + - name: socket-dir + mountPath: /var/lib/csi/sockets/pluginproxy/ + {{- with default .Values.controller.resources .Values.sidecars.csiProvisioner.resources }} + resources: {{ toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.csiProvisioner.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + - name: liveness-probe + image: {{ printf "%s:%s" .Values.sidecars.livenessProbe.image.repository .Values.sidecars.livenessProbe.image.tag }} + imagePullPolicy: {{ .Values.sidecars.livenessProbe.image.pullPolicy }} + args: + - --csi-address=/csi/csi.sock + - --health-port={{ .Values.controller.healthPort }} + volumeMounts: + - name: socket-dir + mountPath: /csi + {{- with .Values.controller.volumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with default .Values.controller.resources .Values.sidecars.livenessProbe.resources }} + resources: {{ toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.livenessProbe.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + volumes: + - name: socket-dir + emptyDir: {} + {{- with .Values.controller.volumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.affinity }} + affinity: {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.controller.topologySpreadConstraints }} + {{- $tscLabelSelector := dict "labelSelector" ( dict "matchLabels" ( dict "app" "efs-csi-controller" ) ) }} + {{- $constraints := list }} + {{- range .Values.controller.topologySpreadConstraints }} + {{- $constraints = mustAppend $constraints (mergeOverwrite . $tscLabelSelector) }} + {{- end }} + topologySpreadConstraints: + {{- $constraints | toYaml | nindent 8 }} + {{- end }} +{{- end }} diff --git a/backing-services/aws-efs-csi-driver/templates/controller-pdb.yaml b/backing-services/aws-efs-csi-driver/templates/controller-pdb.yaml new file mode 100644 index 0000000..43d5e69 --- /dev/null +++ b/backing-services/aws-efs-csi-driver/templates/controller-pdb.yaml @@ -0,0 +1,24 @@ +{{- if .Values.controller.podDisruptionBudget.enabled -}} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ .Values.controller.name }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "aws-efs-csi-driver.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + app: {{ .Values.controller.name }} + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + {{- if .Values.controller.podDisruptionBudget.unhealthyPodEvictionPolicy }} + unhealthyPodEvictionPolicy: {{ .Values.controller.podDisruptionBudget.unhealthyPodEvictionPolicy }} + {{- end }} + {{- if .Values.controller.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.controller.podDisruptionBudget.maxUnavailable }} + {{- end }} + {{- if .Values.controller.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.controller.podDisruptionBudget.minAvailable }} + {{- end }} +{{- end -}} \ No newline at end of file diff --git a/backing-services/aws-efs-csi-driver/templates/controller-serviceaccount.yaml b/backing-services/aws-efs-csi-driver/templates/controller-serviceaccount.yaml new file mode 100644 index 0000000..1a11330 --- /dev/null +++ b/backing-services/aws-efs-csi-driver/templates/controller-serviceaccount.yaml @@ -0,0 +1,88 @@ +{{- if .Values.controller.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.controller.serviceAccount.name }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} + {{- with .Values.controller.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} +--- + +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: efs-csi-external-provisioner-role + labels: + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} +rules: + - apiGroups: [""] + resources: ["persistentvolumes"] + verbs: ["get", "list", "watch", "create", "patch", "delete"] + - apiGroups: [""] + resources: ["persistentvolumeclaims"] + verbs: ["get", "list", "watch", "update"] + - apiGroups: ["storage.k8s.io"] + resources: ["storageclasses"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["events"] + verbs: ["list", "watch", "create", "patch"] + - apiGroups: ["storage.k8s.io"] + resources: ["csinodes"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch"] + - apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["get", "watch", "list", "delete", "update", "create"] +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: efs-csi-external-provisioner-role-describe-secrets + labels: + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} +rules: + - apiGroups: [ "" ] + resources: [ "secrets" ] + resourceNames: ["x-account"] + verbs: [ "get", "watch", "list" ] +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: efs-csi-provisioner-binding + labels: + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} +subjects: + - kind: ServiceAccount + name: {{ .Values.controller.serviceAccount.name }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: efs-csi-external-provisioner-role + apiGroup: rbac.authorization.k8s.io +--- +# We use a RoleBinding to restrict Secret access to the namespace that the +# RoleBinding is created in (typically kube-system) +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: efs-csi-provisioner-binding-describe-secrets + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} +subjects: + - kind: ServiceAccount + name: {{ .Values.controller.serviceAccount.name }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: efs-csi-external-provisioner-role-describe-secrets + apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/backing-services/aws-efs-csi-driver/templates/csidriver.yaml b/backing-services/aws-efs-csi-driver/templates/csidriver.yaml new file mode 100644 index 0000000..6b68cc1 --- /dev/null +++ b/backing-services/aws-efs-csi-driver/templates/csidriver.yaml @@ -0,0 +1,12 @@ +apiVersion: {{ ternary "storage.k8s.io/v1" "storage.k8s.io/v1beta1" (semverCompare ">=1.18.0-0" .Capabilities.KubeVersion.Version) }} +kind: CSIDriver +metadata: + name: efs.csi.aws.com + annotations: + {{- if .Values.useHelmHooksForCSIDriver }} + "helm.sh/hook": pre-install, pre-upgrade + "helm.sh/hook-delete-policy": before-hook-creation + {{- end }} + "helm.sh/resource-policy": keep +spec: + attachRequired: false diff --git a/backing-services/aws-efs-csi-driver/templates/node-daemonset.yaml b/backing-services/aws-efs-csi-driver/templates/node-daemonset.yaml new file mode 100644 index 0000000..324350c --- /dev/null +++ b/backing-services/aws-efs-csi-driver/templates/node-daemonset.yaml @@ -0,0 +1,202 @@ +# Node Service +kind: DaemonSet +apiVersion: apps/v1 +metadata: + name: efs-csi-node + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} + {{- with .Values.node.additionalLabels }} + {{ toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + app: efs-csi-node + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + {{- with .Values.node.updateStrategy }} + updateStrategy: + {{ toYaml . | nindent 4 }} + {{- end }} + template: + metadata: + labels: + app: efs-csi-node + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + {{- with .Values.node.podLabels }} + {{ toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.node.podAnnotations }} + annotations: {{ toYaml .Values.node.podAnnotations | nindent 8 }} + {{- end }} + spec: + {{- with .Values.node.hostAliases }} + hostAliases: + {{- range $k, $v := . }} + - ip: {{ $v.ip }} + hostnames: + - {{ $k }}.efs.{{ $v.region }}.amazonaws.com + {{- end }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- range .Values.imagePullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} + nodeSelector: + kubernetes.io/os: linux + {{- with .Values.node.nodeSelector }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.node.affinity }} + affinity: {{- toYaml . | nindent 8 }} + {{- end }} + hostNetwork: true + dnsPolicy: {{ .Values.node.dnsPolicy }} + {{- with .Values.node.dnsConfig }} + dnsConfig: {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ .Values.node.serviceAccount.name }} + priorityClassName: {{ .Values.node.priorityClassName}} + {{- with .Values.node.tolerations }} + tolerations: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.node.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: efs-plugin + securityContext: + privileged: true + image: {{ printf "%s:%s" .Values.image.repository (default (printf "v%s" .Chart.AppVersion) (toString .Values.image.tag)) }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - --endpoint=$(CSI_ENDPOINT) + - --logtostderr + - --v={{ .Values.node.logLevel }} + - --vol-metrics-opt-in={{ hasKey .Values.node "volMetricsOptIn" | ternary .Values.node.volMetricsOptIn false }} + - --vol-metrics-refresh-period={{ hasKey .Values.node "volMetricsRefreshPeriod" | ternary .Values.node.volMetricsRefreshPeriod 240 }} + - --vol-metrics-fs-rate-limit={{ hasKey .Values.node "volMetricsFsRateLimit" | ternary .Values.node.volMetricsFsRateLimit 5 }} + env: + - name: CSI_ENDPOINT + value: unix:/csi/csi.sock + - name: CSI_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + {{- if .Values.useFIPS }} + - name: AWS_USE_FIPS_ENDPOINT + value: "true" + {{- end }} + - name: PORT_RANGE_UPPER_BOUND + value: "{{ .Values.portRangeUpperBound }}" + {{- with .Values.node.env }} + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: kubelet-dir + mountPath: {{ .Values.node.kubeletPath }} + mountPropagation: "Bidirectional" + - name: plugin-dir + mountPath: /csi + - name: efs-state-dir + mountPath: /var/run/efs + - name: efs-utils-config + mountPath: /var/amazon/efs + - name: efs-utils-config-legacy + mountPath: /etc/amazon/efs-legacy + {{- with .Values.node.volumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: healthz + containerPort: {{ .Values.node.healthPort }} + protocol: TCP + livenessProbe: + httpGet: + path: /healthz + port: healthz + initialDelaySeconds: 10 + timeoutSeconds: 3 + periodSeconds: 2 + failureThreshold: 5 + {{- with .Values.node.resources }} + resources: {{ toYaml . | nindent 12 }} + {{- end }} + - name: csi-driver-registrar + image: {{ printf "%s:%s" .Values.sidecars.nodeDriverRegistrar.image.repository .Values.sidecars.nodeDriverRegistrar.image.tag }} + imagePullPolicy: {{ .Values.sidecars.nodeDriverRegistrar.image.pullPolicy }} + args: + - --csi-address=$(ADDRESS) + - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) + - --v={{ .Values.node.logLevel }} + env: + - name: ADDRESS + value: /csi/csi.sock + - name: DRIVER_REG_SOCK_PATH + value: {{ printf "%s/plugins/efs.csi.aws.com/csi.sock" (trimSuffix "/" .Values.node.kubeletPath) }} + - name: KUBE_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + volumeMounts: + - name: plugin-dir + mountPath: /csi + - name: registration-dir + mountPath: /registration + {{- with .Values.sidecars.nodeDriverRegistrar.resources }} + resources: {{ toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.nodeDriverRegistrar.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + - name: liveness-probe + image: {{ printf "%s:%s" .Values.sidecars.livenessProbe.image.repository .Values.sidecars.livenessProbe.image.tag }} + imagePullPolicy: {{ .Values.sidecars.livenessProbe.image.pullPolicy }} + args: + - --csi-address=/csi/csi.sock + - --health-port={{ .Values.node.healthPort }} + - --v={{ .Values.node.logLevel }} + volumeMounts: + - name: plugin-dir + mountPath: /csi + {{- with .Values.sidecars.livenessProbe.resources }} + resources: {{ toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.livenessProbe.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + volumes: + - name: kubelet-dir + hostPath: + path: {{ .Values.node.kubeletPath }} + type: Directory + - name: plugin-dir + hostPath: + path: {{ printf "%s/plugins/efs.csi.aws.com/" (trimSuffix "/" .Values.node.kubeletPath) }} + type: DirectoryOrCreate + - name: registration-dir + hostPath: + path: {{ printf "%s/plugins_registry/" (trimSuffix "/" .Values.node.kubeletPath) }} + type: Directory + - name: efs-state-dir + hostPath: + path: /var/run/efs + type: DirectoryOrCreate + - name: efs-utils-config + hostPath: + path: /var/amazon/efs + type: DirectoryOrCreate + - name: efs-utils-config-legacy + hostPath: + path: /etc/amazon/efs + type: DirectoryOrCreate + {{- with .Values.node.volumes }} + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/backing-services/aws-efs-csi-driver/templates/node-serviceaccount.yaml b/backing-services/aws-efs-csi-driver/templates/node-serviceaccount.yaml new file mode 100644 index 0000000..797f1b3 --- /dev/null +++ b/backing-services/aws-efs-csi-driver/templates/node-serviceaccount.yaml @@ -0,0 +1,40 @@ +{{- if .Values.node.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.node.serviceAccount.name }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} + {{- with .Values.node.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: efs-csi-node-role + labels: + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} +rules: + - apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch", "patch"] +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: efs-csi-node-binding + labels: + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} +subjects: + - kind: ServiceAccount + name: {{ .Values.node.serviceAccount.name }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: efs-csi-node-role + apiGroup: rbac.authorization.k8s.io + \ No newline at end of file diff --git a/backing-services/aws-efs-csi-driver/templates/storageclass.yaml b/backing-services/aws-efs-csi-driver/templates/storageclass.yaml new file mode 100644 index 0000000..8ce1ec8 --- /dev/null +++ b/backing-services/aws-efs-csi-driver/templates/storageclass.yaml @@ -0,0 +1,26 @@ +{{- range .Values.storageClasses }} +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: {{ .name }} + {{- with .annotations }} + annotations: + {{ toYaml . | indent 4 }} + {{- end }} +provisioner: efs.csi.aws.com +{{- with .mountOptions }} +mountOptions: +{{ toYaml . }} +{{- end }} +{{- with .parameters }} +parameters: +{{ toYaml . | indent 2 }} +{{- end }} +{{- with .reclaimPolicy }} +reclaimPolicy: {{ . }} +{{- end }} +{{- with .volumeBindingMode }} +volumeBindingMode: {{ . }} +{{- end }} +--- +{{- end }} \ No newline at end of file diff --git a/backing-services/aws-efs-csi-driver/values.yaml b/backing-services/aws-efs-csi-driver/values.yaml new file mode 100644 index 0000000..d47807e --- /dev/null +++ b/backing-services/aws-efs-csi-driver/values.yaml @@ -0,0 +1,237 @@ +# Default values for aws-efs-csi-driver. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +nameOverride: "" +fullnameOverride: "" + +useFIPS: false + +portRangeUpperBound: "21049" + +image: + repository: public.ecr.aws/efs-csi-driver/amazon/aws-efs-csi-driver + tag: "v2.1.4" + pullPolicy: IfNotPresent + +sidecars: + livenessProbe: + image: + repository: public.ecr.aws/eks-distro/kubernetes-csi/livenessprobe + tag: v2.14.0-eks-1-31-5 + pullPolicy: IfNotPresent + resources: {} + securityContext: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + nodeDriverRegistrar: + image: + repository: public.ecr.aws/eks-distro/kubernetes-csi/node-driver-registrar + tag: v2.12.0-eks-1-31-5 + pullPolicy: IfNotPresent + resources: {} + securityContext: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + csiProvisioner: + image: + repository: public.ecr.aws/eks-distro/kubernetes-csi/external-provisioner + tag: v5.1.0-eks-1-31-5 + pullPolicy: IfNotPresent + resources: {} + securityContext: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + additionalArgs: [] + +imagePullSecrets: [] + +## Controller deployment variables + +controller: + # Specifies whether a deployment should be created + create: true + # Name of the CSI controller service + name: efs-csi-controller + # Number of replicas for the CSI controller service deployment + replicaCount: 2 + # Number for the log level verbosity + logLevel: 2 + # If set, add pv/pvc metadata to plugin create requests as parameters. + extraCreateMetadata: true + # Add additional tags to access points + tags: + {} + # environment: prod + # region: us-east-1 + # Enable if you want the controller to also delete the + # path on efs when deleteing an access point + deleteAccessPointRootDir: false + podAnnotations: {} + podLabels: {} + hostNetwork: false + priorityClassName: system-cluster-critical + dnsPolicy: ClusterFirst + dnsConfig: {} + additionalLabels: {} + resources: + {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + nodeSelector: {} + updateStrategy: {} + tolerations: + - key: CriticalAddonsOnly + operator: Exists + - key: efs.csi.aws.com/agent-not-ready + operator: Exists + affinity: {} + env: [] + volumes: [] + volumeMounts: [] + # Specifies whether a service account should be created + serviceAccount: + create: true + name: efs-csi-controller-sa + annotations: {} + ## Enable if EKS IAM for SA is used + # eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/efs-csi-role + healthPort: 9909 + regionalStsEndpoints: false + # Pod Disruption Budget + podDisruptionBudget: + enabled: false + # maxUnavailable: 1 + minAvailable: 1 + unhealthyPodEvictionPolicy: IfHealthyBudget + # securityContext on the controller pod + securityContext: + runAsNonRoot: false + runAsUser: 0 + runAsGroup: 0 + fsGroup: 0 + # securityContext on the controller container + # Setting privileged=false will cause the "delete-access-point-root-dir" controller option to fail + containerSecurityContext: + privileged: true + leaderElectionRenewDeadline: 10s + leaderElectionLeaseDuration: 15s + # TSCs without the label selector stanza + # + # Example: + # + # topologySpreadConstraints: + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: ScheduleAnyway + # - maxSkew: 1 + # topologyKey: kubernetes.io/hostname + # whenUnsatisfiable: ScheduleAnyway + topologySpreadConstraints: [] + +## Node daemonset variables + +node: + # Number for the log level verbosity + logLevel: 2 + volMetricsOptIn: false + volMetricsRefreshPeriod: 240 + volMetricsFsRateLimit: 5 + hostAliases: + {} + # For cross VPC EFS, you need to poison or overwrite the DNS for the efs volume as per + # https://docs.aws.amazon.com/efs/latest/ug/efs-different-vpc.html#wt6-efs-utils-step3 + # implementing the suggested solution found here: + # https://github.com/kubernetes-sigs/aws-efs-csi-driver/issues/240#issuecomment-676849346 + # EFS Vol ID, IP, Region + # "fs-01234567": + # ip: 10.10.2.2 + # region: us-east-2 + priorityClassName: system-node-critical + dnsPolicy: ClusterFirst + dnsConfig: + {} + # Example config which uses the AWS nameservers + # dnsPolicy: "None" + # dnsConfig: + # nameservers: + # - 169.254.169.253 + podLabels: {} + podAnnotations: {} + additionalLabels: {} + resources: + {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + nodeSelector: {} + updateStrategy: + {} + # Override default strategy (RollingUpdate) to speed up deployment. + # This can be useful if helm timeouts are observed. + # type: OnDelete + tolerations: + - operator: Exists + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: eks.amazonaws.com/compute-type + operator: NotIn + values: + - fargate + - hybrid + # Specifies whether a service account should be created + serviceAccount: + create: true + name: efs-csi-node-sa + annotations: {} + ## Enable if EKS IAM for SA is used + # eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/efs-csi-role + healthPort: 9809 + # securityContext on the node pod + securityContext: + # The node pod must be run as root to bind to the registration/driver sockets + runAsNonRoot: false + runAsUser: 0 + runAsGroup: 0 + fsGroup: 0 + env: [] + volumes: [] + volumeMounts: [] + kubeletPath: /var/lib/kubelet + +storageClasses: [] +# Add StorageClass resources like: +# - name: efs-sc +# annotations: +# # Use that annotation if you want this to your default storageclass +# storageclass.kubernetes.io/is-default-class: "true" +# mountOptions: +# - tls +# parameters: +# provisioningMode: efs-ap +# fileSystemId: fs-1122aabb +# directoryPerms: "700" +# gidRangeStart: "1000" +# gidRangeEnd: "2000" +# basePath: "/dynamic_provisioning" +# subPathPattern: "/subPath" +# ensureUniqueDirectory: true +# reclaimPolicy: Delete +# volumeBindingMode: Immediate + +# Specifies wether to use helm hooks to apply the CSI driver +useHelmHooksForCSIDriver: true diff --git a/backing-services/aws-efs-csi-driverOLD/.helmignore b/backing-services/aws-efs-csi-driverOLD/.helmignore new file mode 100644 index 0000000..50af031 --- /dev/null +++ b/backing-services/aws-efs-csi-driverOLD/.helmignore @@ -0,0 +1,22 @@ +# 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 +.vscode/ diff --git a/backing-services/aws-efs-csi-driverOLD/CHANGELOG.md b/backing-services/aws-efs-csi-driverOLD/CHANGELOG.md new file mode 100644 index 0000000..9243c84 --- /dev/null +++ b/backing-services/aws-efs-csi-driverOLD/CHANGELOG.md @@ -0,0 +1,231 @@ +# Helm chart +# v3.0.8 +* Bump app/driver version to `v2.0.7` +# v3.0.7 +* Bump app/driver version to `v2.0.6` +# v3.0.6 +* Bump app/driver version to `v2.0.5` +# v3.0.5 +* Bump app/driver version to `v2.0.4` +# v3.0.4 +* Bump app/driver version to `v2.0.3` +# v3.0.3 +* Bump app/driver version to `v2.0.2` +# v3.0.2 +* Update Helm to use the image from Public ECR rather than DockerHub +# v3.0.1 +* Bump app/driver version to `v2.0.1` +# v3.0.0 +* Bump app/driver version to `v2.0.0` +# v2.5.7 +* Bump app/driver version to `v1.7.7` +# v2.5.6 +* Bump app/driver version to `v1.7.6` +# v2.5.5 +* Bump app/driver version to `v1.7.5` +# v2.5.4 +* Bump app/driver version to `v1.7.4` +# v2.5.3 +* Bump app/driver version to `v1.7.3` +# v2.5.2 +* Bump app/driver version to `v1.7.2` +# v2.5.1 +* Bump app/driver version to `v1.7.1` +# v2.5.0 +* Bump app/driver version to `v1.7.0` +# v2.4.9 +* Bump app/driver version to `v1.6.0` +# v2.4.8 +* Bump app/driver version to `v1.5.9` +# v2.4.7 +* Bump app/driver version to `v1.5.8` +# v2.4.6 +* Bump app/driver version to `v1.5.7` +# v2.4.5 +* Bump helm version for change of state-dir path to avoid losing track of state files which exists already to `v2.4.5` +# v2.4.4 +* Bump helm version to pick the latest side-car images `v2.4.4` +# v2.4.3 +* Bump app/driver version to `v1.5.6` +# v2.4.2 +* Bump app/driver version to `v1.5.5` +# v2.4.1 +* Bump app/driver version to `v1.5.4` +# v2.4.0 +* Bump app/driver version to `v1.5.3` +# v2.3.9 +* Bump app/driver version to `v1.5.2` +# v2.3.8 +* Bump app/driver version to `v1.5.1` +# v2.3.7 +* Bump app/driver version to `v1.5.0` +# v2.3.6 +* Bump app/driver version to `v1.4.9` +# v2.3.5 +* Bump app/driver version to `v1.4.8` + +# v2.3.4 +* Bump app/driver version to `v1.4.7` + +# v2.3.3 +* Bump app/driver version to `v1.4.6` + +# v2.3.2 +* Bump app/driver version to `v1.4.5` + +# v2.3.1 +* Bump app/driver version to `v1.4.4` + +# v2.3.0 +* Bump app/driver version to `v1.4.3` + +# v2.2.9 +* Bump app/driver version to `v1.4.2` + +# v2.2.8 +* Bump app/driver version to `v1.4.1` + +# v2.2.7 +* Bump app/driver version to `v1.4.0` +# v2.2.6 +* Bump app/driver version to `v1.3.8` + +# v2.2.5 +* Bump app/driver version to `v1.3.7` + +# v2.2.4 +* Add STS regional endpoints flag to fix PV creation on private EKS + +# v2.2.3 +* Bump app/driver version to `v1.3.6` + +# v2.2.2 +* Add controller.volMetricsOptIn for emitting volume metrics +* Update ECR sidecars to 1-18-13 + +# v2.2.1 +* Bump app/driver version to `v1.3.5` + +# v2.2.0 +* Allow health ports to be configured +* Add Missing "patch" permission for "events" + +# v2.1.6 +* Bump app/driver version to `v1.3.4` + +# v2.1.5 +* Bump app/driver version to `v1.3.3` + +# v2.1.4 +* Add node.serviceAccount values for creating and/or specifying daemonset service account + +# v2.1.3 +* Bump app/driver version to `v1.3.2` + +# v2.1.2 +* Add extra-create-metadata + +# v2.1.1 +* Update app/driver version to `v1.3.1` + +# v2.1.0 + +## New features +* Update app/driver version to `v1.3.0` + +## Bug fixes +* Put comments back in place inside the values file ([#475](https://github.com/kubernetes-sigs/aws-efs-csi-driver/pull/475), [@pierluigilenoci](https://github.com/pierluigilenoci)) + +# v2.0.1 + +## Bug fixes +* Helm chart: fix reclaimPolicy and volumeBindingMode ([#464](https://github.com/kubernetes-sigs/aws-efs-csi-driver/pull/464), [@devinsmith911](https://github.com/devinsmith911)) + + +# v2.0.0 + +## Breaking changes + +Multiple changes in values file at `sidecars`, `controller` and `node` + +--- +```yaml +sidecars: + xxxxxxxxx: + repository: + tag: +``` + +Moving to + +```yaml +sidecars: + xxxxxxxxx: + image: + repository: + tag: +``` + +--- +```yaml +podAnnotations: +resources: +nodeSelector: +tolerations: +affinity: +``` + +Moving to + +```yaml +controller: + podAnnotations: + resources: + nodeSelector: + tolerations: + affinity: +``` + +--- +```yaml +hostAliases: +dnsPolicy: +dnsConfig: +``` + +Moving to + +```yaml +node: + hostAliases: + dnsPolicy: + dnsConfig: +``` + +--- +```yaml +serviceAccount: + controller: +``` + +Moving to + +```yaml +controller: + serviceAccount: +``` + +## New features + +* Chart API `v2` (requires Helm 3) +* Set `resources` and `imagePullPolicy` fields independently for containers +* Set `logLevel`, `affinity`, `nodeSelector`, `podAnnotations` and `tolerations` fields independently +for Controller deployment and Node daemonset +* Set `reclaimPolicy` and `volumeBindingMode` fields in storage class + +## Fixes + +* Fixing Controller deployment using `podAnnotations` and `tolerations` values from Node daemonset +* Let the user define the whole `tolerations` array, default to `- operator: Exists` +* Default `logLevel` lowered from `5` to `2` +* Default `imagePullPolicy` everywhere set to `IfNotPresent` diff --git a/backing-services/aws-efs-csi-driverOLD/Chart.yaml b/backing-services/aws-efs-csi-driverOLD/Chart.yaml new file mode 100644 index 0000000..06de4d7 --- /dev/null +++ b/backing-services/aws-efs-csi-driverOLD/Chart.yaml @@ -0,0 +1,18 @@ +apiVersion: v2 +appVersion: 2.0.7 +description: A Helm chart for AWS EFS CSI Driver +home: https://github.com/kubernetes-sigs/aws-efs-csi-driver +keywords: +- aws +- efs +- csi +kubeVersion: '>=1.17.0-0' +maintainers: +- name: leakingtapan + url: https://github.com/leakingtapan +- name: krmichel + url: https://github.com/krmichel +name: aws-efs-csi-driver +sources: +- https://github.com/kubernetes-sigs/aws-efs-csi-driver +version: 3.0.8 diff --git a/backing-services/aws-efs-csi-driverOLD/auction-stage-eks.values.yaml b/backing-services/aws-efs-csi-driverOLD/auction-stage-eks.values.yaml new file mode 100644 index 0000000..52521cd --- /dev/null +++ b/backing-services/aws-efs-csi-driverOLD/auction-stage-eks.values.yaml @@ -0,0 +1,28 @@ +controller: + serviceAccount: + create: true + name: efs-csi-node-sa + +node: + # Specifies whether a service account should be created + serviceAccount: + create: true + name: efs-csi-node-sa + annotations: + ## Enable if EKS IAM for SA is used + eks.amazonaws.com/role-arn: "arn:aws:iam::667294666490:role/auction-cluster-20241126163757775000000001" + +storageClasses: +- name: efs-sc + annotations: + storageclass.kubernetes.io/is-default-class: "true" + mountOptions: + - tls + parameters: + provisioningMode: efs-ap + fileSystemId: fs-09f60032cda93f18a + directoryPerms: "700" + gidRangeStart: "1000" + gidRangeEnd: "2000" + reclaimPolicy: Delete + volumeBindingMode: Immediate diff --git a/backing-services/aws-efs-csi-driverOLD/school-stage-eks.values.yaml b/backing-services/aws-efs-csi-driverOLD/school-stage-eks.values.yaml new file mode 100644 index 0000000..2249290 --- /dev/null +++ b/backing-services/aws-efs-csi-driverOLD/school-stage-eks.values.yaml @@ -0,0 +1,28 @@ +controller: + serviceAccount: + create: true + name: efs-csi-node-sa + +node: + # Specifies whether a service account should be created + serviceAccount: + create: true + name: efs-csi-node-sa + annotations: + ## Enable if EKS IAM for SA is used + eks.amazonaws.com/role-arn: "arn:aws:iam::889565812003:role/schoolbuses-cluster-20241110104436981500000002" + +storageClasses: +- name: efs-sc + annotations: + storageclass.kubernetes.io/is-default-class: "true" + mountOptions: + - tls + parameters: + provisioningMode: efs-ap + fileSystemId: fs-0a434a5de93866ab1 + directoryPerms: "700" + gidRangeStart: "1000" + gidRangeEnd: "2000" + reclaimPolicy: Delete + volumeBindingMode: Immediate diff --git a/backing-services/aws-efs-csi-driverOLD/schoolbuses.values.yaml b/backing-services/aws-efs-csi-driverOLD/schoolbuses.values.yaml new file mode 100644 index 0000000..38d9c6a --- /dev/null +++ b/backing-services/aws-efs-csi-driverOLD/schoolbuses.values.yaml @@ -0,0 +1,28 @@ +controller: + serviceAccount: + create: true + name: efs-csi-controller-sa + +node: + # Specifies whether a service account should be created + serviceAccount: + create: true + name: efs-csi-node-sa + annotations: + ## Enable if EKS IAM for SA is used + eks.amazonaws.com/role-arn: arn:aws:iam::889565812003:role/schoolbuses_Cluster_IAM + +storageClasses: +- name: efs-sc + annotations: + storageclass.kubernetes.io/is-default-class: "true" + mountOptions: + - tls + parameters: + provisioningMode: efs-ap + fileSystemId: fs-08694c721b539abe2 + directoryPerms: "700" + gidRangeStart: "1000" + gidRangeEnd: "2000" + reclaimPolicy: Delete + volumeBindingMode: Immediate diff --git a/backing-services/aws-efs-csi-driverOLD/templates/NOTES.txt b/backing-services/aws-efs-csi-driverOLD/templates/NOTES.txt new file mode 100644 index 0000000..66f4d12 --- /dev/null +++ b/backing-services/aws-efs-csi-driverOLD/templates/NOTES.txt @@ -0,0 +1,3 @@ +To verify that aws-efs-csi-driver has started, run: + + kubectl get pod -n {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "aws-efs-csi-driver.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" diff --git a/backing-services/aws-efs-csi-driverOLD/templates/_helpers.tpl b/backing-services/aws-efs-csi-driverOLD/templates/_helpers.tpl new file mode 100644 index 0000000..ab6b4e0 --- /dev/null +++ b/backing-services/aws-efs-csi-driverOLD/templates/_helpers.tpl @@ -0,0 +1,56 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "aws-efs-csi-driver.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "aws-efs-csi-driver.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "aws-efs-csi-driver.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "aws-efs-csi-driver.labels" -}} +app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} +helm.sh/chart: {{ include "aws-efs-csi-driver.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Create a string out of the map for controller tags flag +*/}} +{{- define "aws-efs-csi-driver.tags" -}} +{{- $tags := list -}} +{{ range $key, $val := . }} +{{- $tags = print $key ":" $val | append $tags -}} +{{- end -}} +{{- join " " $tags -}} +{{- end -}} diff --git a/backing-services/aws-efs-csi-driverOLD/templates/controller-deployment.yaml b/backing-services/aws-efs-csi-driverOLD/templates/controller-deployment.yaml new file mode 100644 index 0000000..94e321c --- /dev/null +++ b/backing-services/aws-efs-csi-driverOLD/templates/controller-deployment.yaml @@ -0,0 +1,178 @@ +{{- if .Values.controller.create }} +# Controller Service +kind: Deployment +apiVersion: apps/v1 +metadata: + name: efs-csi-controller + labels: + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} + {{- with .Values.controller.additionalLabels }} + {{ toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: efs-csi-controller + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + {{- with .Values.controller.updateStrategy }} + strategy: + {{ toYaml . | nindent 4 }} + {{- end }} + template: + metadata: + labels: + app: efs-csi-controller + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + {{- with .Values.controller.podLabels }} + {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.podAnnotations }} + annotations: {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if hasKey .Values.controller "hostNetwork" }} + hostNetwork: {{ .Values.controller.hostNetwork }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- range .Values.imagePullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} + nodeSelector: + kubernetes.io/os: linux + {{- with .Values.controller.nodeSelector }} + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ .Values.controller.serviceAccount.name }} + priorityClassName: {{ .Values.controller.priorityClassName | default "system-cluster-critical" }} + {{- with .Values.controller.tolerations }} + tolerations: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.controller.dnsPolicy }} + dnsPolicy: {{ .Values.controller.dnsPolicy }} + {{- end }} + {{- with .Values.controller.dnsConfig }} + dnsConfig: {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: efs-plugin + {{- with .Values.controller.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + image: {{ printf "%s:%s" .Values.image.repository (default (printf "v%s" .Chart.AppVersion) (toString .Values.image.tag)) }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - --endpoint=$(CSI_ENDPOINT) + - --logtostderr + {{- if .Values.controller.tags }} + - --tags={{ include "aws-efs-csi-driver.tags" .Values.controller.tags }} + {{- end }} + - --v={{ .Values.controller.logLevel }} + - --delete-access-point-root-dir={{ hasKey .Values.controller "deleteAccessPointRootDir" | ternary .Values.controller.deleteAccessPointRootDir false }} + env: + - name: CSI_ENDPOINT + value: unix:///var/lib/csi/sockets/pluginproxy/csi.sock + {{- if .Values.controller.regionalStsEndpoints }} + - name: AWS_STS_REGIONAL_ENDPOINTS + value: regional + {{- end }} + - name: CSI_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + {{- if .Values.useFIPS }} + - name: AWS_USE_FIPS_ENDPOINT + value: "true" + {{- end }} + {{- with .Values.controller.env }} + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: socket-dir + mountPath: /var/lib/csi/sockets/pluginproxy/ + {{- with .Values.controller.volumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: healthz + containerPort: {{ .Values.controller.healthPort }} + protocol: TCP + livenessProbe: + httpGet: + path: /healthz + port: healthz + initialDelaySeconds: 10 + timeoutSeconds: 3 + periodSeconds: 10 + failureThreshold: 5 + {{- with .Values.controller.resources }} + resources: {{ toYaml . | nindent 12 }} + {{- end }} + - name: csi-provisioner + image: {{ printf "%s:%s" .Values.sidecars.csiProvisioner.image.repository .Values.sidecars.csiProvisioner.image.tag }} + imagePullPolicy: {{ .Values.sidecars.csiProvisioner.image.pullPolicy }} + args: + - --csi-address=$(ADDRESS) + - --v={{ .Values.controller.logLevel }} + - --feature-gates=Topology=true + {{- if .Values.controller.extraCreateMetadata }} + - --extra-create-metadata + {{- end }} + - --leader-election + {{- if hasKey .Values.controller "leaderElectionRenewDeadline" }} + - --leader-election-renew-deadline={{ .Values.controller.leaderElectionRenewDeadline }} + {{- end }} + {{- if hasKey .Values.controller "leaderElectionLeaseDuration" }} + - --leader-election-lease-duration={{ .Values.controller.leaderElectionLeaseDuration }} + {{- end }} + env: + - name: ADDRESS + value: /var/lib/csi/sockets/pluginproxy/csi.sock + volumeMounts: + - name: socket-dir + mountPath: /var/lib/csi/sockets/pluginproxy/ + {{- with .Values.sidecars.csiProvisioner.resources }} + resources: {{ toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.csiProvisioner.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + - name: liveness-probe + image: {{ printf "%s:%s" .Values.sidecars.livenessProbe.image.repository .Values.sidecars.livenessProbe.image.tag }} + imagePullPolicy: {{ .Values.sidecars.livenessProbe.image.pullPolicy }} + args: + - --csi-address=/csi/csi.sock + - --health-port={{ .Values.controller.healthPort }} + volumeMounts: + - name: socket-dir + mountPath: /csi + {{- with .Values.controller.volumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.livenessProbe.resources }} + resources: {{ toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.livenessProbe.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + volumes: + - name: socket-dir + emptyDir: {} + {{- with .Values.controller.volumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.affinity }} + affinity: {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/backing-services/aws-efs-csi-driverOLD/templates/controller-serviceaccount.yaml b/backing-services/aws-efs-csi-driverOLD/templates/controller-serviceaccount.yaml new file mode 100644 index 0000000..44326cd --- /dev/null +++ b/backing-services/aws-efs-csi-driverOLD/templates/controller-serviceaccount.yaml @@ -0,0 +1,86 @@ +{{- if .Values.controller.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.controller.serviceAccount.name }} + labels: + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} + {{- with .Values.controller.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} +--- + +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: efs-csi-external-provisioner-role + labels: + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} +rules: + - apiGroups: [""] + resources: ["persistentvolumes"] + verbs: ["get", "list", "watch", "create", "patch", "delete"] + - apiGroups: [""] + resources: ["persistentvolumeclaims"] + verbs: ["get", "list", "watch", "update"] + - apiGroups: ["storage.k8s.io"] + resources: ["storageclasses"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["events"] + verbs: ["list", "watch", "create", "patch"] + - apiGroups: ["storage.k8s.io"] + resources: ["csinodes"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch"] + - apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["get", "watch", "list", "delete", "update", "create"] +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: efs-csi-external-provisioner-role-describe-secrets + labels: + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} +rules: + - apiGroups: [ "" ] + resources: [ "secrets" ] + resourceNames: ["x-account"] + verbs: [ "get", "watch", "list" ] +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: efs-csi-provisioner-binding + labels: + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} +subjects: + - kind: ServiceAccount + name: {{ .Values.controller.serviceAccount.name }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: efs-csi-external-provisioner-role + apiGroup: rbac.authorization.k8s.io +--- +# We use a RoleBinding to restrict Secret access to the namespace that the +# RoleBinding is created in (typically kube-system) +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: efs-csi-provisioner-binding-describe-secrets + labels: + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} +subjects: + - kind: ServiceAccount + name: {{ .Values.controller.serviceAccount.name }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: efs-csi-external-provisioner-role-describe-secrets + apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/backing-services/aws-efs-csi-driverOLD/templates/csidriver.yaml b/backing-services/aws-efs-csi-driverOLD/templates/csidriver.yaml new file mode 100644 index 0000000..e6b4d41 --- /dev/null +++ b/backing-services/aws-efs-csi-driverOLD/templates/csidriver.yaml @@ -0,0 +1,10 @@ +apiVersion: {{ ternary "storage.k8s.io/v1" "storage.k8s.io/v1beta1" (semverCompare ">=1.18.0-0" .Capabilities.KubeVersion.Version) }} +kind: CSIDriver +metadata: + name: efs.csi.aws.com + annotations: + "helm.sh/hook": pre-install, pre-upgrade + "helm.sh/hook-delete-policy": before-hook-creation + "helm.sh/resource-policy": keep +spec: + attachRequired: false diff --git a/backing-services/aws-efs-csi-driverOLD/templates/node-daemonset.yaml b/backing-services/aws-efs-csi-driverOLD/templates/node-daemonset.yaml new file mode 100644 index 0000000..4fa44b9 --- /dev/null +++ b/backing-services/aws-efs-csi-driverOLD/templates/node-daemonset.yaml @@ -0,0 +1,199 @@ +# Node Service +kind: DaemonSet +apiVersion: apps/v1 +metadata: + name: efs-csi-node + labels: + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} + {{- with .Values.node.additionalLabels }} + {{ toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + app: efs-csi-node + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + {{- with .Values.node.updateStrategy }} + updateStrategy: + {{ toYaml . | nindent 4 }} + {{- end }} + template: + metadata: + labels: + app: efs-csi-node + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + {{- with .Values.node.podLabels }} + {{ toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.node.podAnnotations }} + annotations: {{ toYaml .Values.node.podAnnotations | nindent 8 }} + {{- end }} + spec: + {{- with .Values.node.hostAliases }} + hostAliases: + {{- range $k, $v := . }} + - ip: {{ $v.ip }} + hostnames: + - {{ $k }}.efs.{{ $v.region }}.amazonaws.com + {{- end }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- range .Values.imagePullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} + nodeSelector: + kubernetes.io/os: linux + {{- with .Values.node.nodeSelector }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.node.affinity }} + affinity: {{- toYaml . | nindent 8 }} + {{- end }} + hostNetwork: true + dnsPolicy: {{ .Values.node.dnsPolicy }} + {{- with .Values.node.dnsConfig }} + dnsConfig: {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ .Values.node.serviceAccount.name }} + priorityClassName: {{ .Values.node.priorityClassName}} + {{- with .Values.node.tolerations }} + tolerations: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.node.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: efs-plugin + securityContext: + privileged: true + image: {{ printf "%s:%s" .Values.image.repository (default (printf "v%s" .Chart.AppVersion) (toString .Values.image.tag)) }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - --endpoint=$(CSI_ENDPOINT) + - --logtostderr + - --v={{ .Values.node.logLevel }} + - --vol-metrics-opt-in={{ hasKey .Values.node "volMetricsOptIn" | ternary .Values.node.volMetricsOptIn false }} + - --vol-metrics-refresh-period={{ hasKey .Values.node "volMetricsRefreshPeriod" | ternary .Values.node.volMetricsRefreshPeriod 240 }} + - --vol-metrics-fs-rate-limit={{ hasKey .Values.node "volMetricsFsRateLimit" | ternary .Values.node.volMetricsFsRateLimit 5 }} + env: + - name: CSI_ENDPOINT + value: unix:/csi/csi.sock + - name: CSI_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + {{- if .Values.useFIPS }} + - name: AWS_USE_FIPS_ENDPOINT + value: "true" + {{- end }} + {{- with .Values.node.env }} + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: kubelet-dir + mountPath: /var/lib/kubelet + mountPropagation: "Bidirectional" + - name: plugin-dir + mountPath: /csi + - name: efs-state-dir + mountPath: /var/run/efs + - name: efs-utils-config + mountPath: /var/amazon/efs + - name: efs-utils-config-legacy + mountPath: /etc/amazon/efs-legacy + {{- with .Values.node.volumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: healthz + containerPort: {{ .Values.node.healthPort }} + protocol: TCP + livenessProbe: + httpGet: + path: /healthz + port: healthz + initialDelaySeconds: 10 + timeoutSeconds: 3 + periodSeconds: 2 + failureThreshold: 5 + {{- with .Values.node.resources }} + resources: {{ toYaml . | nindent 12 }} + {{- end }} + - name: csi-driver-registrar + image: {{ printf "%s:%s" .Values.sidecars.nodeDriverRegistrar.image.repository .Values.sidecars.nodeDriverRegistrar.image.tag }} + imagePullPolicy: {{ .Values.sidecars.nodeDriverRegistrar.image.pullPolicy }} + args: + - --csi-address=$(ADDRESS) + - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) + - --v={{ .Values.node.logLevel }} + env: + - name: ADDRESS + value: /csi/csi.sock + - name: DRIVER_REG_SOCK_PATH + value: /var/lib/kubelet/plugins/efs.csi.aws.com/csi.sock + - name: KUBE_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + volumeMounts: + - name: plugin-dir + mountPath: /csi + - name: registration-dir + mountPath: /registration + {{- with .Values.sidecars.nodeDriverRegistrar.resources }} + resources: {{ toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.nodeDriverRegistrar.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + - name: liveness-probe + image: {{ printf "%s:%s" .Values.sidecars.livenessProbe.image.repository .Values.sidecars.livenessProbe.image.tag }} + imagePullPolicy: {{ .Values.sidecars.livenessProbe.image.pullPolicy }} + args: + - --csi-address=/csi/csi.sock + - --health-port={{ .Values.node.healthPort }} + - --v={{ .Values.node.logLevel }} + volumeMounts: + - name: plugin-dir + mountPath: /csi + {{- with .Values.sidecars.livenessProbe.resources }} + resources: {{ toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.livenessProbe.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + volumes: + - name: kubelet-dir + hostPath: + path: /var/lib/kubelet + type: Directory + - name: plugin-dir + hostPath: + path: /var/lib/kubelet/plugins/efs.csi.aws.com/ + type: DirectoryOrCreate + - name: registration-dir + hostPath: + path: /var/lib/kubelet/plugins_registry/ + type: Directory + - name: efs-state-dir + hostPath: + path: /var/run/efs + type: DirectoryOrCreate + - name: efs-utils-config + hostPath: + path: /var/amazon/efs + type: DirectoryOrCreate + - name: efs-utils-config-legacy + hostPath: + path: /etc/amazon/efs + type: DirectoryOrCreate + {{- with .Values.node.volumes }} + {{- toYaml . | nindent 8 }} + {{- end }} \ No newline at end of file diff --git a/backing-services/aws-efs-csi-driverOLD/templates/node-serviceaccount.yaml b/backing-services/aws-efs-csi-driverOLD/templates/node-serviceaccount.yaml new file mode 100644 index 0000000..c90d62b --- /dev/null +++ b/backing-services/aws-efs-csi-driverOLD/templates/node-serviceaccount.yaml @@ -0,0 +1,39 @@ +{{- if .Values.node.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.node.serviceAccount.name }} + labels: + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} + {{- with .Values.node.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: efs-csi-node-role + labels: + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} +rules: + - apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch", "patch"] +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: efs-csi-node-binding + labels: + app.kubernetes.io/name: {{ include "aws-efs-csi-driver.name" . }} +subjects: + - kind: ServiceAccount + name: {{ .Values.node.serviceAccount.name }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: efs-csi-node-role + apiGroup: rbac.authorization.k8s.io + \ No newline at end of file diff --git a/backing-services/aws-efs-csi-driverOLD/templates/storageclass.yaml b/backing-services/aws-efs-csi-driverOLD/templates/storageclass.yaml new file mode 100644 index 0000000..8ce1ec8 --- /dev/null +++ b/backing-services/aws-efs-csi-driverOLD/templates/storageclass.yaml @@ -0,0 +1,26 @@ +{{- range .Values.storageClasses }} +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: {{ .name }} + {{- with .annotations }} + annotations: + {{ toYaml . | indent 4 }} + {{- end }} +provisioner: efs.csi.aws.com +{{- with .mountOptions }} +mountOptions: +{{ toYaml . }} +{{- end }} +{{- with .parameters }} +parameters: +{{ toYaml . | indent 2 }} +{{- end }} +{{- with .reclaimPolicy }} +reclaimPolicy: {{ . }} +{{- end }} +{{- with .volumeBindingMode }} +volumeBindingMode: {{ . }} +{{- end }} +--- +{{- end }} \ No newline at end of file diff --git a/backing-services/aws-efs-csi-driverOLD/values.yaml b/backing-services/aws-efs-csi-driverOLD/values.yaml new file mode 100644 index 0000000..a9e549f --- /dev/null +++ b/backing-services/aws-efs-csi-driverOLD/values.yaml @@ -0,0 +1,209 @@ +# Default values for aws-efs-csi-driver. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +nameOverride: "" +fullnameOverride: "" + +replicaCount: 2 + +useFIPS: false + +image: + repository: public.ecr.aws/efs-csi-driver/amazon/aws-efs-csi-driver + tag: "v2.0.7" + pullPolicy: IfNotPresent + +sidecars: + livenessProbe: + image: + repository: public.ecr.aws/eks-distro/kubernetes-csi/livenessprobe + tag: v2.13.0-eks-1-30-8 + pullPolicy: IfNotPresent + resources: {} + securityContext: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + nodeDriverRegistrar: + image: + repository: public.ecr.aws/eks-distro/kubernetes-csi/node-driver-registrar + tag: v2.11.0-eks-1-30-8 + pullPolicy: IfNotPresent + resources: {} + securityContext: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + csiProvisioner: + image: + repository: public.ecr.aws/eks-distro/kubernetes-csi/external-provisioner + tag: v5.0.1-eks-1-30-8 + pullPolicy: IfNotPresent + resources: {} + securityContext: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + +imagePullSecrets: [] + +## Controller deployment variables + +controller: + # Specifies whether a deployment should be created + create: true + # Number for the log level verbosity + logLevel: 2 + # If set, add pv/pvc metadata to plugin create requests as parameters. + extraCreateMetadata: true + # Add additional tags to access points + tags: + {} + # environment: prod + # region: us-east-1 + # Enable if you want the controller to also delete the + # path on efs when deleteing an access point + deleteAccessPointRootDir: false + podAnnotations: {} + podLabel: {} + hostNetwork: false + priorityClassName: system-cluster-critical + dnsPolicy: ClusterFirst + dnsConfig: {} + additionalLabels: {} + resources: + {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + nodeSelector: {} + updateStrategy: {} + tolerations: + - key: CriticalAddonsOnly + operator: Exists + - key: efs.csi.aws.com/agent-not-ready + operator: Exists + affinity: {} + env: [] + volumes: [] + volumeMounts: [] + # Specifies whether a service account should be created + serviceAccount: + create: true + name: efs-csi-controller-sa + annotations: {} + ## Enable if EKS IAM for SA is used + # eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/efs-csi-role + healthPort: 9909 + regionalStsEndpoints: false + # securityContext on the controller pod + securityContext: + runAsNonRoot: false + runAsUser: 0 + runAsGroup: 0 + fsGroup: 0 + # securityContext on the controller container + # Setting privileged=false will cause the "delete-access-point-root-dir" controller option to fail + containerSecurityContext: + privileged: true + leaderElectionRenewDeadline: 10s + leaderElectionLeaseDuration: 15s + + +## Node daemonset variables + +node: + # Number for the log level verbosity + logLevel: 2 + volMetricsOptIn: false + volMetricsRefreshPeriod: 240 + volMetricsFsRateLimit: 5 + hostAliases: + {} + # For cross VPC EFS, you need to poison or overwrite the DNS for the efs volume as per + # https://docs.aws.amazon.com/efs/latest/ug/efs-different-vpc.html#wt6-efs-utils-step3 + # implementing the suggested solution found here: + # https://github.com/kubernetes-sigs/aws-efs-csi-driver/issues/240#issuecomment-676849346 + # EFS Vol ID, IP, Region + # "fs-01234567": + # ip: 10.10.2.2 + # region: us-east-2 + priorityClassName: system-node-critical + dnsPolicy: ClusterFirst + dnsConfig: + {} + # Example config which uses the AWS nameservers + # dnsPolicy: "None" + # dnsConfig: + # nameservers: + # - 169.254.169.253 + podLabels: {} + podAnnotations: {} + additionalLabels: {} + resources: + {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + nodeSelector: {} + updateStrategy: {} + # Override default strategy (RollingUpdate) to speed up deployment. + # This can be useful if helm timeouts are observed. + # type: OnDelete + tolerations: + - operator: Exists + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: eks.amazonaws.com/compute-type + operator: NotIn + values: + - fargate + # Specifies whether a service account should be created + serviceAccount: + create: true + name: efs-csi-node-sa + annotations: {} + ## Enable if EKS IAM for SA is used + # eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/efs-csi-role + healthPort: 9809 + # securityContext on the node pod + securityContext: + # The node pod must be run as root to bind to the registration/driver sockets + runAsNonRoot: false + runAsUser: 0 + runAsGroup: 0 + fsGroup: 0 + env: [] + volumes: [] + volumeMounts: [] + +storageClasses: [] +# Add StorageClass resources like: +# - name: efs-sc +# annotations: +# # Use that annotation if you want this to your default storageclass +# storageclass.kubernetes.io/is-default-class: "true" +# mountOptions: +# - tls +# parameters: +# provisioningMode: efs-ap +# fileSystemId: fs-1122aabb +# directoryPerms: "700" +# gidRangeStart: "1000" +# gidRangeEnd: "2000" +# basePath: "/dynamic_provisioning" +# subPathPattern: "/subPath" +# ensureUniqueDirectory: true +# reclaimPolicy: Delete +# volumeBindingMode: Immediate diff --git a/backing-services/aws-load-balancer-controller/.helmignore b/backing-services/aws-load-balancer-controller/.helmignore new file mode 100644 index 0000000..67263be --- /dev/null +++ b/backing-services/aws-load-balancer-controller/.helmignore @@ -0,0 +1,25 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ +crds/kustomization.yaml +test.yaml diff --git a/backing-services/aws-load-balancer-controller/Chart.yaml b/backing-services/aws-load-balancer-controller/Chart.yaml new file mode 100644 index 0000000..dc43ccd --- /dev/null +++ b/backing-services/aws-load-balancer-controller/Chart.yaml @@ -0,0 +1,22 @@ +apiVersion: v2 +appVersion: v2.8.2 +description: AWS Load Balancer Controller Helm chart for Kubernetes +home: https://github.com/aws/eks-charts +icon: https://raw.githubusercontent.com/aws/eks-charts/master/docs/logo/aws.png +keywords: +- eks +- alb +- load balancer +- ingress +- nlb +maintainers: +- email: kishorj@users.noreply.github.com + name: kishorj + url: https://github.com/kishorj +- email: m00nf1sh@users.noreply.github.com + name: m00nf1sh + url: https://github.com/m00nf1sh +name: aws-load-balancer-controller +sources: +- https://github.com/aws/eks-charts +version: 1.8.2 diff --git a/backing-services/aws-load-balancer-controller/README.md b/backing-services/aws-load-balancer-controller/README.md new file mode 100644 index 0000000..775898e --- /dev/null +++ b/backing-services/aws-load-balancer-controller/README.md @@ -0,0 +1,283 @@ +# AWS Load Balancer Controller + +AWS Load Balancer controller Helm chart for Kubernetes + +## TL;DR: +```sh +helm repo add eks https://aws.github.io/eks-charts +# If using IAM Roles for service account install as follows - NOTE: you need to specify both of the chart values `serviceAccount.create=false` and `serviceAccount.name=aws-load-balancer-controller` +helm install aws-load-balancer-controller eks/aws-load-balancer-controller --set clusterName=my-cluster -n kube-system --set serviceAccount.create=false --set serviceAccount.name=aws-load-balancer-controller +# If not using IAM Roles for service account +helm install aws-load-balancer-controller eks/aws-load-balancer-controller --set clusterName=my-cluster -n kube-system +``` + +## Introduction +AWS Load Balancer controller manages the following AWS resources +- Application Load Balancers to satisfy Kubernetes ingress objects +- Network Load Balancers to satisfy Kubernetes service objects of type LoadBalancer with appropriate annotations + +## Security updates +**Note**: Deployed chart does not receive security updates automatically. You need to manually upgrade to a newer chart. +#### Node isolation +As a security best practice, we recommend isolating the controller deployment pods to specific node groups which run critical components. The helm chart provides parameters ```nodeSelector```, ```tolerations``` and ```affinity``` to configure node isolation. For more information, please refer to the guidance [here](https://aws.github.io/aws-eks-best-practices/security/docs/multitenancy/#isolating-tenant-workloads-to-specific-nodes). + +## Prerequisites +- Supported Kubernetes Versions + - Chart version v1.5.0+ requires Kubernetes 1.22+ + - Chart version v1.4.0+ requires Kubernetes 1.19+ + - Chart version v1.2.0 - v1.3.3 supports Kubernetes 1.16-1.21 + - Chart version v1.1.6 and before supports Kubernetes 1.15 +- IAM permissions +- Helm v3 +- Optional dependencies + - cert-manager + - Prometheus Operator + +The controller runs on the worker nodes, so it needs access to the AWS ALB/NLB resources via IAM permissions. The +IAM permissions can either be setup via IAM roles for ServiceAccount or can be attached directly to the worker node IAM roles. + +#### Setup IAM for ServiceAccount +1. Create IAM OIDC provider + ``` + eksctl utils associate-iam-oidc-provider \ + --region \ + --cluster \ + --approve + ``` +1. Download IAM policy for the AWS Load Balancer Controller + ``` + curl -o iam-policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json + ``` +1. Create an IAM policy called AWSLoadBalancerControllerIAMPolicy + ``` + aws iam create-policy \ + --policy-name AWSLoadBalancerControllerIAMPolicy \ + --policy-document file://iam-policy.json + ``` + Take note of the policy ARN that is returned + +1. Create a IAM role and ServiceAccount for the Load Balancer controller, use the ARN from the step above + ``` + eksctl create iamserviceaccount \ + --cluster= \ + --namespace=kube-system \ + --name=aws-load-balancer-controller \ + --attach-policy-arn=arn:aws:iam:::policy/AWSLoadBalancerControllerIAMPolicy \ + --approve + ``` +#### Setup IAM manually +If not setting up IAM for ServiceAccount, apply the IAM policies from the following URL at minimum. +``` +https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/main/docs/install/iam_policy.json +``` + +#### Upgrading from ALB ingress controller +If migrating from ALB ingress controller, grant [additional IAM permissions](https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy_v1_to_v2_additional.json). + +#### Upgrading from AWS Load Balancer controller v2.1.3 and earlier +- Additional IAM permissions required, ensure you have granted the [required IAM permissions](https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json). +- CRDs need to be updated as follows +```shell script +kubectl apply -k "github.com/aws/eks-charts/stable/aws-load-balancer-controller//crds?ref=master" +``` +- you can run helm upgrade without uninstalling the old chart completely + +#### Installing cert-manager + +If you are setting `enableCertManager: true` you need to have installed cert-manager and it's CRDs before installing this chart; to install [cert-manager](https://artifacthub.io/packages/helm/cert-manager/cert-manager) follow the installation guide. + +The controller helm chart requires the cert-manager with apiVersion `cert-manager.io/v1`. + +Set `cluster.dnsDomain` (default: `cluster.local`) to the actual DNS domain of your cluster to include the FQDN in requested TLS certificates. + +#### Installing the Prometheus Operator + +If you are setting `serviceMonitor.enabled: true` you need to have installed the Prometheus Operator ServiceMonitor CRD before installing this chart and have the operator running to collect the metrics. The easiest way to do this is to install the [kube-prometheus-stack](https://artifacthub.io/packages/helm/prometheus-community/kube-prometheus-stack) Helm chart using the installation guide. + +## Installing the Chart +**Note**: You need to uninstall aws-alb-ingress-controller. Please refer to the [upgrade](#Upgrade) section below before you proceed. + +**Note**: Starting chart version 1.4.1, you need to explicitly set `clusterSecretsPermissions.allowAllSecrets` to true to grant the controller permission to access all secrets for OIDC feature. We recommend configuring access to individual secrets resource separately [[link](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/examples/secrets_access/)]. + +**Note**: To ensure compatibility, we recommend installing the AWS Load Balancer controller image version with its compatible Helm chart version. Use the ```helm search repo eks/aws-load-balancer-controller --versions``` command to find the compatible versions. + +Add the EKS repository to Helm: +```shell script +helm repo add eks https://aws.github.io/eks-charts +``` + +Install the TargetGroupBinding CRDs: + +```shell script +kubectl apply -k "github.com/aws/eks-charts/stable/aws-load-balancer-controller/crds?ref=master" +``` + +Install the AWS Load Balancer controller, if using iamserviceaccount +```shell script +# NOTE: The clusterName value must be set either via the values.yaml or the Helm command line. The in the command +# below should be replaced with name of your k8s cluster before running it. +helm upgrade -i aws-load-balancer-controller eks/aws-load-balancer-controller -n kube-system --set clusterName= --set serviceAccount.create=false --set serviceAccount.name=aws-load-balancer-controller +``` + +Install the AWS Load Balancer controller, if not using iamserviceaccount +```shell script +helm upgrade -i aws-load-balancer-controller eks/aws-load-balancer-controller -n kube-system --set clusterName= +``` + +## Upgrade +The new controller is backwards compatible with the existing ingress objects. However, it will not coexist with the older aws-alb-ingress-controller. +The old controller must be uninstalled completely before installing the new version. +### Kubectl installation +If you had installed the previous version via kubectl, uninstall as follows +```shell script +$ kubectl delete deployment -n kube-system alb-ingress-controller +$ kubectl delete clusterRole alb-ingress-controller +$ kubectl delete ClusterRoleBinding alb-ingress-controller +$ kubectl delete ServiceAccount -n kube-system alb-ingress-controller + +# Alternatively you can find the version of the controller and delete as follows +$ kubectl describe deployment -n kube-system alb-ingress-controller |grep Image + Image: docker.io/amazon/aws-alb-ingress-controller:v1.1.8 +# You can delete the deployment now +$ kubectl delete deployment -n kube-system alb-ingress-controller +# In this case, the version is v1.1.8, the rbac roles can be removed as follows +$ kubectl delete -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.8/docs/examples/rbac-role.yaml +``` +### Helm installation +If you had installed the incubator/aws-alb-ingress-controller Helm chart, uninstall as follows +```shell script +# NOTE: If installed under a different chart name and namespace, please specify as appropriate +$ helm delete aws-alb-ingress-controller -n kube-system +``` + +If you had installed the 0.1.x version of eks-charts/aws-load-balancer-controller chart earlier, the upgrade to chart version 1.0.0 will +not work due to incompatibility of the webhook api version, uninstall as follows +```shell script +$ helm delete aws-load-balancer-controller -n kube-system +``` + +## Uninstalling the Chart +```sh +helm delete aws-load-balancer-controller -n kube-system +``` + +If you setup IAM Roles for ServiceAccount, you can cleanup as follows +``` +eksctl delete iamserviceaccount --cluster --namespace kube-system --name aws-load-balancer-controller +``` + +## HA configuration +Chart release v1.2.0 and later enables high availability configuration by default. +- The default number of replicas is 2. You can pass`--set replicaCount=1` flag during chart installation to disable this. Due to leader election, only one controller will actively reconcile resources. +- The default priority class for the controller pods is `system-cluster-critical` +- Soft pod anti-affinity is enabled for controller pods with `topologyKey: kubernetes.io/hostname` if you don't configure custom affinity and set `configureDefaultAffinity` to `true` +- Pod disruption budget (PDB) has not been set by default. If you plan on running at least 2 controller pods, you can pass `--set podDisruptionBudget.maxUnavailable=1` flag during chart installation + +## Configuration + +The following tables lists the configurable parameters of the chart and their default values. +The default values set by the application itself can be confirmed [here](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/deploy/configurations/#controller-configuration-options). + + +| Parameter | Description | Default | +| ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- | +| `image.repository` | image repository | `public.ecr.aws/eks/aws-load-balancer-controller` | +| `image.tag` | image tag | `` | +| `image.pullPolicy` | image pull policy | `IfNotPresent` | +| `clusterName` | Kubernetes cluster name | None | +| `cluster.dnsDomain` | DNS domain of the Kubernetes cluster, included in TLS certificate requests | `cluster.local` | +| `securityContext` | Set to security context for pod | `{}` | +| `resources` | Controller pod resource requests & limits | `{}` | +| `priorityClassName` | Controller pod priority class | system-cluster-critical | +| `nodeSelector` | Node labels for controller pod assignment | `{}` | +| `tolerations` | Controller pod toleration for taints | `{}` | +| `affinity` | Affinity for pod assignment | `{}` | +| `configureDefaultAffinity` | Configure soft pod anti-affinity if custom affinity is not configured | `true` | +| `topologySpreadConstraints` | Topology Spread Constraints for pod assignment | `{}` | +| `deploymentAnnotations` | Annotations to add to deployment | `{}` | +| `podAnnotations` | Annotations to add to each pod | `{}` | +| `podLabels` | Labels to add to each pod | `{}` | +| `additionalLabels` | Labels to add to all components | `{}` | +| `rbac.create` | if `true`, create and use RBAC resources | `true` | +| `serviceAccount.annotations` | optional annotations to add to service account | None | +| `serviceAccount.automountServiceAccountToken` | Automount API credentials for a Service Account | `true` | +| `serviceAccount.imagePullSecrets` | List of image pull secrets to add to the Service Account | `[]` | +| `serviceAccount.create` | If `true`, create a new service account | `true` | +| `serviceAccount.name` | Service account to be used | None | +| `terminationGracePeriodSeconds` | Time period for controller pod to do a graceful shutdown | 10 | +| `ingressClass` | The ingress class to satisfy | alb | +| `createIngressClassResource` | Create ingressClass resource | true | +| `ingressClassParams.name` | IngressClassParams resource's name, default to the aws load balancer controller's name | None | +| `ingressClassParams.create` | If `true`, create a new ingressClassParams | true | +| `ingressClassParams.spec` | IngressClassParams defined ingress specifications | {} | +| `region` | The AWS region for the kubernetes cluster | None | +| `vpcId` | The VPC ID for the Kubernetes cluster | None | +| `awsApiEndpoints` | Custom AWS API Endpoints | None | +| `awsApiThrottle` | Custom AWS API throttle settings | None | +| `awsMaxRetries` | Maximum retries for AWS APIs | None | +| `defaultTargetType` | Default target type. Used as the default value of the `alb.ingress.kubernetes.io/target-type` and `service.beta.kubernetes.io/aws-load-balancer-nlb-target-type" annotations.`Possible values are `ip` and `instance`. | `instance` | +| `enablePodReadinessGateInject` | If enabled, targetHealth readiness gate will get injected to the pod spec for the matching endpoint pods | None | +| `enableShield` | Enable Shield addon for ALB | None | +| `enableWaf` | Enable WAF addon for ALB | None | +| `enableWafv2` | Enable WAF V2 addon for ALB | None | +| `ingressMaxConcurrentReconciles` | Maximum number of concurrently running reconcile loops for ingress | None | +| `logLevel` | Set the controller log level - info, debug | None | +| `metricsBindAddr` | The address the metric endpoint binds to | "" | +| `webhookBindPort` | The TCP port the Webhook server binds to | None | +| `webhookTLS.caCert` | TLS CA certificate for webhook (auto-generated if not provided) | "" | +| `webhookTLS.cert` | TLS certificate for webhook (auto-generated if not provided) | "" | +| `webhookTLS.key` | TLS private key for webhook (auto-generated if not provided) | "" | +| `webhookNamespaceSelectors` | Namespace selectors for the wekbook | None | +| `keepTLSSecret` | Reuse existing TLS Secret during chart upgrade | `true` | +| `serviceAnnotations` | Annotations to be added to the provisioned webhook service resource | `{}` | +| `serviceMaxConcurrentReconciles` | Maximum number of concurrently running reconcile loops for service | None | +| `targetgroupbindingMaxConcurrentReconciles` | Maximum number of concurrently running reconcile loops for targetGroupBinding | None | +| `targetgroupbindingMaxExponentialBackoffDelay` | Maximum duration of exponential backoff for targetGroupBinding reconcile failures | None | +| `syncPeriod` | Period at which the controller forces the repopulation of its local object stores | None | +| `watchNamespace` | Namespace the controller watches for updates to Kubernetes objects, If empty, all namespaces are watched | None | +| `disableIngressClassAnnotation` | Disables the usage of kubernetes.io/ingress.class annotation | None | +| `disableIngressGroupNameAnnotation` | Disables the usage of alb.ingress.kubernetes.io/group.name annotation | None | +| `tolerateNonExistentBackendService` | whether to allow rules that reference a backend service that does not exist. (When enabled, it will return 503 error if backend service not exist) | `true` | +| `tolerateNonExistentBackendAction` | whether to allow rules that reference a backend action that does not exist. (When enabled, it will return 503 error if backend action not exist) | `true` | +| `defaultSSLPolicy` | Specifies the default SSL policy to use for HTTPS or TLS listeners | None | +| `externalManagedTags` | Specifies the list of tag keys on AWS resources that are managed externally | `[]` | +| `livenessProbe` | Liveness probe settings for the controller | (see `values.yaml`) | +| `env` | Environment variables to set for aws-load-balancer-controller pod | None | +| `envFrom` | Environment variables to set for aws-load-balancer-controller pod from configMap or Secret | None | + +| `envSecretName` | AWS credentials as environment variables from Secret (Secret keys `key_id` and `access_key`). | None | +| `hostNetwork` | If `true`, use hostNetwork | `false` | +| `dnsPolicy` | Set dnsPolicy if required | `ClusterFirst` | +| `extraVolumeMounts` | Extra volume mounts for the pod | `[]` | +| `extraVolumes` | Extra volumes for the pod | `[]` | +| `defaultTags` | Default tags to apply to all AWS resources managed by this controller | `{}` | +| `replicaCount` | Number of controller pods to run, only one will be active due to leader election | `2` | +| `revisionHistoryLimit` | Number of revisions to keep | `10` | +| `podDisruptionBudget` | Limit the disruption for controller pods. Require at least 2 controller replicas and 3 worker nodes | `{}` | +| `updateStrategy` | Defines the update strategy for the deployment | `{}` | +| `enableCertManager` | If enabled, cert-manager issues the webhook certificates instead of the helm template, requires cert-manager and it's CRDs to be installed | `false` | +| `enableEndpointSlices` | If enabled, controller uses k8s EndpointSlices instead of Endpoints for IP targets | `false` | +| `enableBackendSecurityGroup` | If enabled, controller uses shared security group for backend traffic | `true` | +| `backendSecurityGroup` | Backend security group to use instead of auto created one if the feature is enabled | `` | +| `disableRestrictedSecurityGroupRules` | If disabled, controller will not specify port range restriction in the backend security group rules | `false` | +| `objectSelector.matchExpressions` | Webhook configuration to select specific pods by specifying the expression to be matched | None | +| `objectSelector.matchLabels` | Webhook configuration to select specific pods by specifying the key value label pair to be matched | None | +| `serviceMonitor.enabled` | Specifies whether a service monitor should be created, requires the ServiceMonitor CRD to be installed | `false` | +| `serviceMonitor.namespace` | Namespace in which to create the service monitor | None | +| `serviceMonitor.additionalLabels` | Labels to add to the service monitor | `{}` | +| `serviceMonitor.interval` | Prometheus scrape interval | `1m` | +| `serviceMonitor.scrapeTimeout` | Prometheus scrape timeout | `1m` | +| `serviceMonitor.relabelings` | Relabelings to apply to samples before ingestion | `1m` | +| `serviceMonitor.metricRelabelings` | Metric relabelings to apply to samples before ingestion | `1m` | +| `clusterSecretsPermissions.allowAllSecrets` | If `true`, controller has access to all secrets in the cluster. | `false` | +| `controllerConfig.featureGates` | set of `key: value` pairs that describe AWS load balance controller features | `{}` | +| `ingressClassConfig.default` | If `true`, the ingressclass will be the default class of the cluster. | `false` | +| `enableServiceMutatorWebhook` | If `false`, disable the Service Mutator webhook which makes all new services of type LoadBalancer reconciled by the lb controller | `true` | +| `serviceMutatorWebhookConfig.failurePolicy` | Failure policy for the Service Mutator webhook | `Fail` | +| `serviceMutatorWebhookConfig.objectSelector` | Object selector(s) to limit which objects will be mutated by the Service Mutator webhook | `[]` | +| `serviceMutatorWebhookConfig.operations` | List of operations that will trigger the the Service Mutator webhook | `[ CREATE ]` | +| `autoscaling` | If `autoscaling.enabled=true`, enable the HPA on the controller mainly to survive load induced failure by the calls to the `aws-load-balancer-webhook-service`. Please keep in mind that the controller pods have `priorityClassName: system-cluster-critical`, enabling HPA may lead to the eviction of other low-priority pods in the node | `false` | +| `serviceTargetENISGTags` | set of `key=value` pairs of AWS tags in addition to cluster name for finding the target ENI security group to which to add inbound rules from NLBs | None | +| `loadBalancerClass` | Sets the AWS load balancer type to be used when the Kubernetes service requests an external load balancer | `service.k8s.aws/nlb` | +| `creator` | if set to a `value!=helm`, it will disable the addition of default helm labels | `helm` | +| `runtimeClassName` | Runtime class name for the controller pods , such as `gvisor` or `kata`. An unspecified `nil` or empty `""` RuntimeClassName is equivalent to the backwards-compatible default behavior as if the RuntimeClass feature is disabled. | "" | diff --git a/backing-services/aws-load-balancer-controller/auction-stage-eks.values.yaml b/backing-services/aws-load-balancer-controller/auction-stage-eks.values.yaml new file mode 100644 index 0000000..3125f6c --- /dev/null +++ b/backing-services/aws-load-balancer-controller/auction-stage-eks.values.yaml @@ -0,0 +1,14 @@ +replicaCount: 2 + +clusterName: auction + +# cluster contains configurations specific to the kubernetes cluster +cluster: + # Cluster DNS domain (required for requesting TLS certificates) + dnsDomain: auction.dev + +serviceAccount: + name: aws-load-balancer-aws-load-balancer-controller + create: true + annotations: + eks.amazonaws.com/role-arn: "arn:aws:iam::667294666490:role/auction-cluster-20241126163757775000000001" \ No newline at end of file diff --git a/backing-services/aws-load-balancer-controller/ci/extra_args b/backing-services/aws-load-balancer-controller/ci/extra_args new file mode 100644 index 0000000..c72e0d8 --- /dev/null +++ b/backing-services/aws-load-balancer-controller/ci/extra_args @@ -0,0 +1 @@ +--set clusterName=k8s-ci-cluster diff --git a/backing-services/aws-load-balancer-controller/ci/values.yaml b/backing-services/aws-load-balancer-controller/ci/values.yaml new file mode 100644 index 0000000..4285476 --- /dev/null +++ b/backing-services/aws-load-balancer-controller/ci/values.yaml @@ -0,0 +1,7 @@ +# CI testing values for aws-load-balancer-controller + +region: us-west-2 +image: + repository: public.ecr.aws/eks/aws-load-balancer-controller + tag: v2.4.5 + pullPolicy: Always diff --git a/backing-services/aws-load-balancer-controller/crds/crds.yaml b/backing-services/aws-load-balancer-controller/crds/crds.yaml new file mode 100644 index 0000000..3fcd14e --- /dev/null +++ b/backing-services/aws-load-balancer-controller/crds/crds.yaml @@ -0,0 +1,621 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: ingressclassparams.elbv2.k8s.aws +spec: + group: elbv2.k8s.aws + names: + kind: IngressClassParams + listKind: IngressClassParamsList + plural: ingressclassparams + singular: ingressclassparams + scope: Cluster + versions: + - additionalPrinterColumns: + - description: The Ingress Group name + jsonPath: .spec.group.name + name: GROUP-NAME + type: string + - description: The AWS Load Balancer scheme + jsonPath: .spec.scheme + name: SCHEME + type: string + - description: The AWS Load Balancer ipAddressType + jsonPath: .spec.ipAddressType + name: IP-ADDRESS-TYPE + type: string + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: IngressClassParams is the Schema for the IngressClassParams API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: IngressClassParamsSpec defines the desired state of IngressClassParams + properties: + certificateArn: + description: CertificateArn specifies the ARN of the certificates + for all Ingresses that belong to IngressClass with this IngressClassParams. + items: + type: string + type: array + group: + description: Group defines the IngressGroup for all Ingresses that + belong to IngressClass with this IngressClassParams. + properties: + name: + description: Name is the name of IngressGroup. + type: string + required: + - name + type: object + inboundCIDRs: + description: InboundCIDRs specifies the CIDRs that are allowed to + access the Ingresses that belong to IngressClass with this IngressClassParams. + items: + type: string + type: array + ipAddressType: + description: IPAddressType defines the ip address type for all Ingresses + that belong to IngressClass with this IngressClassParams. + enum: + - ipv4 + - dualstack + - dualstack-without-public-ipv4 + type: string + loadBalancerAttributes: + description: LoadBalancerAttributes define the custom attributes to + LoadBalancers for all Ingress that that belong to IngressClass with + this IngressClassParams. + items: + description: Attributes defines custom attributes on resources. + properties: + key: + description: The key of the attribute. + type: string + value: + description: The value of the attribute. + type: string + required: + - key + - value + type: object + type: array + namespaceSelector: + description: |- + NamespaceSelector restrict the namespaces of Ingresses that are allowed to specify the IngressClass with this IngressClassParams. + * if absent or present but empty, it selects all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + scheme: + description: Scheme defines the scheme for all Ingresses that belong + to IngressClass with this IngressClassParams. + enum: + - internal + - internet-facing + type: string + sslPolicy: + description: SSLPolicy specifies the SSL Policy for all Ingresses + that belong to IngressClass with this IngressClassParams. + type: string + subnets: + description: Subnets defines the subnets for all Ingresses that belong + to IngressClass with this IngressClassParams. + properties: + ids: + description: IDs specify the resource IDs of subnets. Exactly + one of this or `tags` must be specified. + items: + description: SubnetID specifies a subnet ID. + pattern: subnet-[0-9a-f]+ + type: string + minItems: 1 + type: array + tags: + additionalProperties: + items: + type: string + type: array + description: |- + Tags specifies subnets in the load balancer's VPC where each + tag specified in the map key contains one of the values in the corresponding + value list. + Exactly one of this or `ids` must be specified. + type: object + type: object + tags: + description: Tags defines list of Tags on AWS resources provisioned + for Ingresses that belong to IngressClass with this IngressClassParams. + items: + description: Tag defines a AWS Tag on resources. + properties: + key: + description: The key of the tag. + type: string + value: + description: The value of the tag. + type: string + required: + - key + - value + type: object + type: array + type: object + type: object + served: true + storage: true + subresources: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: targetgroupbindings.elbv2.k8s.aws +spec: + group: elbv2.k8s.aws + names: + kind: TargetGroupBinding + listKind: TargetGroupBindingList + plural: targetgroupbindings + singular: targetgroupbinding + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: The Kubernetes Service's name + jsonPath: .spec.serviceRef.name + name: SERVICE-NAME + type: string + - description: The Kubernetes Service's port + jsonPath: .spec.serviceRef.port + name: SERVICE-PORT + type: string + - description: The AWS TargetGroup's TargetType + jsonPath: .spec.targetType + name: TARGET-TYPE + type: string + - description: The AWS TargetGroup's Amazon Resource Name + jsonPath: .spec.targetGroupARN + name: ARN + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: TargetGroupBinding is the Schema for the TargetGroupBinding API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: TargetGroupBindingSpec defines the desired state of TargetGroupBinding + properties: + networking: + description: networking provides the networking setup for ELBV2 LoadBalancer + to access targets in TargetGroup. + properties: + ingress: + description: List of ingress rules to allow ELBV2 LoadBalancer + to access targets in TargetGroup. + items: + properties: + from: + description: |- + List of peers which should be able to access the targets in TargetGroup. + At least one NetworkingPeer should be specified. + items: + description: NetworkingPeer defines the source/destination + peer for networking rules. + properties: + ipBlock: + description: |- + IPBlock defines an IPBlock peer. + If specified, none of the other fields can be set. + properties: + cidr: + description: |- + CIDR is the network CIDR. + Both IPV4 or IPV6 CIDR are accepted. + type: string + required: + - cidr + type: object + securityGroup: + description: |- + SecurityGroup defines a SecurityGroup peer. + If specified, none of the other fields can be set. + properties: + groupID: + description: GroupID is the EC2 SecurityGroupID. + type: string + required: + - groupID + type: object + type: object + type: array + ports: + description: |- + List of ports which should be made accessible on the targets in TargetGroup. + If ports is empty or unspecified, it defaults to all ports with TCP. + items: + properties: + port: + anyOf: + - type: integer + - type: string + description: |- + The port which traffic must match. + When NodePort endpoints(instance TargetType) is used, this must be a numerical port. + When Port endpoints(ip TargetType) is used, this can be either numerical or named port on pods. + if port is unspecified, it defaults to all ports. + x-kubernetes-int-or-string: true + protocol: + description: |- + The protocol which traffic must match. + If protocol is unspecified, it defaults to TCP. + enum: + - TCP + - UDP + type: string + type: object + type: array + required: + - from + - ports + type: object + type: array + type: object + serviceRef: + description: serviceRef is a reference to a Kubernetes Service and + ServicePort. + properties: + name: + description: Name is the name of the Service. + type: string + port: + anyOf: + - type: integer + - type: string + description: Port is the port of the ServicePort. + x-kubernetes-int-or-string: true + required: + - name + - port + type: object + targetGroupARN: + description: targetGroupARN is the Amazon Resource Name (ARN) for + the TargetGroup. + type: string + targetType: + description: targetType is the TargetType of TargetGroup. If unspecified, + it will be automatically inferred. + enum: + - instance + - ip + type: string + required: + - serviceRef + - targetGroupARN + type: object + status: + description: TargetGroupBindingStatus defines the observed state of TargetGroupBinding + properties: + observedGeneration: + description: The generation observed by the TargetGroupBinding controller. + format: int64 + type: integer + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - description: The Kubernetes Service's name + jsonPath: .spec.serviceRef.name + name: SERVICE-NAME + type: string + - description: The Kubernetes Service's port + jsonPath: .spec.serviceRef.port + name: SERVICE-PORT + type: string + - description: The AWS TargetGroup's TargetType + jsonPath: .spec.targetType + name: TARGET-TYPE + type: string + - description: The AWS TargetGroup's Amazon Resource Name + jsonPath: .spec.targetGroupARN + name: ARN + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: TargetGroupBinding is the Schema for the TargetGroupBinding API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: TargetGroupBindingSpec defines the desired state of TargetGroupBinding + properties: + ipAddressType: + description: ipAddressType specifies whether the target group is of + type IPv4 or IPv6. If unspecified, it will be automatically inferred. + enum: + - ipv4 + - ipv6 + type: string + networking: + description: networking defines the networking rules to allow ELBV2 + LoadBalancer to access targets in TargetGroup. + properties: + ingress: + description: List of ingress rules to allow ELBV2 LoadBalancer + to access targets in TargetGroup. + items: + description: NetworkingIngressRule defines a particular set + of traffic that is allowed to access TargetGroup's targets. + properties: + from: + description: |- + List of peers which should be able to access the targets in TargetGroup. + At least one NetworkingPeer should be specified. + items: + description: NetworkingPeer defines the source/destination + peer for networking rules. + properties: + ipBlock: + description: |- + IPBlock defines an IPBlock peer. + If specified, none of the other fields can be set. + properties: + cidr: + description: |- + CIDR is the network CIDR. + Both IPV4 or IPV6 CIDR are accepted. + type: string + required: + - cidr + type: object + securityGroup: + description: |- + SecurityGroup defines a SecurityGroup peer. + If specified, none of the other fields can be set. + properties: + groupID: + description: GroupID is the EC2 SecurityGroupID. + type: string + required: + - groupID + type: object + type: object + type: array + ports: + description: |- + List of ports which should be made accessible on the targets in TargetGroup. + If ports is empty or unspecified, it defaults to all ports with TCP. + items: + description: NetworkingPort defines the port and protocol + for networking rules. + properties: + port: + anyOf: + - type: integer + - type: string + description: |- + The port which traffic must match. + When NodePort endpoints(instance TargetType) is used, this must be a numerical port. + When Port endpoints(ip TargetType) is used, this can be either numerical or named port on pods. + if port is unspecified, it defaults to all ports. + x-kubernetes-int-or-string: true + protocol: + description: |- + The protocol which traffic must match. + If protocol is unspecified, it defaults to TCP. + enum: + - TCP + - UDP + type: string + type: object + type: array + required: + - from + - ports + type: object + type: array + type: object + nodeSelector: + description: node selector for instance type target groups to only + register certain nodes + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + serviceRef: + description: serviceRef is a reference to a Kubernetes Service and + ServicePort. + properties: + name: + description: Name is the name of the Service. + type: string + port: + anyOf: + - type: integer + - type: string + description: Port is the port of the ServicePort. + x-kubernetes-int-or-string: true + required: + - name + - port + type: object + targetGroupARN: + description: targetGroupARN is the Amazon Resource Name (ARN) for + the TargetGroup. + minLength: 1 + type: string + targetType: + description: targetType is the TargetType of TargetGroup. If unspecified, + it will be automatically inferred. + enum: + - instance + - ip + type: string + vpcID: + description: VpcID is the VPC of the TargetGroup. If unspecified, + it will be automatically inferred. + type: string + required: + - serviceRef + - targetGroupARN + type: object + status: + description: TargetGroupBindingStatus defines the observed state of TargetGroupBinding + properties: + observedGeneration: + description: The generation observed by the TargetGroupBinding controller. + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/backing-services/aws-load-balancer-controller/school-stage-eks.values.yaml b/backing-services/aws-load-balancer-controller/school-stage-eks.values.yaml new file mode 100644 index 0000000..3ff61ef --- /dev/null +++ b/backing-services/aws-load-balancer-controller/school-stage-eks.values.yaml @@ -0,0 +1,14 @@ +replicaCount: 2 + +clusterName: schoolbuses + +# cluster contains configurations specific to the kubernetes cluster +cluster: + # Cluster DNS domain (required for requesting TLS certificates) + dnsDomain: alpharoute.dev + +serviceAccount: + name: aws-load-balancer-aws-load-balancer-controller + create: true + annotations: + eks.amazonaws.com/role-arn: "arn:aws:iam::889565812003:role/schoolbuses_Cluster_IAM" \ No newline at end of file diff --git a/backing-services/aws-load-balancer-controller/templates/NOTES.txt b/backing-services/aws-load-balancer-controller/templates/NOTES.txt new file mode 100644 index 0000000..04e98e0 --- /dev/null +++ b/backing-services/aws-load-balancer-controller/templates/NOTES.txt @@ -0,0 +1 @@ +AWS Load Balancer controller installed! diff --git a/backing-services/aws-load-balancer-controller/templates/_helpers.tpl b/backing-services/aws-load-balancer-controller/templates/_helpers.tpl new file mode 100644 index 0000000..d916b99 --- /dev/null +++ b/backing-services/aws-load-balancer-controller/templates/_helpers.tpl @@ -0,0 +1,131 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "aws-load-balancer-controller.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "aws-load-balancer-controller.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "aws-load-balancer-controller.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Chart name prefix for resource names +Strip the "-controller" suffix from the default .Chart.Name if the nameOverride is not specified. +This enables using a shorter name for the resources, for example aws-load-balancer-webhook. +*/}} +{{- define "aws-load-balancer-controller.namePrefix" -}} +{{- $defaultNamePrefix := .Chart.Name | trimSuffix "-controller" -}} +{{- default $defaultNamePrefix .Values.nameOverride | trunc 42 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "aws-load-balancer-controller.labels" -}} +{{- if eq (default "helm" .Values.creator) "helm" -}} +app.kubernetes.io/managed-by: {{ .Release.Service }} +helm.sh/chart: {{ include "aws-load-balancer-controller.chart" . }} +{{- end }} +{{ include "aws-load-balancer-controller.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +{{- if .Values.additionalLabels }} +{{ toYaml .Values.additionalLabels }} +{{- end -}} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "aws-load-balancer-controller.selectorLabels" -}} +app.kubernetes.io/name: {{ include "aws-load-balancer-controller.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "aws-load-balancer-controller.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "aws-load-balancer-controller.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the webhook service +*/}} +{{- define "aws-load-balancer-controller.webhookService" -}} +{{- printf "%s-webhook-service" (include "aws-load-balancer-controller.namePrefix" .) -}} +{{- end -}} + +{{/* +Create the name of the webhook cert secret +*/}} +{{- define "aws-load-balancer-controller.webhookCertSecret" -}} +{{- printf "%s-tls" (include "aws-load-balancer-controller.namePrefix" .) -}} +{{- end -}} + +{{/* +Generate certificates for webhook +*/}} +{{- define "aws-load-balancer-controller.webhookCerts" -}} +{{- $serviceName := (include "aws-load-balancer-controller.webhookService" .) -}} +{{- $secretName := (include "aws-load-balancer-controller.webhookCertSecret" .) -}} +{{- $secret := lookup "v1" "Secret" .Release.Namespace $secretName -}} +{{- if (and .Values.webhookTLS.caCert .Values.webhookTLS.cert .Values.webhookTLS.key) -}} +caCert: {{ .Values.webhookTLS.caCert | b64enc }} +clientCert: {{ .Values.webhookTLS.cert | b64enc }} +clientKey: {{ .Values.webhookTLS.key | b64enc }} +{{- else if and .Values.keepTLSSecret $secret -}} +caCert: {{ index $secret.data "ca.crt" }} +clientCert: {{ index $secret.data "tls.crt" }} +clientKey: {{ index $secret.data "tls.key" }} +{{- else -}} +{{- $altNames := list (printf "%s.%s" $serviceName .Release.Namespace) (printf "%s.%s.svc" $serviceName .Release.Namespace) (printf "%s.%s.svc.%s" $serviceName .Release.Namespace .Values.cluster.dnsDomain) -}} +{{- $ca := genCA "aws-load-balancer-controller-ca" 3650 -}} +{{- $cert := genSignedCert (include "aws-load-balancer-controller.fullname" .) nil $altNames 3650 $ca -}} +caCert: {{ $ca.Cert | b64enc }} +clientCert: {{ $cert.Cert | b64enc }} +clientKey: {{ $cert.Key | b64enc }} +{{- end -}} +{{- end -}} + +{{/* +Convert map to comma separated key=value string +*/}} +{{- define "aws-load-balancer-controller.convertMapToCsv" -}} +{{- range $key, $value := . -}} {{ $key }}={{ $value }}, {{- end -}} +{{- end -}} + +{{/* +Create the name of the ingressClassParams +*/}} +{{- define "aws-load-balancer-controller.ingressClassParamsName" -}} +{{ default .Values.ingressClass .Values.ingressClassParams.name }} +{{- end -}} diff --git a/backing-services/aws-load-balancer-controller/templates/deployment.yaml b/backing-services/aws-load-balancer-controller/templates/deployment.yaml new file mode 100644 index 0000000..70fe8d5 --- /dev/null +++ b/backing-services/aws-load-balancer-controller/templates/deployment.yaml @@ -0,0 +1,259 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "aws-load-balancer-controller.fullname" . }} + namespace: {{ .Release.Namespace }} + {{- if .Values.deploymentAnnotations }} + annotations: + {{- toYaml .Values.deploymentAnnotations | nindent 4 }} + {{- end }} + labels: + {{- include "aws-load-balancer-controller.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "aws-load-balancer-controller.selectorLabels" . | nindent 6 }} + {{- with .Values.updateStrategy }} + strategy: + {{ toYaml . | nindent 4 }} + {{- end }} + template: + metadata: + labels: + {{- include "aws-load-balancer-controller.selectorLabels" . | nindent 8 }} + {{- if .Values.podLabels }} + {{- toYaml .Values.podLabels | nindent 8 }} + {{- end }} + annotations: + {{- if not .Values.serviceMonitor.enabled }} + prometheus.io/scrape: "true" + prometheus.io/port: "{{ (split ":" .Values.metricsBindAddr)._1 | default 8080 }}" + {{- end}} + {{- if .Values.podAnnotations }} + {{- toYaml .Values.podAnnotations | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.runtimeClassName }} + runtimeClassName: {{ .Values.runtimeClassName }} + {{- end }} + serviceAccountName: {{ include "aws-load-balancer-controller.serviceAccountName" . }} + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: {{ template "aws-load-balancer-controller.webhookCertSecret" . }} + {{- with .Values.extraVolumes }} + {{ toYaml . | nindent 6 }} + {{- end }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- if .Values.hostNetwork }} + hostNetwork: true + {{- end }} + {{- if .Values.dnsPolicy }} + dnsPolicy: {{ .Values.dnsPolicy }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + args: + - --cluster-name={{ required "Chart cannot be installed without a valid clusterName!" (tpl (default "" .Values.clusterName) .) }} + {{- if .Values.ingressClass }} + - --ingress-class={{ .Values.ingressClass }} + {{- end }} + {{- $region := tpl (default "" .Values.region) . }} + {{- if $region }} + - --aws-region={{ .Values.region }} + {{- end }} + {{- $vpcID := tpl (default "" .Values.vpcId) . }} + {{- if $vpcID }} + - --aws-vpc-id={{ $vpcID }} + {{- end }} + {{- if .Values.awsApiEndpoints }} + - --aws-api-endpoints={{ .Values.awsApiEndpoints }} + {{- end }} + {{- if .Values.awsApiThrottle }} + - --aws-api-throttle={{ join "," .Values.awsApiThrottle }} + {{- end }} + {{- if .Values.awsMaxRetries }} + - --aws-max-retries={{ .Values.awsMaxRetries }} + {{- end }} + {{- if kindIs "bool" .Values.enablePodReadinessGateInject }} + - --enable-pod-readiness-gate-inject={{ .Values.enablePodReadinessGateInject }} + {{- end }} + {{- if kindIs "bool" .Values.enableShield }} + - --enable-shield={{ .Values.enableShield }} + {{- end }} + {{- if kindIs "bool" .Values.enableWaf }} + - --enable-waf={{ .Values.enableWaf }} + {{- end }} + {{- if kindIs "bool" .Values.enableWafv2 }} + - --enable-wafv2={{ .Values.enableWafv2 }} + {{- end }} + {{- if .Values.metricsBindAddr }} + - --metrics-bind-addr={{ .Values.metricsBindAddr }} + {{- end }} + {{- if .Values.ingressMaxConcurrentReconciles }} + - --ingress-max-concurrent-reconciles={{ .Values.ingressMaxConcurrentReconciles }} + {{- end }} + {{- if .Values.serviceMaxConcurrentReconciles }} + - --service-max-concurrent-reconciles={{ .Values.serviceMaxConcurrentReconciles }} + {{- end }} + {{- if .Values.targetgroupbindingMaxConcurrentReconciles }} + - --targetgroupbinding-max-concurrent-reconciles={{ .Values.targetgroupbindingMaxConcurrentReconciles }} + {{- end }} + {{- if .Values.targetgroupbindingMaxExponentialBackoffDelay }} + - --targetgroupbinding-max-exponential-backoff-delay={{ .Values.targetgroupbindingMaxExponentialBackoffDelay }} + {{- end }} + {{- if .Values.logLevel }} + - --log-level={{ .Values.logLevel }} + {{- end }} + {{- if .Values.webhookBindPort }} + - --webhook-bind-port={{ .Values.webhookBindPort }} + {{- end }} + {{- if .Values.syncPeriod }} + - --sync-period={{ .Values.syncPeriod }} + {{- end }} + {{- if .Values.watchNamespace }} + - --watch-namespace={{ .Values.watchNamespace }} + {{- end }} + {{- if kindIs "bool" .Values.disableIngressClassAnnotation }} + - --disable-ingress-class-annotation={{ .Values.disableIngressClassAnnotation }} + {{- end }} + {{- if kindIs "bool" .Values.disableIngressGroupNameAnnotation }} + - --disable-ingress-group-name-annotation={{ .Values.disableIngressGroupNameAnnotation }} + {{- end }} + {{- if kindIs "bool" .Values.tolerateNonExistentBackendService }} + - --tolerate-non-existent-backend-service={{ .Values.tolerateNonExistentBackendService }} + {{- end }} + {{- if kindIs "bool" .Values.tolerateNonExistentBackendAction }} + - --tolerate-non-existent-backend-action={{ .Values.tolerateNonExistentBackendAction }} + {{- end }} + {{- if .Values.defaultSSLPolicy }} + - --default-ssl-policy={{ .Values.defaultSSLPolicy }} + {{- end }} + {{- if .Values.externalManagedTags }} + - --external-managed-tags={{ join "," .Values.externalManagedTags }} + {{- end }} + {{- if .Values.defaultTags }} + - --default-tags={{ include "aws-load-balancer-controller.convertMapToCsv" .Values.defaultTags | trimSuffix "," }} + {{- end }} + {{- if kindIs "bool" .Values.enableEndpointSlices }} + - --enable-endpoint-slices={{ .Values.enableEndpointSlices }} + {{- end }} + {{- if kindIs "bool" .Values.enableBackendSecurityGroup }} + - --enable-backend-security-group={{ .Values.enableBackendSecurityGroup }} + {{- end }} + {{- if .Values.backendSecurityGroup }} + - --backend-security-group={{ .Values.backendSecurityGroup }} + {{- end }} + {{- if kindIs "bool" .Values.disableRestrictedSecurityGroupRules }} + - --disable-restricted-sg-rules={{ .Values.disableRestrictedSecurityGroupRules }} + {{- end }} + {{- if .Values.controllerConfig.featureGates }} + - --feature-gates={{ include "aws-load-balancer-controller.convertMapToCsv" .Values.controllerConfig.featureGates | trimSuffix "," }} + {{- end }} + {{- if ne .Values.defaultTargetType "instance" }} + - --default-target-type={{ .Values.defaultTargetType }} + {{- end }} + {{- if .Values.serviceTargetENISGTags }} + - --service-target-eni-security-group-tags={{ .Values.serviceTargetENISGTags }} + {{- end }} + {{- if .Values.certDiscovery.allowedCertificateAuthorityARNs }} + - --allowed-certificate-authority-arns={{ .Values.certDiscovery.allowedCertificateAuthorityARNs }} + {{- end }} + {{- if .Values.loadBalancerClass }} + - --load-balancer-class={{ .Values.loadBalancerClass }} + {{- end }} + {{- if or .Values.env .Values.envSecretName .Values.envFrom }} + env: + {{- if .Values.env}} + {{- range $key, $value := .Values.env }} + - name: {{ $key }} + value: "{{ $value }}" + {{- end }} + {{- end }} + {{- if .Values.envFrom }} + {{ .Values.envFrom | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.envSecretName }} + - name: AWS_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: {{ .Values.envSecretName }} + key: key_id + optional: true + - name: AWS_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: {{ .Values.envSecretName }} + key: access_key + optional: true + {{- end }} + {{- end }} + securityContext: + {{- toYaml .Values.securityContext | nindent 10 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + volumeMounts: + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true + {{- with .Values.extraVolumeMounts }} + {{ toYaml . | nindent 8 }} + {{- end }} + ports: + - name: webhook-server + containerPort: {{ .Values.webhookBindPort | default 9443 }} + protocol: TCP + - name: metrics-server + containerPort: {{ (split ":" .Values.metricsBindAddr)._1 | default 8080 }} + protocol: TCP + resources: + {{- toYaml .Values.resources | nindent 10 }} + {{- with .Values.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 10 }} + {{- end }} + terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.affinity }} + affinity: + {{- toYaml .Values.affinity | nindent 8 }} + {{- else if .Values.configureDefaultAffinity }} + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - {{ include "aws-load-balancer-controller.name" . }} + topologyKey: kubernetes.io/hostname + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName | quote }} + {{- end }} + {{- with .Values.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/backing-services/aws-load-balancer-controller/templates/hpa.yaml b/backing-services/aws-load-balancer-controller/templates/hpa.yaml new file mode 100644 index 0000000..2ce96ef --- /dev/null +++ b/backing-services/aws-load-balancer-controller/templates/hpa.yaml @@ -0,0 +1,34 @@ +{{- if .Values.autoscaling.enabled }} +{{- if (semverCompare ">=1.23-0" .Capabilities.KubeVersion.GitVersion)}} +apiVersion: autoscaling/v2 +{{- else }} +apiVersion: autoscaling/v2beta2 +{{- end }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "aws-load-balancer-controller.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "aws-load-balancer-controller.labels" . | nindent 4 }} + annotations: + {{- .Values.annotations | toYaml | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "aws-load-balancer-controller.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ required "A valid .Values.autoscaling.maxReplicas value is required" .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + type: Utilization + {{- end }} + {{- if .Values.autoscaling.autoscaleBehavior }} + behavior: {{ toYaml .Values.autoscaling.autoscaleBehavior | nindent 4 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/backing-services/aws-load-balancer-controller/templates/ingressclass.yaml b/backing-services/aws-load-balancer-controller/templates/ingressclass.yaml new file mode 100644 index 0000000..feed802 --- /dev/null +++ b/backing-services/aws-load-balancer-controller/templates/ingressclass.yaml @@ -0,0 +1,41 @@ +{{- /* +[caution] AWSLoadBalancerController <= v2.4.2 expects referenced IngressClassParams to be created before IngressClass. +We use a list here to force Helm create IngressClassParams(if any) before apply any IngressClass changes. +*/}} +{{- if .Values.createIngressClassResource }} +apiVersion: v1 +kind: List +metadata: + name: ingress-class +items: +{{- if .Values.ingressClassParams.create }} +- apiVersion: elbv2.k8s.aws/v1beta1 + kind: IngressClassParams + metadata: + name: {{ include "aws-load-balancer-controller.ingressClassParamsName" . }} + labels: + {{- include "aws-load-balancer-controller.labels" . | nindent 6 }} + {{- with .Values.ingressClassParams.spec }} + spec: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} +- apiVersion: networking.k8s.io/v1 + kind: IngressClass + metadata: + name: {{ .Values.ingressClass }} + labels: + {{- include "aws-load-balancer-controller.labels" . | nindent 6 }} + {{- if .Values.ingressClassConfig.default }} + annotations: + ingressclass.kubernetes.io/is-default-class: "true" + {{- end }} + spec: + controller: ingress.k8s.aws/alb + {{- if or .Values.ingressClassParams.name (and .Values.ingressClassParams.create .Values.ingressClassParams.spec) }} + parameters: + apiGroup: elbv2.k8s.aws + kind: IngressClassParams + name: {{ include "aws-load-balancer-controller.ingressClassParamsName" . }} + {{- end }} +{{- end }} diff --git a/backing-services/aws-load-balancer-controller/templates/pdb.yaml b/backing-services/aws-load-balancer-controller/templates/pdb.yaml new file mode 100644 index 0000000..f72abaf --- /dev/null +++ b/backing-services/aws-load-balancer-controller/templates/pdb.yaml @@ -0,0 +1,14 @@ +{{- if and .Values.podDisruptionBudget (gt (int .Values.replicaCount) 1) }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "aws-load-balancer-controller.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "aws-load-balancer-controller.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "aws-load-balancer-controller.selectorLabels" . | nindent 6 }} + {{- toYaml .Values.podDisruptionBudget | nindent 2 }} +{{- end }} diff --git a/backing-services/aws-load-balancer-controller/templates/rbac.yaml b/backing-services/aws-load-balancer-controller/templates/rbac.yaml new file mode 100644 index 0000000..fc3bda6 --- /dev/null +++ b/backing-services/aws-load-balancer-controller/templates/rbac.yaml @@ -0,0 +1,104 @@ +{{- if .Values.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "aws-load-balancer-controller.fullname" . }}-leader-election-role + namespace: {{ .Release.Namespace }} + labels: + {{- include "aws-load-balancer-controller.labels" . | nindent 4 }} +rules: +- apiGroups: [""] + resources: [configmaps] + verbs: [create] +- apiGroups: [""] + resources: [configmaps] + resourceNames: [aws-load-balancer-controller-leader] + verbs: [get, patch, update] +- apiGroups: + - "coordination.k8s.io" + resources: + - leases + verbs: + - create +- apiGroups: + - "coordination.k8s.io" + resources: + - leases + resourceNames: + - aws-load-balancer-controller-leader + verbs: + - get + - update + - patch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "aws-load-balancer-controller.fullname" . }}-leader-election-rolebinding + namespace: {{ .Release.Namespace }} + labels: + {{- include "aws-load-balancer-controller.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "aws-load-balancer-controller.fullname" . }}-leader-election-role +subjects: +- kind: ServiceAccount + name: {{ template "aws-load-balancer-controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "aws-load-balancer-controller.fullname" . }}-role + labels: + {{- include "aws-load-balancer-controller.labels" . | nindent 4 }} +rules: +- apiGroups: ["elbv2.k8s.aws"] + resources: [targetgroupbindings] + verbs: [create, delete, get, list, patch, update, watch] +- apiGroups: ["elbv2.k8s.aws"] + resources: [ingressclassparams] + verbs: [get, list, watch] +- apiGroups: [""] + resources: [events] + verbs: [create, patch] +- apiGroups: [""] + resources: [pods] + verbs: [get, list, watch] +- apiGroups: ["networking.k8s.io"] + resources: [ingressclasses] + verbs: [get, list, watch] +- apiGroups: ["", "extensions", "networking.k8s.io"] + resources: [services, ingresses] + verbs: [get, list, patch, update, watch] +- apiGroups: [""] + resources: [nodes, namespaces, endpoints] + verbs: [get, list, watch] +{{- if .Values.clusterSecretsPermissions.allowAllSecrets }} +- apiGroups: [""] + resources: [secrets] + verbs: [get, list, watch] +{{- end }} +- apiGroups: ["elbv2.k8s.aws", "", "extensions", "networking.k8s.io"] + resources: [targetgroupbindings/status, pods/status, services/status, ingresses/status] + verbs: [update, patch] +- apiGroups: ["discovery.k8s.io"] + resources: [endpointslices] + verbs: [get, list, watch] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "aws-load-balancer-controller.fullname" . }}-rolebinding + labels: + {{- include "aws-load-balancer-controller.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "aws-load-balancer-controller.fullname" . }}-role +subjects: +- kind: ServiceAccount + name: {{ template "aws-load-balancer-controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/backing-services/aws-load-balancer-controller/templates/service.yaml b/backing-services/aws-load-balancer-controller/templates/service.yaml new file mode 100644 index 0000000..aad0044 --- /dev/null +++ b/backing-services/aws-load-balancer-controller/templates/service.yaml @@ -0,0 +1,41 @@ +{{- if.Values.serviceMonitor.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "aws-load-balancer-controller.fullname" . }} + namespace: {{ .Release.Namespace }} + {{- with .Values.serviceAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "aws-load-balancer-controller.labels" . | nindent 4 }} +spec: + ports: + - port: 8080 + name: metrics-server + targetPort: metrics-server + selector: + {{- include "aws-load-balancer-controller.selectorLabels" . | nindent 4 }} +--- +{{- end }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "aws-load-balancer-controller.webhookService" . }} + namespace: {{ .Release.Namespace }} + {{- with .Values.serviceAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "aws-load-balancer-controller.labels" . | nindent 4 }} + app.kubernetes.io/component: webhook + prometheus.io/service-monitor: "false" +spec: + ports: + - port: 443 + name: webhook-server + targetPort: webhook-server + selector: + {{- include "aws-load-balancer-controller.selectorLabels" . | nindent 4 }} diff --git a/backing-services/aws-load-balancer-controller/templates/serviceaccount.yaml b/backing-services/aws-load-balancer-controller/templates/serviceaccount.yaml new file mode 100644 index 0000000..f4cfcac --- /dev/null +++ b/backing-services/aws-load-balancer-controller/templates/serviceaccount.yaml @@ -0,0 +1,18 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "aws-load-balancer-controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "aws-load-balancer-controller.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +{{- with .Values.serviceAccount.imagePullSecrets }} +imagePullSecrets: +{{ toYaml . }} +{{- end }} +{{- end -}} diff --git a/backing-services/aws-load-balancer-controller/templates/servicemonitor.yaml b/backing-services/aws-load-balancer-controller/templates/servicemonitor.yaml new file mode 100644 index 0000000..0454558 --- /dev/null +++ b/backing-services/aws-load-balancer-controller/templates/servicemonitor.yaml @@ -0,0 +1,43 @@ +{{- if.Values.serviceMonitor.enabled -}} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "aws-load-balancer-controller.fullname" . }} + namespace: {{ default .Release.Namespace .Values.serviceMonitor.namespace }} + labels: + {{- include "aws-load-balancer-controller.labels" . | nindent 4 }} + {{- with .Values.serviceMonitor.additionalLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + jobLabel: app.kubernetes.io/instance + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + {{- include "aws-load-balancer-controller.selectorLabels" . | nindent 6 }} + matchExpressions: + - key: prometheus.io/service-monitor + operator: NotIn + values: + - "false" + endpoints: + - port: metrics-server + path: /metrics + scheme: http + {{- with .Values.serviceMonitor.interval }} + interval: {{ . }} + {{- end }} + {{- with .Values.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ . }} + {{- end }} + {{- with .Values.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end -}} diff --git a/backing-services/aws-load-balancer-controller/templates/webhook.yaml b/backing-services/aws-load-balancer-controller/templates/webhook.yaml new file mode 100644 index 0000000..666770d --- /dev/null +++ b/backing-services/aws-load-balancer-controller/templates/webhook.yaml @@ -0,0 +1,248 @@ +{{ $tls := fromYaml ( include "aws-load-balancer-controller.webhookCerts" . ) }} +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: +{{- if $.Values.enableCertManager }} + annotations: + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ template "aws-load-balancer-controller.namePrefix" . }}-serving-cert +{{- end }} + name: {{ include "aws-load-balancer-controller.namePrefix" . }}-webhook + labels: + {{- include "aws-load-balancer-controller.labels" . | nindent 4 }} +webhooks: +- clientConfig: + {{ if not $.Values.enableCertManager -}} + caBundle: {{ $tls.caCert }} + {{ end }} + service: + name: {{ template "aws-load-balancer-controller.webhookService" . }} + namespace: {{ $.Release.Namespace }} + path: /mutate-v1-pod + failurePolicy: Fail + name: mpod.elbv2.k8s.aws + admissionReviewVersions: + - v1beta1 + namespaceSelector: + matchExpressions: + {{ if .Values.webhookNamespaceSelectors }} + {{ toYaml .Values.webhookNamespaceSelectors | nindent 4 }} + {{ else }} + - key: elbv2.k8s.aws/pod-readiness-gate-inject + operator: In + values: + - enabled + {{ end }} + objectSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: NotIn + values: + - {{ include "aws-load-balancer-controller.name" . }} + {{- if .Values.objectSelector.matchExpressions }} + {{- toYaml .Values.objectSelector.matchExpressions | nindent 4 }} + {{- end }} + {{- if .Values.objectSelector.matchLabels }} + matchLabels: + {{- toYaml .Values.objectSelector.matchLabels | nindent 6 }} + {{- end }} + rules: + - apiGroups: + - "" + apiVersions: + - v1 + operations: + - CREATE + resources: + - pods + sideEffects: None +{{- if .Values.enableServiceMutatorWebhook }} +- clientConfig: + {{ if not $.Values.enableCertManager -}} + caBundle: {{ $tls.caCert }} + {{ end }} + service: + name: {{ template "aws-load-balancer-controller.webhookService" . }} + namespace: {{ $.Release.Namespace }} + path: /mutate-v1-service + failurePolicy: {{ .Values.serviceMutatorWebhookConfig.failurePolicy }} + name: mservice.elbv2.k8s.aws + admissionReviewVersions: + - v1beta1 + objectSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: NotIn + values: + - {{ include "aws-load-balancer-controller.name" . }} + {{- if .Values.serviceMutatorWebhookConfig.objectSelector.matchExpressions }} + {{- toYaml .Values.serviceMutatorWebhookConfig.objectSelector.matchExpressions | nindent 4 }} + {{- end }} + + {{- if .Values.serviceMutatorWebhookConfig.objectSelector.matchLabels }} + matchLabels: + {{- toYaml .Values.serviceMutatorWebhookConfig.objectSelector.matchLabels | nindent 6 }} + {{- end }} + rules: + - apiGroups: + - "" + apiVersions: + - v1 + operations: + {{- toYaml .Values.serviceMutatorWebhookConfig.operations | nindent 4 }} + resources: + - services + sideEffects: None +{{- end }} +- clientConfig: + {{ if not $.Values.enableCertManager -}} + caBundle: {{ $tls.caCert }} + {{ end }} + service: + name: {{ template "aws-load-balancer-controller.webhookService" . }} + namespace: {{ $.Release.Namespace }} + path: /mutate-elbv2-k8s-aws-v1beta1-targetgroupbinding + failurePolicy: Fail + name: mtargetgroupbinding.elbv2.k8s.aws + admissionReviewVersions: + - v1beta1 + rules: + - apiGroups: + - elbv2.k8s.aws + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - targetgroupbindings + sideEffects: None +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: +{{- if $.Values.enableCertManager }} + annotations: + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ template "aws-load-balancer-controller.namePrefix" . }}-serving-cert +{{- end }} + name: {{ include "aws-load-balancer-controller.namePrefix" . }}-webhook + labels: + {{- include "aws-load-balancer-controller.labels" . | nindent 4 }} +webhooks: +- clientConfig: + {{ if not $.Values.enableCertManager -}} + caBundle: {{ $tls.caCert }} + {{ end }} + service: + name: {{ template "aws-load-balancer-controller.webhookService" . }} + namespace: {{ $.Release.Namespace }} + path: /validate-elbv2-k8s-aws-v1beta1-ingressclassparams + failurePolicy: Fail + name: vingressclassparams.elbv2.k8s.aws + admissionReviewVersions: + - v1beta1 + objectSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: NotIn + values: + - {{ include "aws-load-balancer-controller.name" . }} + rules: + - apiGroups: + - elbv2.k8s.aws + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - ingressclassparams + sideEffects: None +- clientConfig: + {{ if not $.Values.enableCertManager -}} + caBundle: {{ $tls.caCert }} + {{ end }} + service: + name: {{ template "aws-load-balancer-controller.webhookService" . }} + namespace: {{ $.Release.Namespace }} + path: /validate-elbv2-k8s-aws-v1beta1-targetgroupbinding + failurePolicy: Fail + name: vtargetgroupbinding.elbv2.k8s.aws + admissionReviewVersions: + - v1beta1 + rules: + - apiGroups: + - elbv2.k8s.aws + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - targetgroupbindings + sideEffects: None +- clientConfig: + {{ if not $.Values.enableCertManager -}} + caBundle: {{ $tls.caCert }} + {{ end }} + service: + name: {{ template "aws-load-balancer-controller.webhookService" . }} + namespace: {{ $.Release.Namespace }} + path: /validate-networking-v1-ingress + failurePolicy: Fail + matchPolicy: Equivalent + name: vingress.elbv2.k8s.aws + admissionReviewVersions: + - v1beta1 + rules: + - apiGroups: + - networking.k8s.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - ingresses + sideEffects: None +--- +{{- if not $.Values.enableCertManager }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "aws-load-balancer-controller.webhookCertSecret" . }} + namespace: {{ .Release.Namespace }} + labels: +{{ include "aws-load-balancer-controller.labels" . | indent 4 }} +type: kubernetes.io/tls +data: + ca.crt: {{ $tls.caCert }} + tls.crt: {{ $tls.clientCert }} + tls.key: {{ $tls.clientKey }} +{{- else }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ template "aws-load-balancer-controller.namePrefix" . }}-serving-cert + namespace: {{ .Release.Namespace }} + labels: +{{ include "aws-load-balancer-controller.labels" . | indent 4 }} +spec: + dnsNames: + - {{ template "aws-load-balancer-controller.webhookService" . }}.{{ .Release.Namespace }}.svc + - {{ template "aws-load-balancer-controller.webhookService" . }}.{{ .Release.Namespace }}.svc.{{ .Values.cluster.dnsDomain }} + issuerRef: + kind: Issuer + name: {{ template "aws-load-balancer-controller.namePrefix" . }}-selfsigned-issuer + secretName: {{ template "aws-load-balancer-controller.webhookCertSecret" . }} +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: {{ template "aws-load-balancer-controller.namePrefix" . }}-selfsigned-issuer + namespace: {{ .Release.Namespace }} + labels: +{{ include "aws-load-balancer-controller.labels" . | indent 4 }} +spec: + selfSigned: {} +{{- end }} diff --git a/backing-services/aws-load-balancer-controller/values.yaml b/backing-services/aws-load-balancer-controller/values.yaml new file mode 100644 index 0000000..fda77a8 --- /dev/null +++ b/backing-services/aws-load-balancer-controller/values.yaml @@ -0,0 +1,430 @@ +# Default values for aws-load-balancer-controller. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 2 + +revisionHistoryLimit: 10 + +image: + repository: public.ecr.aws/eks/aws-load-balancer-controller + tag: v2.8.2 + pullPolicy: IfNotPresent + +runtimeClassName: "" +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +# AWS LBC only has 1 main working pod, other pods are just standby +# the purpose of enable hpa is to survive load induced failure by the calls to the aws-load-balancer-webhook-service +# since the calls from kube-apiserver are sent round-robin to all replicas, and the failure policy on those webhooks is Fail +# if the pods become overloaded and do not respond within the timeout that could block the creation of pods, targetgroupbindings or ingresses +# Please keep in mind that the controller pods have `priorityClassName: system-cluster-critical`, enabling HPA may lead to the eviction of other low-priority pods in the node +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 5 + targetCPUUtilizationPercentage: 80 + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: + eks.amazonaws.com/role-arn: "{{ .Values.serviceAccount.awsRoleArn }}" + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: + # Automount API credentials for a Service Account. + automountServiceAccountToken: true + # List of image pull secrets to add to the Service Account. + imagePullSecrets: + # - name: docker + +rbac: + # Specifies whether rbac resources should be created + create: true + +podSecurityContext: + fsGroup: 65534 + +securityContext: + # capabilities: + # drop: + # - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + allowPrivilegeEscalation: false + +# Time period for the controller pod to do a graceful shutdown +terminationGracePeriodSeconds: 10 + +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 + +# priorityClassName specifies the PriorityClass to indicate the importance of controller pods +# ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass +priorityClassName: system-cluster-critical + +nodeSelector: {} + +tolerations: [] + +# affinity specifies a custom affinity for the controller pods +affinity: {} + +# configureDefaultAffinity specifies whether to configure a default affinity for the controller pods to prevent +# co-location on the same node. This will get ignored if you specify a custom affinity configuration. +configureDefaultAffinity: true + +# topologySpreadConstraints is a stable feature of k8s v1.19 which provides the ability to +# control how Pods are spread across your cluster among failure-domains such as regions, zones, +# nodes, and other user-defined topology domains. +# +# more details here: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ +topologySpreadConstraints: {} + +updateStrategy: {} + # type: RollingUpdate + # rollingUpdate: + # maxSurge: 1 + # maxUnavailable: 1 + +# serviceAnnotations contains annotations to be added to the provisioned webhook service resource +serviceAnnotations: {} + +# deploymentAnnotations contains annotations for the controller deployment +deploymentAnnotations: {} + +podAnnotations: {} + +podLabels: {} + +# additionalLabels -- Labels to add to each object of the chart. +additionalLabels: {} + +# Enable cert-manager +enableCertManager: false + +# The name of the Kubernetes cluster. A non-empty value is required +clusterName: + +# cluster contains configurations specific to the kubernetes cluster +cluster: + # Cluster DNS domain (required for requesting TLS certificates) + dnsDomain: alpharoute.dev + +# The ingress class this controller will satisfy. If not specified, controller will match all +# ingresses without ingress class annotation and ingresses of type alb +ingressClass: alb + +# ingressClassParams specify the IngressCLassParams that enforce settings for a set of Ingresses when using with ingress Controller. +ingressClassParams: + create: true + # The name of ingressClassParams resource will be referred in ingressClass + name: + spec: {} + # Due to dependency issue, the validation webhook ignores this particular ingressClassParams resource. + # We recommend creating ingressClassParams resources separately after installing this chart and the + # controller is functional. + # + # You can set the specifications in the `helm install` command through `--set` or `--set-string` + # If you do want to specify in the values.yaml, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'spec:' + # + # namespaceSelector: + # matchLabels: + # group: + # scheme: + # ipAddressType: + # tags: + # loadBalancerAttributes: + # - key: + # value: + +# To use IngressClass resource instead of annotation, before you need to install the IngressClass resource pointing to controller. +# If specified as true, the IngressClass resource will be created. +createIngressClassResource: true + +# The AWS region for the kubernetes cluster. Set to use KIAM or kube2iam for example. +region: + +# The VPC ID for the Kubernetes cluster. Set this manually when your pods are unable to use the metadata service to determine this automatically +vpcId: + +# Custom AWS API Endpoints (serviceID1=URL1,serviceID2=URL2) +awsApiEndpoints: + +# awsApiThrottle specifies custom AWS API throttle settings (serviceID1:operationRegex1=rate:burst,serviceID2:operationRegex2=rate:burst) +# example: --set awsApiThrottle="{Elastic Load Balancing v2:RegisterTargets|DeregisterTargets=4:20,Elastic Load Balancing v2:.*=10:40}" +awsApiThrottle: + +# Maximum retries for AWS APIs (default 10) +awsMaxRetries: + +# Default target type. Used as the default value of the "alb.ingress.kubernetes.io/target-type" and +# "service.beta.kubernetes.io/aws-load-balancer-nlb-target-type" annotations. +# Possible values are "ip" and "instance" +# The value "ip" should be used for ENI-based CNIs, such as the Amazon VPC CNI, +# Calico with encapsulation disabled, or Cilium with masquerading disabled. +# The value "instance" should be used for overlay-based CNIs, such as Calico in VXLAN or IPIP mode or +# Cilium with masquerading enabled. +defaultTargetType: instance + +# If enabled, targetHealth readiness gate will get injected to the pod spec for the matching endpoint pods (default true) +enablePodReadinessGateInject: + +# Enable Shield addon for ALB (default true) +enableShield: + +# Enable WAF addon for ALB (default true) +enableWaf: + +# Enable WAF V2 addon for ALB (default true) +enableWafv2: + +# Maximum number of concurrently running reconcile loops for ingress (default 3) +ingressMaxConcurrentReconciles: + +# Set the controller log level - info(default), debug (default "info") +logLevel: + +# The address the metric endpoint binds to. (default ":8080") +metricsBindAddr: "" + +# The TCP port the Webhook server binds to. (default 9443) +webhookBindPort: + +# webhookTLS specifies TLS cert/key for the webhook +webhookTLS: + caCert: + cert: + key: + +# array of namespace selectors for the pod mutator webhook +webhookNamespaceSelectors: +# - key: elbv2.k8s.aws/pod-readiness-gate-inject +# operator: In +# values: +# - enabled + +# keepTLSSecret specifies whether to reuse existing TLS secret for chart upgrade +keepTLSSecret: true + +# Maximum number of concurrently running reconcile loops for service (default 3) +serviceMaxConcurrentReconciles: + +# Maximum number of concurrently running reconcile loops for targetGroupBinding +targetgroupbindingMaxConcurrentReconciles: + +# Maximum duration of exponential backoff for targetGroupBinding reconcile failures +targetgroupbindingMaxExponentialBackoffDelay: + +# Period at which the controller forces the repopulation of its local object stores. (default 10h0m0s) +syncPeriod: + +# Namespace the controller watches for updates to Kubernetes objects, If empty, all namespaces are watched. +watchNamespace: + +# disableIngressClassAnnotation disables the usage of kubernetes.io/ingress.class annotation, false by default +disableIngressClassAnnotation: + +# disableIngressGroupNameAnnotation disables the usage of alb.ingress.kubernetes.io/group.name annotation, false by default +disableIngressGroupNameAnnotation: + +# tolerateNonExistentBackendService permits rules which specify backend services that don't exist, true by default (When enabled, it will return 503 error if backend service not exist) +tolerateNonExistentBackendService: + +# tolerateNonExistentBackendAction permits rules which specify backend actions that don't exist, true by default (When enabled, it will return 503 error if backend action not exist) +tolerateNonExistentBackendAction: + +# defaultSSLPolicy specifies the default SSL policy to use for TLS/HTTPS listeners +defaultSSLPolicy: + +# Liveness probe configuration for the controller +livenessProbe: + failureThreshold: 2 + httpGet: + path: /healthz + port: 61779 + scheme: HTTP + initialDelaySeconds: 30 + timeoutSeconds: 10 + +# readiness probe configuration for the controller +readinessProbe: + failureThreshold: 2 + httpGet: + path: /readyz + port: 61779 + scheme: HTTP + successThreshold: 1 + initialDelaySeconds: 10 + timeoutSeconds: 10 + +# Environment variables to set for aws-load-balancer-controller pod. +# We strongly discourage programming access credentials in the controller environment. You should setup IRSA or +# comparable solutions like kube2iam, kiam etc instead. +env: + # ENV_1: "" + # ENV_2: "" + +# Use Environment variables credentials from Secret (aws-secret) for aws-load-balancer-controller pod similarly as The EBS CSI Driver does. +# envSecretName: aws-secret + +# Use envFrom to set environment variables from a Secret or ConfigMap +envFrom: + # valueFrom: + # - secretKeyRef: + # name: aws-load-balancer-controller + +# Specifies if aws-load-balancer-controller should be started in hostNetwork mode. +# This is required if using a custom CNI where the managed control plane nodes are unable to initiate +# network connections to the pods, for example using Calico CNI plugin on EKS. This is not required or +# recommended if using the Amazon VPC CNI plugin. +hostNetwork: false + +# Specifies the dnsPolicy that should be used for pods in the deployment +# +# This may need to be used to be changed given certain conditions. For instance, if one uses the cilium CNI +# with certain settings, one may need to set `hostNetwork: true` and webhooks won't work unless `dnsPolicy` +# is set to `ClusterFirstWithHostNet`. See https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy +dnsPolicy: + +# extraVolumeMounts are the additional volume mounts. This enables setting up IRSA on non-EKS Kubernetes cluster +extraVolumeMounts: + # - name: aws-iam-token + # mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount + # readOnly: true + +# extraVolumes for the extraVolumeMounts. Useful to mount a projected service account token for example. +extraVolumes: + # - name: aws-iam-token + # projected: + # defaultMode: 420 + # sources: + # - serviceAccountToken: + # audience: sts.amazonaws.com + # expirationSeconds: 86400 + # path: token + +# defaultTags are the tags to apply to all AWS resources managed by this controller +defaultTags: {} + # default_tag1: value1 + # default_tag2: value2 + +# podDisruptionBudget specifies the disruption budget for the controller pods. +# Disruption budget will be configured only when the replicaCount is greater than 1 +podDisruptionBudget: {} +# maxUnavailable: 1 + +# externalManagedTags is the list of tag keys on AWS resources that will be managed externally +externalManagedTags: [] + +# enableEndpointSlices enables k8s EndpointSlices for IP targets instead of Endpoints (default false) +enableEndpointSlices: + +# enableBackendSecurityGroup enables shared security group for backend traffic (default true) +enableBackendSecurityGroup: + +# backendSecurityGroup specifies backend security group id (default controller auto create backend security group) +backendSecurityGroup: + +# disableRestrictedSecurityGroupRules specifies whether to disable creating port-range restricted security group rules for traffic +disableRestrictedSecurityGroupRules: + +# controllerConfig specifies controller configuration +controllerConfig: + # featureGates set of key: value pairs that describe AWS load balance controller features + featureGates: {} + # ListenerRulesTagging: true + # WeightedTargetGroups: true + # ServiceTypeLoadBalancerOnly: false + # EndpointsFailOpen: true + # EnableServiceController: true + # EnableIPTargetType: true + # SubnetsClusterTagCheck: true + # NLBHealthCheckAdvancedConfig: true + # ALBSingleSubnet: false + +certDiscovery: + allowedCertificateAuthorityARNs: "" # empty means all CAs are in scope + +# objectSelector for webhook +objectSelector: + matchExpressions: + # - key: + # operator: + # values: + # - + matchLabels: + # key: value + +serviceMonitor: + # Specifies whether a service monitor should be created + enabled: false + # Namespace to create the service monitor in + namespace: + # Labels to add to the service monitor + additionalLabels: {} + # Prometheus scrape interval + interval: 1m + # Prometheus scrape timeout + scrapeTimeout: + # Relabelings to apply to samples before ingestion + relabelings: + # Metric relabelings to apply to samples before ingestion + metricRelabelings: + +# clusterSecretsPermissions lets you configure RBAC permissions for secret resources +# Access to secrets resource is required only if you use the OIDC feature, and instead of +# enabling access to all secrets, we recommend configuring namespaced role/rolebinding. +# This option is for backwards compatibility only, and will potentially be deprecated in future. +clusterSecretsPermissions: + # allowAllSecrets allows the controller to access all secrets in the cluster. + # This is to get backwards compatible behavior, but *NOT* recommended for security reasons + allowAllSecrets: false + +# ingressClassConfig contains configurations specific to the ingress class +ingressClassConfig: + default: false + +# enableServiceMutatorWebhook allows you enable the webhook which makes this controller the default for all new services of type LoadBalancer +enableServiceMutatorWebhook: true + +# serviceMutatorWebhook contains configurations specific to the service mutator webhook +serviceMutatorWebhookConfig: + # whether or not to fail the service creation if the webhook fails + failurePolicy: Fail + # limit webhook to only mutate services matching the objectSelector + objectSelector: + matchExpressions: [] + # - key: + # operator: + # values: + # - + matchLabels: {} + # key: value + # which operations trigger the webhook + operations: + - CREATE + # - UPDATE + +# serviceTargetENISGTags specifies AWS tags, in addition to the cluster tags, for finding the target ENI SG to which to add inbound rules from NLBs. +serviceTargetENISGTags: + +# Specifies the class of load balancer to use for services. This affects how services are provisioned if type LoadBalancer is used (default service.k8s.aws/nlb) +loadBalancerClass: + +# creator will disable helm default labels, so you can only add yours +# creator: "me" diff --git a/backing-services/cert-manager/Chart.yaml b/backing-services/cert-manager/Chart.yaml new file mode 100644 index 0000000..549472b --- /dev/null +++ b/backing-services/cert-manager/Chart.yaml @@ -0,0 +1,26 @@ +annotations: + artifacthub.io/category: security + artifacthub.io/license: Apache-2.0 + artifacthub.io/prerelease: "false" + artifacthub.io/signKey: | + fingerprint: 1020CF3C033D4F35BAE1C19E1226061C665DF13E + url: https://cert-manager.io/public-keys/cert-manager-keyring-2021-09-20-1020CF3C033D4F35BAE1C19E1226061C665DF13E.gpg +apiVersion: v2 +appVersion: v1.16.2 +description: A Helm chart for cert-manager +home: https://cert-manager.io +icon: https://raw.githubusercontent.com/cert-manager/community/4d35a69437d21b76322157e6284be4cd64e6d2b7/logo/logo-small.png +keywords: +- cert-manager +- kube-lego +- letsencrypt +- tls +kubeVersion: '>= 1.22.0-0' +maintainers: +- email: cert-manager-maintainers@googlegroups.com + name: cert-manager-maintainers + url: https://cert-manager.io +name: cert-manager +sources: +- https://github.com/cert-manager/cert-manager +version: v1.16.2 diff --git a/backing-services/cert-manager/README.md b/backing-services/cert-manager/README.md new file mode 100644 index 0000000..c9cc708 --- /dev/null +++ b/backing-services/cert-manager/README.md @@ -0,0 +1,1994 @@ +# cert-manager + +cert-manager is a Kubernetes addon to automate the management and issuance of +TLS certificates from various issuing sources. + +It will ensure certificates are valid and up to date periodically, and attempt +to renew certificates at an appropriate time before expiry. + +## Prerequisites + +- Kubernetes 1.22+ + +## Installing the Chart + +Full installation instructions, including details on how to configure extra +functionality in cert-manager can be found in the [installation docs](https://cert-manager.io/docs/installation/kubernetes/). + +Before installing the chart, you must first install the cert-manager CustomResourceDefinition resources. +This is performed in a separate step to allow you to easily uninstall and reinstall cert-manager without deleting your installed custom resources. + +```bash +$ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.2/cert-manager.crds.yaml +``` + +To install the chart with the release name `cert-manager`: + +```console +## Add the Jetstack Helm repository +$ helm repo add jetstack https://charts.jetstack.io --force-update + +## Install the cert-manager helm chart +$ helm install cert-manager --namespace cert-manager --version v1.16.2 jetstack/cert-manager +``` + +In order to begin issuing certificates, you will need to set up a ClusterIssuer +or Issuer resource (for example, by creating a 'letsencrypt-staging' issuer). + +More information on the different types of issuers and how to configure them +can be found in [our documentation](https://cert-manager.io/docs/configuration/). + +For information on how to configure cert-manager to automatically provision +Certificates for Ingress resources, take a look at the +[Securing Ingresses documentation](https://cert-manager.io/docs/usage/ingress/). + +> **Tip**: List all releases using `helm list` + +## Upgrading the Chart + +Special considerations may be required when upgrading the Helm chart, and these +are documented in our full [upgrading guide](https://cert-manager.io/docs/installation/upgrading/). + +**Please check here before performing upgrades!** + +## Uninstalling the Chart + +To uninstall/delete the `cert-manager` deployment: + +```console +$ helm delete cert-manager --namespace cert-manager +``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. + +If you want to completely uninstall cert-manager from your cluster, you will also need to +delete the previously installed CustomResourceDefinition resources: + +```console +$ kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.2/cert-manager.crds.yaml +``` + +## Configuration + + +### Global + +#### **global.imagePullSecrets** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Reference to one or more secrets to be used when pulling images. For more information, see [Pull an Image from a Private Registry](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/). + +For example: + +```yaml +imagePullSecrets: + - name: "image-pull-secret" +``` +#### **global.commonLabels** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Labels to apply to all resources. +Please note that this does not add labels to the resources created dynamically by the controllers. For these resources, you have to add the labels in the template in the cert-manager custom resource: For example, podTemplate/ ingressTemplate in ACMEChallengeSolverHTTP01Ingress. For more information, see the [cert-manager documentation](https://cert-manager.io/docs/reference/api-docs/#acme.cert-manager.io/v1.ACMEChallengeSolverHTTP01Ingress). +For example, secretTemplate in CertificateSpec +For more information, see the [cert-manager documentation](https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificateSpec). +#### **global.revisionHistoryLimit** ~ `number` + +The number of old ReplicaSets to retain to allow rollback (if not set, the default Kubernetes value is set to 10). + +#### **global.priorityClassName** ~ `string` +> Default value: +> ```yaml +> "" +> ``` + +The optional priority class to be used for the cert-manager pods. +#### **global.rbac.create** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Create required ClusterRoles and ClusterRoleBindings for cert-manager. +#### **global.rbac.aggregateClusterRoles** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Aggregate ClusterRoles to Kubernetes default user-facing roles. For more information, see [User-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) +#### **global.podSecurityPolicy.enabled** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Create PodSecurityPolicy for cert-manager. + +Note that PodSecurityPolicy was deprecated in Kubernetes 1.21 and removed in Kubernetes 1.25. +#### **global.podSecurityPolicy.useAppArmor** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Configure the PodSecurityPolicy to use AppArmor. +#### **global.logLevel** ~ `number` +> Default value: +> ```yaml +> 2 +> ``` + +Set the verbosity of cert-manager. A range of 0 - 6, with 6 being the most verbose. +#### **global.leaderElection.namespace** ~ `string` +> Default value: +> ```yaml +> kube-system +> ``` + +Override the namespace used for the leader election lease. +#### **global.leaderElection.leaseDuration** ~ `string` + +The duration that non-leader candidates will wait after observing a leadership renewal until attempting to acquire leadership of a led but unrenewed leader slot. This is effectively the maximum duration that a leader can be stopped before it is replaced by another candidate. + +#### **global.leaderElection.renewDeadline** ~ `string` + +The interval between attempts by the acting master to renew a leadership slot before it stops leading. This must be less than or equal to the lease duration. + +#### **global.leaderElection.retryPeriod** ~ `string` + +The duration the clients should wait between attempting acquisition and renewal of a leadership. + +#### **installCRDs** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +This option is equivalent to setting crds.enabled=true and crds.keep=true. Deprecated: use crds.enabled and crds.keep instead. +#### **crds.enabled** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +This option decides if the CRDs should be installed as part of the Helm installation. +#### **crds.keep** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +This option makes it so that the "helm.sh/resource-policy": keep annotation is added to the CRD. This will prevent Helm from uninstalling the CRD when the Helm release is uninstalled. WARNING: when the CRDs are removed, all cert-manager custom resources +(Certificates, Issuers, ...) will be removed too by the garbage collector. +### Controller + +#### **replicaCount** ~ `number` +> Default value: +> ```yaml +> 1 +> ``` + +The number of replicas of the cert-manager controller to run. + +The default is 1, but in production set this to 2 or 3 to provide high availability. + +If `replicas > 1`, consider setting `podDisruptionBudget.enabled=true`. + +Note that cert-manager uses leader election to ensure that there can only be a single instance active at a time. +#### **strategy** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Deployment update strategy for the cert-manager controller deployment. For more information, see the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy). + +For example: + +```yaml +strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 +``` +#### **podDisruptionBudget.enabled** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Enable or disable the PodDisruptionBudget resource. + +This prevents downtime during voluntary disruptions such as during a Node upgrade. For example, the PodDisruptionBudget will block `kubectl drain` if it is used on the Node where the only remaining cert-manager +Pod is currently running. +#### **podDisruptionBudget.minAvailable** ~ `unknown` + +This configures the minimum available pods for disruptions. It can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%). +It cannot be used if `maxUnavailable` is set. + + +#### **podDisruptionBudget.maxUnavailable** ~ `unknown` + +This configures the maximum unavailable pods for disruptions. It can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%). it cannot be used if `minAvailable` is set. + + +#### **featureGates** ~ `string` +> Default value: +> ```yaml +> "" +> ``` + +A comma-separated list of feature gates that should be enabled on the controller pod. +#### **maxConcurrentChallenges** ~ `number` +> Default value: +> ```yaml +> 60 +> ``` + +The maximum number of challenges that can be scheduled as 'processing' at once. +#### **image.registry** ~ `string` + +The container registry to pull the manager image from. + +#### **image.repository** ~ `string` +> Default value: +> ```yaml +> quay.io/jetstack/cert-manager-controller +> ``` + +The container image for the cert-manager controller. + +#### **image.tag** ~ `string` + +Override the image tag to deploy by setting this variable. If no value is set, the chart's appVersion is used. + +#### **image.digest** ~ `string` + +Setting a digest will override any tag. + +#### **image.pullPolicy** ~ `string` +> Default value: +> ```yaml +> IfNotPresent +> ``` + +Kubernetes imagePullPolicy on Deployment. +#### **clusterResourceNamespace** ~ `string` +> Default value: +> ```yaml +> "" +> ``` + +Override the namespace used to store DNS provider credentials etc. for ClusterIssuer resources. By default, the same namespace as cert-manager is deployed within is used. This namespace will not be automatically created by the Helm chart. +#### **namespace** ~ `string` +> Default value: +> ```yaml +> "" +> ``` + +This namespace allows you to define where the services are installed into. If not set then they use the namespace of the release. This is helpful when installing cert manager as a chart dependency (sub chart). +#### **fullnameOverride** ~ `string` + +Override the "cert-manager.fullname" value. This value is used as part of most of the names of the resources created by this Helm chart. + +#### **nameOverride** ~ `string` + +Override the "cert-manager.name" value, which is used to annotate some of the resources that are created by this Chart (using "app.kubernetes.io/name"). NOTE: There are some inconsistencies in the Helm chart when it comes to these annotations (some resources use eg. "cainjector.name" which resolves to the value "cainjector"). + +#### **serviceAccount.create** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Specifies whether a service account should be created. +#### **serviceAccount.name** ~ `string` + +The name of the service account to use. +If not set and create is true, a name is generated using the fullname template. + +#### **serviceAccount.annotations** ~ `object` + +Optional additional annotations to add to the controller's Service Account. + +#### **serviceAccount.labels** ~ `object` + +Optional additional labels to add to the controller's Service Account. + +#### **serviceAccount.automountServiceAccountToken** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Automount API credentials for a Service Account. +#### **automountServiceAccountToken** ~ `bool` + +Automounting API credentials for a particular pod. + +#### **enableCertificateOwnerRef** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +When this flag is enabled, secrets will be automatically removed when the certificate resource is deleted. +#### **config** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +This property is used to configure options for the controller pod. This allows setting options that would usually be provided using flags. + +If `apiVersion` and `kind` are unspecified they default to the current latest version (currently `controller.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself. + +For example: + +```yaml +config: + apiVersion: controller.config.cert-manager.io/v1alpha1 + kind: ControllerConfiguration + logging: + verbosity: 2 + format: text + leaderElectionConfig: + namespace: kube-system + kubernetesAPIQPS: 9000 + kubernetesAPIBurst: 9000 + numberOfConcurrentWorkers: 200 + featureGates: + AdditionalCertificateOutputFormats: true + DisallowInsecureCSRUsageDefinition: true + ExperimentalCertificateSigningRequestControllers: true + ExperimentalGatewayAPISupport: true + LiteralCertificateSubject: true + SecretsFilteredCaching: true + ServerSideApply: true + StableCertificateRequestName: true + UseCertificateRequestBasicConstraints: true + ValidateCAA: true + # Configure the metrics server for TLS + # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls + metricsTLSConfig: + dynamic: + secretNamespace: "cert-manager" + secretName: "cert-manager-metrics-ca" + dnsNames: + - cert-manager-metrics +``` +#### **dns01RecursiveNameservers** ~ `string` +> Default value: +> ```yaml +> "" +> ``` + +A comma-separated string with the host and port of the recursive nameservers cert-manager should query. +#### **dns01RecursiveNameserversOnly** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Forces cert-manager to use only the recursive nameservers for verification. Enabling this option could cause the DNS01 self check to take longer owing to caching performed by the recursive nameservers. +#### **disableAutoApproval** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Option to disable cert-manager's build-in auto-approver. The auto-approver approves all CertificateRequests that reference issuers matching the 'approveSignerNames' option. This 'disableAutoApproval' option is useful when you want to make all approval decisions using a different approver (like approver-policy - https://github.com/cert-manager/approver-policy). +#### **approveSignerNames** ~ `array` +> Default value: +> ```yaml +> - issuers.cert-manager.io/* +> - clusterissuers.cert-manager.io/* +> ``` + +List of signer names that cert-manager will approve by default. CertificateRequests referencing these signer names will be auto-approved by cert-manager. Defaults to just approving the cert-manager.io Issuer and ClusterIssuer issuers. When set to an empty array, ALL issuers will be auto-approved by cert-manager. To disable the auto-approval, because eg. you are using approver-policy, you can enable 'disableAutoApproval'. +ref: https://cert-manager.io/docs/concepts/certificaterequest/#approval + +#### **extraArgs** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional command line flags to pass to cert-manager controller binary. To see all available flags run `docker run quay.io/jetstack/cert-manager-controller: --help`. + +Use this flag to enable or disable arbitrary controllers. For example, to disable the CertificateRequests approver. + +For example: + +```yaml +extraArgs: + - --controllers=*,-certificaterequests-approver +``` +#### **extraEnv** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional environment variables to pass to cert-manager controller binary. +For example: + +```yaml +extraEnv: +- name: SOME_VAR + value: 'some value' +``` +#### **resources** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Resources to provide to the cert-manager controller pod. + +For example: + +```yaml +requests: + cpu: 10m + memory: 32Mi +``` + +For more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). +#### **securityContext** ~ `object` +> Default value: +> ```yaml +> runAsNonRoot: true +> seccompProfile: +> type: RuntimeDefault +> ``` + +Pod Security Context. +For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + +#### **containerSecurityContext** ~ `object` +> Default value: +> ```yaml +> allowPrivilegeEscalation: false +> capabilities: +> drop: +> - ALL +> readOnlyRootFilesystem: true +> ``` + +Container Security Context to be set on the controller component container. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + +#### **volumes** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional volumes to add to the cert-manager controller pod. +#### **volumeMounts** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional volume mounts to add to the cert-manager controller container. +#### **deploymentAnnotations** ~ `object` + +Optional additional annotations to add to the controller Deployment. + +#### **podAnnotations** ~ `object` + +Optional additional annotations to add to the controller Pods. + +#### **podLabels** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Optional additional labels to add to the controller Pods. +#### **serviceAnnotations** ~ `object` + +Optional annotations to add to the controller Service. + +#### **serviceLabels** ~ `object` + +Optional additional labels to add to the controller Service. + +#### **serviceIPFamilyPolicy** ~ `string` + +Optionally set the IP family policy for the controller Service to configure dual-stack; see [Configure dual-stack](https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services). + +#### **serviceIPFamilies** ~ `array` + +Optionally set the IP families for the controller Service that should be supported, in the order in which they should be applied to ClusterIP. Can be IPv4 and/or IPv6. + +#### **podDnsPolicy** ~ `string` + +Pod DNS policy. +For more information, see [Pod's DNS Policy](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). + +#### **podDnsConfig** ~ `object` + +Pod DNS configuration. The podDnsConfig field is optional and can work with any podDnsPolicy settings. However, when a Pod's dnsPolicy is set to "None", the dnsConfig field has to be specified. For more information, see [Pod's DNS Config](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-dns-config). + +#### **hostAliases** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Optional hostAliases for cert-manager-controller pods. May be useful when performing ACME DNS-01 self checks. +#### **nodeSelector** ~ `object` +> Default value: +> ```yaml +> kubernetes.io/os: linux +> ``` + +The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with matching labels. For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). + +This default ensures that Pods are only scheduled to Linux nodes. It prevents Pods being scheduled to Windows nodes in a mixed OS cluster. + +#### **ingressShim.defaultIssuerName** ~ `string` + +Optional default issuer to use for ingress resources. + +#### **ingressShim.defaultIssuerKind** ~ `string` + +Optional default issuer kind to use for ingress resources. + +#### **ingressShim.defaultIssuerGroup** ~ `string` + +Optional default issuer group to use for ingress resources. + +#### **http_proxy** ~ `string` + +Configures the HTTP_PROXY environment variable where a HTTP proxy is required. + +#### **https_proxy** ~ `string` + +Configures the HTTPS_PROXY environment variable where a HTTP proxy is required. + +#### **no_proxy** ~ `string` + +Configures the NO_PROXY environment variable where a HTTP proxy is required, but certain domains should be excluded. + +#### **affinity** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core). + +For example: + +```yaml +affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: foo.bar.com/role + operator: In + values: + - master +``` +#### **tolerations** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core). + +For example: + +```yaml +tolerations: +- key: foo.bar.com/role + operator: Equal + value: master + effect: NoSchedule +``` +#### **topologySpreadConstraints** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +A list of Kubernetes TopologySpreadConstraints, if required. For more information, see [Topology spread constraint v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#topologyspreadconstraint-v1-core + +For example: + +```yaml +topologySpreadConstraints: +- maxSkew: 2 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app.kubernetes.io/instance: cert-manager + app.kubernetes.io/component: controller +``` +#### **livenessProbe** ~ `object` +> Default value: +> ```yaml +> enabled: true +> failureThreshold: 8 +> initialDelaySeconds: 10 +> periodSeconds: 10 +> successThreshold: 1 +> timeoutSeconds: 15 +> ``` + +LivenessProbe settings for the controller container of the controller Pod. + +This is enabled by default, in order to enable the clock-skew liveness probe that restarts the controller in case of a skew between the system clock and the monotonic clock. LivenessProbe durations and thresholds are based on those used for the Kubernetes controller-manager. For more information see the following on the +[Kubernetes GitHub repository](https://github.com/kubernetes/kubernetes/blob/806b30170c61a38fedd54cc9ede4cd6275a1ad3b/cmd/kubeadm/app/util/staticpod/utils.go#L241-L245) + +#### **enableServiceLinks** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +enableServiceLinks indicates whether information about services should be injected into the pod's environment variables, matching the syntax of Docker links. +### Prometheus + +#### **prometheus.enabled** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Enable Prometheus monitoring for the cert-manager controller and webhook. If you use the Prometheus Operator, set prometheus.podmonitor.enabled or prometheus.servicemonitor.enabled, to create a PodMonitor or a +ServiceMonitor resource. +Otherwise, 'prometheus.io' annotations are added to the cert-manager and cert-manager-webhook Deployments. Note that you can not enable both PodMonitor and ServiceMonitor as they are mutually exclusive. Enabling both will result in an error. +#### **prometheus.servicemonitor.enabled** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Create a ServiceMonitor to add cert-manager to Prometheus. +#### **prometheus.servicemonitor.namespace** ~ `string` + +The namespace that the service monitor should live in, defaults to the cert-manager namespace. + +#### **prometheus.servicemonitor.prometheusInstance** ~ `string` +> Default value: +> ```yaml +> default +> ``` + +Specifies the `prometheus` label on the created ServiceMonitor. This is used when different Prometheus instances have label selectors matching different ServiceMonitors. +#### **prometheus.servicemonitor.targetPort** ~ `number` +> Default value: +> ```yaml +> 9402 +> ``` + +The target port to set on the ServiceMonitor. This must match the port that the cert-manager controller is listening on for metrics. +#### **prometheus.servicemonitor.path** ~ `string` +> Default value: +> ```yaml +> /metrics +> ``` + +The path to scrape for metrics. +#### **prometheus.servicemonitor.interval** ~ `string` +> Default value: +> ```yaml +> 60s +> ``` + +The interval to scrape metrics. +#### **prometheus.servicemonitor.scrapeTimeout** ~ `string` +> Default value: +> ```yaml +> 30s +> ``` + +The timeout before a metrics scrape fails. +#### **prometheus.servicemonitor.labels** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Additional labels to add to the ServiceMonitor. +#### **prometheus.servicemonitor.annotations** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Additional annotations to add to the ServiceMonitor. +#### **prometheus.servicemonitor.honorLabels** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Keep labels from scraped data, overriding server-side labels. +#### **prometheus.servicemonitor.endpointAdditionalProperties** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +EndpointAdditionalProperties allows setting additional properties on the endpoint such as relabelings, metricRelabelings etc. + +For example: + +```yaml +endpointAdditionalProperties: + relabelings: + - action: replace + sourceLabels: + - __meta_kubernetes_pod_node_name + targetLabel: instance +``` + + + +#### **prometheus.podmonitor.enabled** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Create a PodMonitor to add cert-manager to Prometheus. +#### **prometheus.podmonitor.namespace** ~ `string` + +The namespace that the pod monitor should live in, defaults to the cert-manager namespace. + +#### **prometheus.podmonitor.prometheusInstance** ~ `string` +> Default value: +> ```yaml +> default +> ``` + +Specifies the `prometheus` label on the created PodMonitor. This is used when different Prometheus instances have label selectors matching different PodMonitors. +#### **prometheus.podmonitor.path** ~ `string` +> Default value: +> ```yaml +> /metrics +> ``` + +The path to scrape for metrics. +#### **prometheus.podmonitor.interval** ~ `string` +> Default value: +> ```yaml +> 60s +> ``` + +The interval to scrape metrics. +#### **prometheus.podmonitor.scrapeTimeout** ~ `string` +> Default value: +> ```yaml +> 30s +> ``` + +The timeout before a metrics scrape fails. +#### **prometheus.podmonitor.labels** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Additional labels to add to the PodMonitor. +#### **prometheus.podmonitor.annotations** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Additional annotations to add to the PodMonitor. +#### **prometheus.podmonitor.honorLabels** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Keep labels from scraped data, overriding server-side labels. +#### **prometheus.podmonitor.endpointAdditionalProperties** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +EndpointAdditionalProperties allows setting additional properties on the endpoint such as relabelings, metricRelabelings etc. + +For example: + +```yaml +endpointAdditionalProperties: + relabelings: + - action: replace + sourceLabels: + - __meta_kubernetes_pod_node_name + targetLabel: instance + # Configure the PodMonitor for TLS connections + # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls + scheme: https + tlsConfig: + serverName: cert-manager-metrics + ca: + secret: + name: cert-manager-metrics-ca + key: "tls.crt" +``` + + + +### Webhook + +#### **webhook.replicaCount** ~ `number` +> Default value: +> ```yaml +> 1 +> ``` + +Number of replicas of the cert-manager webhook to run. + +The default is 1, but in production set this to 2 or 3 to provide high availability. + +If `replicas > 1`, consider setting `webhook.podDisruptionBudget.enabled=true`. +#### **webhook.timeoutSeconds** ~ `number` +> Default value: +> ```yaml +> 30 +> ``` + +The number of seconds the API server should wait for the webhook to respond before treating the call as a failure. The value must be between 1 and 30 seconds. For more information, see +[Validating webhook configuration v1](https://kubernetes.io/docs/reference/kubernetes-api/extend-resources/validating-webhook-configuration-v1/). + +The default is set to the maximum value of 30 seconds as users sometimes report that the connection between the K8S API server and the cert-manager webhook server times out. If *this* timeout is reached, the error message will be "context deadline exceeded", which doesn't help the user diagnose what phase of the HTTPS connection timed out. For example, it could be during DNS resolution, TCP connection, TLS negotiation, HTTP negotiation, or slow HTTP response from the webhook server. By setting this timeout to its maximum value the underlying timeout error message has more chance of being returned to the end user. +#### **webhook.config** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +This is used to configure options for the webhook pod. This allows setting options that would usually be provided using flags. + +If `apiVersion` and `kind` are unspecified they default to the current latest version (currently `webhook.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself. + +For example: + +```yaml +apiVersion: webhook.config.cert-manager.io/v1alpha1 +kind: WebhookConfiguration +# The port that the webhook listens on for requests. +# In GKE private clusters, by default Kubernetes apiservers are allowed to +# talk to the cluster nodes only on 443 and 10250. Configuring +# securePort: 10250 therefore will work out-of-the-box without needing to add firewall +# rules or requiring NET_BIND_SERVICE capabilities to bind port numbers < 1000. +# This should be uncommented and set as a default by the chart once +# the apiVersion of WebhookConfiguration graduates beyond v1alpha1. +securePort: 10250 +# Configure the metrics server for TLS +# See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls +metricsTLSConfig: + dynamic: + secretNamespace: "cert-manager" + secretName: "cert-manager-metrics-ca" + dnsNames: + - cert-manager-metrics +``` +#### **webhook.strategy** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +The update strategy for the cert-manager webhook deployment. For more information, see the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy) + +For example: + +```yaml +strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 +``` +#### **webhook.securityContext** ~ `object` +> Default value: +> ```yaml +> runAsNonRoot: true +> seccompProfile: +> type: RuntimeDefault +> ``` + +Pod Security Context to be set on the webhook component Pod. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + +#### **webhook.containerSecurityContext** ~ `object` +> Default value: +> ```yaml +> allowPrivilegeEscalation: false +> capabilities: +> drop: +> - ALL +> readOnlyRootFilesystem: true +> ``` + +Container Security Context to be set on the webhook component container. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + +#### **webhook.podDisruptionBudget.enabled** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Enable or disable the PodDisruptionBudget resource. + +This prevents downtime during voluntary disruptions such as during a Node upgrade. For example, the PodDisruptionBudget will block `kubectl drain` if it is used on the Node where the only remaining cert-manager +Pod is currently running. +#### **webhook.podDisruptionBudget.minAvailable** ~ `unknown` + +This property configures the minimum available pods for disruptions. Can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%). +It cannot be used if `maxUnavailable` is set. + + +#### **webhook.podDisruptionBudget.maxUnavailable** ~ `unknown` + +This property configures the maximum unavailable pods for disruptions. Can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%). +It cannot be used if `minAvailable` is set. + + +#### **webhook.deploymentAnnotations** ~ `object` + +Optional additional annotations to add to the webhook Deployment. + +#### **webhook.podAnnotations** ~ `object` + +Optional additional annotations to add to the webhook Pods. + +#### **webhook.serviceAnnotations** ~ `object` + +Optional additional annotations to add to the webhook Service. + +#### **webhook.mutatingWebhookConfigurationAnnotations** ~ `object` + +Optional additional annotations to add to the webhook MutatingWebhookConfiguration. + +#### **webhook.validatingWebhookConfigurationAnnotations** ~ `object` + +Optional additional annotations to add to the webhook ValidatingWebhookConfiguration. + +#### **webhook.validatingWebhookConfiguration.namespaceSelector** ~ `object` +> Default value: +> ```yaml +> matchExpressions: +> - key: cert-manager.io/disable-validation +> operator: NotIn +> values: +> - "true" +> ``` + +Configure spec.namespaceSelector for validating webhooks. + +#### **webhook.mutatingWebhookConfiguration.namespaceSelector** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Configure spec.namespaceSelector for mutating webhooks. + +#### **webhook.extraArgs** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional command line flags to pass to cert-manager webhook binary. To see all available flags run `docker run quay.io/jetstack/cert-manager-webhook: --help`. +#### **webhook.extraEnv** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional environment variables to pass to cert-manager webhook binary. +For example: + +```yaml +extraEnv: +- name: SOME_VAR + value: 'some value' +``` +#### **webhook.featureGates** ~ `string` +> Default value: +> ```yaml +> "" +> ``` + +Comma separated list of feature gates that should be enabled on the webhook pod. +#### **webhook.resources** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Resources to provide to the cert-manager webhook pod. + +For example: + +```yaml +requests: + cpu: 10m + memory: 32Mi +``` + +For more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). +#### **webhook.livenessProbe** ~ `object` +> Default value: +> ```yaml +> failureThreshold: 3 +> initialDelaySeconds: 60 +> periodSeconds: 10 +> successThreshold: 1 +> timeoutSeconds: 1 +> ``` + +Liveness probe values. +For more information, see [Container probes](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes). + +#### **webhook.readinessProbe** ~ `object` +> Default value: +> ```yaml +> failureThreshold: 3 +> initialDelaySeconds: 5 +> periodSeconds: 5 +> successThreshold: 1 +> timeoutSeconds: 1 +> ``` + +Readiness probe values. +For more information, see [Container probes](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes). + +#### **webhook.nodeSelector** ~ `object` +> Default value: +> ```yaml +> kubernetes.io/os: linux +> ``` + +The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with matching labels. For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). + +This default ensures that Pods are only scheduled to Linux nodes. It prevents Pods being scheduled to Windows nodes in a mixed OS cluster. + +#### **webhook.affinity** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core). + +For example: + +```yaml +affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: foo.bar.com/role + operator: In + values: + - master +``` +#### **webhook.tolerations** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core). + +For example: + +```yaml +tolerations: +- key: foo.bar.com/role + operator: Equal + value: master + effect: NoSchedule +``` +#### **webhook.topologySpreadConstraints** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +A list of Kubernetes TopologySpreadConstraints, if required. For more information, see [Topology spread constraint v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#topologyspreadconstraint-v1-core). + +For example: + +```yaml +topologySpreadConstraints: +- maxSkew: 2 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app.kubernetes.io/instance: cert-manager + app.kubernetes.io/component: controller +``` +#### **webhook.podLabels** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Optional additional labels to add to the Webhook Pods. +#### **webhook.serviceLabels** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Optional additional labels to add to the Webhook Service. +#### **webhook.serviceIPFamilyPolicy** ~ `string` +> Default value: +> ```yaml +> "" +> ``` + +Optionally set the IP family policy for the controller Service to configure dual-stack; see [Configure dual-stack](https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services). +#### **webhook.serviceIPFamilies** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Optionally set the IP families for the controller Service that should be supported, in the order in which they should be applied to ClusterIP. Can be IPv4 and/or IPv6. +#### **webhook.image.registry** ~ `string` + +The container registry to pull the webhook image from. + +#### **webhook.image.repository** ~ `string` +> Default value: +> ```yaml +> quay.io/jetstack/cert-manager-webhook +> ``` + +The container image for the cert-manager webhook + +#### **webhook.image.tag** ~ `string` + +Override the image tag to deploy by setting this variable. If no value is set, the chart's appVersion will be used. + +#### **webhook.image.digest** ~ `string` + +Setting a digest will override any tag + +#### **webhook.image.pullPolicy** ~ `string` +> Default value: +> ```yaml +> IfNotPresent +> ``` + +Kubernetes imagePullPolicy on Deployment. +#### **webhook.serviceAccount.create** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Specifies whether a service account should be created. +#### **webhook.serviceAccount.name** ~ `string` + +The name of the service account to use. +If not set and create is true, a name is generated using the fullname template. + +#### **webhook.serviceAccount.annotations** ~ `object` + +Optional additional annotations to add to the webhook's Service Account. + +#### **webhook.serviceAccount.labels** ~ `object` + +Optional additional labels to add to the webhook's Service Account. + +#### **webhook.serviceAccount.automountServiceAccountToken** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Automount API credentials for a Service Account. +#### **webhook.automountServiceAccountToken** ~ `bool` + +Automounting API credentials for a particular pod. + +#### **webhook.securePort** ~ `number` +> Default value: +> ```yaml +> 10250 +> ``` + +The port that the webhook listens on for requests. In GKE private clusters, by default Kubernetes apiservers are allowed to talk to the cluster nodes only on 443 and 10250. Configuring securePort: 10250, therefore will work out-of-the-box without needing to add firewall rules or requiring NET_BIND_SERVICE capabilities to bind port numbers <1000. +#### **webhook.hostNetwork** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Specifies if the webhook should be started in hostNetwork mode. + +Required for use in some managed kubernetes clusters (such as AWS EKS) with custom. CNI (such as calico), because control-plane managed by AWS cannot communicate with pods' IP CIDR and admission webhooks are not working + +Since the default port for the webhook conflicts with kubelet on the host network, `webhook.securePort` should be changed to an available port if running in hostNetwork mode. +#### **webhook.serviceType** ~ `string` +> Default value: +> ```yaml +> ClusterIP +> ``` + +Specifies how the service should be handled. Useful if you want to expose the webhook outside of the cluster. In some cases, the control plane cannot reach internal services. +#### **webhook.loadBalancerIP** ~ `string` + +Specify the load balancer IP for the created service. + +#### **webhook.url** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Overrides the mutating webhook and validating webhook so they reach the webhook service using the `url` field instead of a service. +#### **webhook.networkPolicy.enabled** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Create network policies for the webhooks. +#### **webhook.networkPolicy.ingress** ~ `array` +> Default value: +> ```yaml +> - from: +> - ipBlock: +> cidr: 0.0.0.0/0 +> ``` + +Ingress rule for the webhook network policy. By default, it allows all inbound traffic. + +#### **webhook.networkPolicy.egress** ~ `array` +> Default value: +> ```yaml +> - ports: +> - port: 80 +> protocol: TCP +> - port: 443 +> protocol: TCP +> - port: 53 +> protocol: TCP +> - port: 53 +> protocol: UDP +> - port: 6443 +> protocol: TCP +> to: +> - ipBlock: +> cidr: 0.0.0.0/0 +> ``` + +Egress rule for the webhook network policy. By default, it allows all outbound traffic to ports 80 and 443, as well as DNS ports. + +#### **webhook.volumes** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional volumes to add to the cert-manager controller pod. +#### **webhook.volumeMounts** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional volume mounts to add to the cert-manager controller container. +#### **webhook.enableServiceLinks** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +enableServiceLinks indicates whether information about services should be injected into the pod's environment variables, matching the syntax of Docker links. +### CA Injector + +#### **cainjector.enabled** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Create the CA Injector deployment +#### **cainjector.replicaCount** ~ `number` +> Default value: +> ```yaml +> 1 +> ``` + +The number of replicas of the cert-manager cainjector to run. + +The default is 1, but in production set this to 2 or 3 to provide high availability. + +If `replicas > 1`, consider setting `cainjector.podDisruptionBudget.enabled=true`. + +Note that cert-manager uses leader election to ensure that there can only be a single instance active at a time. +#### **cainjector.config** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +This is used to configure options for the cainjector pod. It allows setting options that are usually provided via flags. + +If `apiVersion` and `kind` are unspecified they default to the current latest version (currently `cainjector.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself. + +For example: + +```yaml +apiVersion: cainjector.config.cert-manager.io/v1alpha1 +kind: CAInjectorConfiguration +logging: + verbosity: 2 + format: text +leaderElectionConfig: + namespace: kube-system +# Configure the metrics server for TLS +# See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls +metricsTLSConfig: + dynamic: + secretNamespace: "cert-manager" + secretName: "cert-manager-metrics-ca" + dnsNames: + - cert-manager-metrics +``` +#### **cainjector.strategy** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Deployment update strategy for the cert-manager cainjector deployment. For more information, see the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy). + +For example: + +```yaml +strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 +``` +#### **cainjector.securityContext** ~ `object` +> Default value: +> ```yaml +> runAsNonRoot: true +> seccompProfile: +> type: RuntimeDefault +> ``` + +Pod Security Context to be set on the cainjector component Pod. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + +#### **cainjector.containerSecurityContext** ~ `object` +> Default value: +> ```yaml +> allowPrivilegeEscalation: false +> capabilities: +> drop: +> - ALL +> readOnlyRootFilesystem: true +> ``` + +Container Security Context to be set on the cainjector component container. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + +#### **cainjector.podDisruptionBudget.enabled** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Enable or disable the PodDisruptionBudget resource. + +This prevents downtime during voluntary disruptions such as during a Node upgrade. For example, the PodDisruptionBudget will block `kubectl drain` if it is used on the Node where the only remaining cert-manager +Pod is currently running. +#### **cainjector.podDisruptionBudget.minAvailable** ~ `unknown` + +`minAvailable` configures the minimum available pods for disruptions. It can either be set to +an integer (e.g. 1) or a percentage value (e.g. 25%). +Cannot be used if `maxUnavailable` is set. + + +#### **cainjector.podDisruptionBudget.maxUnavailable** ~ `unknown` + +`maxUnavailable` configures the maximum unavailable pods for disruptions. It can either be set to +an integer (e.g. 1) or a percentage value (e.g. 25%). +Cannot be used if `minAvailable` is set. + + +#### **cainjector.deploymentAnnotations** ~ `object` + +Optional additional annotations to add to the cainjector Deployment. + +#### **cainjector.podAnnotations** ~ `object` + +Optional additional annotations to add to the cainjector Pods. + +#### **cainjector.serviceAnnotations** ~ `object` + +Optional additional annotations to add to the cainjector metrics Service. + +#### **cainjector.extraArgs** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional command line flags to pass to cert-manager cainjector binary. To see all available flags run `docker run quay.io/jetstack/cert-manager-cainjector: --help`. +#### **cainjector.extraEnv** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional environment variables to pass to cert-manager cainjector binary. +For example: + +```yaml +extraEnv: +- name: SOME_VAR + value: 'some value' +``` +#### **cainjector.featureGates** ~ `string` +> Default value: +> ```yaml +> "" +> ``` + +Comma separated list of feature gates that should be enabled on the cainjector pod. +#### **cainjector.resources** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Resources to provide to the cert-manager cainjector pod. + +For example: + +```yaml +requests: + cpu: 10m + memory: 32Mi +``` + +For more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). +#### **cainjector.nodeSelector** ~ `object` +> Default value: +> ```yaml +> kubernetes.io/os: linux +> ``` + +The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with matching labels. For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). + +This default ensures that Pods are only scheduled to Linux nodes. It prevents Pods being scheduled to Windows nodes in a mixed OS cluster. + +#### **cainjector.affinity** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core). + +For example: + +```yaml +affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: foo.bar.com/role + operator: In + values: + - master +``` +#### **cainjector.tolerations** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core). + +For example: + +```yaml +tolerations: +- key: foo.bar.com/role + operator: Equal + value: master + effect: NoSchedule +``` +#### **cainjector.topologySpreadConstraints** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +A list of Kubernetes TopologySpreadConstraints, if required. For more information, see [Topology spread constraint v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#topologyspreadconstraint-v1-core). + +For example: + +```yaml +topologySpreadConstraints: +- maxSkew: 2 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app.kubernetes.io/instance: cert-manager + app.kubernetes.io/component: controller +``` +#### **cainjector.podLabels** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Optional additional labels to add to the CA Injector Pods. +#### **cainjector.serviceLabels** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Optional additional labels to add to the CA Injector metrics Service. +#### **cainjector.image.registry** ~ `string` + +The container registry to pull the cainjector image from. + +#### **cainjector.image.repository** ~ `string` +> Default value: +> ```yaml +> quay.io/jetstack/cert-manager-cainjector +> ``` + +The container image for the cert-manager cainjector + +#### **cainjector.image.tag** ~ `string` + +Override the image tag to deploy by setting this variable. If no value is set, the chart's appVersion will be used. + +#### **cainjector.image.digest** ~ `string` + +Setting a digest will override any tag. + +#### **cainjector.image.pullPolicy** ~ `string` +> Default value: +> ```yaml +> IfNotPresent +> ``` + +Kubernetes imagePullPolicy on Deployment. +#### **cainjector.serviceAccount.create** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Specifies whether a service account should be created. +#### **cainjector.serviceAccount.name** ~ `string` + +The name of the service account to use. +If not set and create is true, a name is generated using the fullname template + +#### **cainjector.serviceAccount.annotations** ~ `object` + +Optional additional annotations to add to the cainjector's Service Account. + +#### **cainjector.serviceAccount.labels** ~ `object` + +Optional additional labels to add to the cainjector's Service Account. + +#### **cainjector.serviceAccount.automountServiceAccountToken** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Automount API credentials for a Service Account. +#### **cainjector.automountServiceAccountToken** ~ `bool` + +Automounting API credentials for a particular pod. + +#### **cainjector.volumes** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional volumes to add to the cert-manager controller pod. +#### **cainjector.volumeMounts** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional volume mounts to add to the cert-manager controller container. +#### **cainjector.enableServiceLinks** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +enableServiceLinks indicates whether information about services should be injected into the pod's environment variables, matching the syntax of Docker links. +### ACME Solver + +#### **acmesolver.image.registry** ~ `string` + +The container registry to pull the acmesolver image from. + +#### **acmesolver.image.repository** ~ `string` +> Default value: +> ```yaml +> quay.io/jetstack/cert-manager-acmesolver +> ``` + +The container image for the cert-manager acmesolver. + +#### **acmesolver.image.tag** ~ `string` + +Override the image tag to deploy by setting this variable. If no value is set, the chart's appVersion is used. + +#### **acmesolver.image.digest** ~ `string` + +Setting a digest will override any tag. + +#### **acmesolver.image.pullPolicy** ~ `string` +> Default value: +> ```yaml +> IfNotPresent +> ``` + +Kubernetes imagePullPolicy on Deployment. +### Startup API Check + + +This startupapicheck is a Helm post-install hook that waits for the webhook endpoints to become available. The check is implemented using a Kubernetes Job - if you are injecting mesh sidecar proxies into cert-manager pods, ensure that they are not injected into this Job's pod. Otherwise, the installation may time out owing to the Job never being completed because the sidecar proxy does not exit. For more information, see [this note](https://github.com/cert-manager/cert-manager/pull/4414). +#### **startupapicheck.enabled** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Enables the startup api check. +#### **startupapicheck.securityContext** ~ `object` +> Default value: +> ```yaml +> runAsNonRoot: true +> seccompProfile: +> type: RuntimeDefault +> ``` + +Pod Security Context to be set on the startupapicheck component Pod. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + +#### **startupapicheck.containerSecurityContext** ~ `object` +> Default value: +> ```yaml +> allowPrivilegeEscalation: false +> capabilities: +> drop: +> - ALL +> readOnlyRootFilesystem: true +> ``` + +Container Security Context to be set on the controller component container. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + +#### **startupapicheck.timeout** ~ `string` +> Default value: +> ```yaml +> 1m +> ``` + +Timeout for 'kubectl check api' command. +#### **startupapicheck.backoffLimit** ~ `number` +> Default value: +> ```yaml +> 4 +> ``` + +Job backoffLimit +#### **startupapicheck.jobAnnotations** ~ `object` +> Default value: +> ```yaml +> helm.sh/hook: post-install +> helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded +> helm.sh/hook-weight: "1" +> ``` + +Optional additional annotations to add to the startupapicheck Job. + +#### **startupapicheck.podAnnotations** ~ `object` + +Optional additional annotations to add to the startupapicheck Pods. + +#### **startupapicheck.extraArgs** ~ `array` +> Default value: +> ```yaml +> - -v +> ``` + +Additional command line flags to pass to startupapicheck binary. To see all available flags run `docker run quay.io/jetstack/cert-manager-startupapicheck: --help`. + +Verbose logging is enabled by default so that if startupapicheck fails, you can know what exactly caused the failure. Verbose logs include details of the webhook URL, IP address and TCP connect errors for example. + +#### **startupapicheck.extraEnv** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional environment variables to pass to cert-manager startupapicheck binary. +For example: + +```yaml +extraEnv: +- name: SOME_VAR + value: 'some value' +``` +#### **startupapicheck.resources** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Resources to provide to the cert-manager controller pod. + +For example: + +```yaml +requests: + cpu: 10m + memory: 32Mi +``` + +For more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). +#### **startupapicheck.nodeSelector** ~ `object` +> Default value: +> ```yaml +> kubernetes.io/os: linux +> ``` + +The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with matching labels. For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). + +This default ensures that Pods are only scheduled to Linux nodes. It prevents Pods being scheduled to Windows nodes in a mixed OS cluster. + +#### **startupapicheck.affinity** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core). +For example: + +```yaml +affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: foo.bar.com/role + operator: In + values: + - master +``` +#### **startupapicheck.tolerations** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core). + +For example: + +```yaml +tolerations: +- key: foo.bar.com/role + operator: Equal + value: master + effect: NoSchedule +``` +#### **startupapicheck.podLabels** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Optional additional labels to add to the startupapicheck Pods. +#### **startupapicheck.image.registry** ~ `string` + +The container registry to pull the startupapicheck image from. + +#### **startupapicheck.image.repository** ~ `string` +> Default value: +> ```yaml +> quay.io/jetstack/cert-manager-startupapicheck +> ``` + +The container image for the cert-manager startupapicheck. + +#### **startupapicheck.image.tag** ~ `string` + +Override the image tag to deploy by setting this variable. If no value is set, the chart's appVersion is used. + +#### **startupapicheck.image.digest** ~ `string` + +Setting a digest will override any tag. + +#### **startupapicheck.image.pullPolicy** ~ `string` +> Default value: +> ```yaml +> IfNotPresent +> ``` + +Kubernetes imagePullPolicy on Deployment. +#### **startupapicheck.rbac.annotations** ~ `object` +> Default value: +> ```yaml +> helm.sh/hook: post-install +> helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded +> helm.sh/hook-weight: "-5" +> ``` + +annotations for the startup API Check job RBAC and PSP resources. + +#### **startupapicheck.automountServiceAccountToken** ~ `bool` + +Automounting API credentials for a particular pod. + +#### **startupapicheck.serviceAccount.create** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Specifies whether a service account should be created. +#### **startupapicheck.serviceAccount.name** ~ `string` + +The name of the service account to use. +If not set and create is true, a name is generated using the fullname template. + +#### **startupapicheck.serviceAccount.annotations** ~ `object` +> Default value: +> ```yaml +> helm.sh/hook: post-install +> helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded +> helm.sh/hook-weight: "-5" +> ``` + +Optional additional annotations to add to the Job's Service Account. + +#### **startupapicheck.serviceAccount.automountServiceAccountToken** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Automount API credentials for a Service Account. + +#### **startupapicheck.serviceAccount.labels** ~ `object` + +Optional additional labels to add to the startupapicheck's Service Account. + +#### **startupapicheck.volumes** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional volumes to add to the cert-manager controller pod. +#### **startupapicheck.volumeMounts** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional volume mounts to add to the cert-manager controller container. +#### **startupapicheck.enableServiceLinks** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +enableServiceLinks indicates whether information about services should be injected into pod's environment variables, matching the syntax of Docker links. +#### **extraObjects** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Create dynamic manifests via values. + +For example: + +```yaml +extraObjects: + - | + apiVersion: v1 + kind: ConfigMap + metadata: + name: '{{ template "cert-manager.fullname" . }}-extra-configmap' +``` + + +### Default Security Contexts + +The default pod-level and container-level security contexts, below, adhere to the [restricted](https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted) Pod Security Standards policies. + +Default pod-level securityContext: +```yaml +runAsNonRoot: true +seccompProfile: + type: RuntimeDefault +``` + +Default containerSecurityContext: +```yaml +allowPrivilegeEscalation: false +capabilities: + drop: + - ALL +``` + +### Assigning Values + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. + +Alternatively, a YAML file that specifies the values for the above parameters can be provided while installing the chart. For example, + +```console +$ helm install my-release -f values.yaml . +``` +> **Tip**: You can use the default [values.yaml](https://github.com/cert-manager/cert-manager/blob/master/deploy/charts/cert-manager/values.yaml) + +## Contributing + +This chart is maintained at [github.com/cert-manager/cert-manager](https://github.com/cert-manager/cert-manager/tree/master/deploy/charts/cert-manager). diff --git a/backing-services/cert-manager/school-stage-eks.values.yaml b/backing-services/cert-manager/school-stage-eks.values.yaml new file mode 100644 index 0000000..e69de29 diff --git a/backing-services/cert-manager/templates/NOTES.txt b/backing-services/cert-manager/templates/NOTES.txt new file mode 100644 index 0000000..341d101 --- /dev/null +++ b/backing-services/cert-manager/templates/NOTES.txt @@ -0,0 +1,18 @@ +{{- if .Values.installCRDs }} +⚠️ WARNING: `installCRDs` is deprecated, use `crds.enabled` instead. +{{- end }} +cert-manager {{ .Chart.AppVersion }} has been deployed successfully! + +In order to begin issuing certificates, you will need to set up a ClusterIssuer +or Issuer resource (for example, by creating a 'letsencrypt-staging' issuer). + +More information on the different types of issuers and how to configure them +can be found in our documentation: + +https://cert-manager.io/docs/configuration/ + +For information on how to configure cert-manager to automatically provision +Certificates for Ingress resources, take a look at the `ingress-shim` +documentation: + +https://cert-manager.io/docs/usage/ingress/ diff --git a/backing-services/cert-manager/templates/_helpers.tpl b/backing-services/cert-manager/templates/_helpers.tpl new file mode 100644 index 0000000..e15fa19 --- /dev/null +++ b/backing-services/cert-manager/templates/_helpers.tpl @@ -0,0 +1,202 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "cert-manager.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 "cert-manager.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 the name of the service account to use +*/}} +{{- define "cert-manager.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "cert-manager.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Webhook templates +*/}} + +{{/* +Expand the name of the chart. +Manually fix the 'app' and 'name' labels to 'webhook' to maintain +compatibility with the v0.9 deployment selector. +*/}} +{{- define "webhook.name" -}} +{{- printf "webhook" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "webhook.fullname" -}} +{{- $trimmedName := printf "%s" (include "cert-manager.fullname" .) | trunc 55 | trimSuffix "-" -}} +{{- printf "%s-webhook" $trimmedName | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- define "webhook.caRef" -}} +{{- template "cert-manager.namespace" }}/{{ template "webhook.fullname" . }}-ca +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "webhook.serviceAccountName" -}} +{{- if .Values.webhook.serviceAccount.create -}} + {{ default (include "webhook.fullname" .) .Values.webhook.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.webhook.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +cainjector templates +*/}} + +{{/* +Expand the name of the chart. +Manually fix the 'app' and 'name' labels to 'cainjector' to maintain +compatibility with the v0.9 deployment selector. +*/}} +{{- define "cainjector.name" -}} +{{- printf "cainjector" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "cainjector.fullname" -}} +{{- $trimmedName := printf "%s" (include "cert-manager.fullname" .) | trunc 52 | trimSuffix "-" -}} +{{- printf "%s-cainjector" $trimmedName | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "cainjector.serviceAccountName" -}} +{{- if .Values.cainjector.serviceAccount.create -}} + {{ default (include "cainjector.fullname" .) .Values.cainjector.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.cainjector.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +startupapicheck templates +*/}} + +{{/* +Expand the name of the chart. +Manually fix the 'app' and 'name' labels to 'startupapicheck' to maintain +compatibility with the v0.9 deployment selector. +*/}} +{{- define "startupapicheck.name" -}} +{{- printf "startupapicheck" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "startupapicheck.fullname" -}} +{{- $trimmedName := printf "%s" (include "cert-manager.fullname" .) | trunc 52 | trimSuffix "-" -}} +{{- printf "%s-startupapicheck" $trimmedName | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "startupapicheck.serviceAccountName" -}} +{{- if .Values.startupapicheck.serviceAccount.create -}} + {{ default (include "startupapicheck.fullname" .) .Values.startupapicheck.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.startupapicheck.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "chartName" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Labels that should be added on each resource +*/}} +{{- define "labels" -}} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- if eq .Values.creator "helm" }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +helm.sh/chart: {{ include "chartName" . }} +{{- end -}} +{{- if .Values.global.commonLabels}} +{{ toYaml .Values.global.commonLabels }} +{{- end }} +{{- end -}} + +{{/* +Namespace for all resources to be installed into +If not defined in values file then the helm release namespace is used +By default this is not set so the helm release namespace will be used + +This gets around an problem within helm discussed here +https://github.com/helm/helm/issues/5358 +*/}} +{{- define "cert-manager.namespace" -}} + {{ .Values.namespace | default .Release.Namespace }} +{{- end -}} + +{{/* +Util function for generating the image URL based on the provided options. +IMPORTANT: This function is standardized across all charts in the cert-manager GH organization. +Any changes to this function should also be made in cert-manager, trust-manager, approver-policy, ... +See https://github.com/cert-manager/cert-manager/issues/6329 for a list of linked PRs. +*/}} +{{- define "image" -}} +{{- $defaultTag := index . 1 -}} +{{- with index . 0 -}} +{{- if .registry -}}{{ printf "%s/%s" .registry .repository }}{{- else -}}{{- .repository -}}{{- end -}} +{{- if .digest -}}{{ printf "@%s" .digest }}{{- else -}}{{ printf ":%s" (default $defaultTag .tag) }}{{- end -}} +{{- end }} +{{- end }} + +{{/* +Check that the user has not set both .installCRDs and .crds.enabled or +set .installCRDs and disabled .crds.keep. +.installCRDs is deprecated and users should use .crds.enabled and .crds.keep instead. +*/}} +{{- define "cert-manager.crd-check" -}} + {{- if and (.Values.installCRDs) (.Values.crds.enabled) }} + {{- fail "ERROR: the deprecated .installCRDs option cannot be enabled at the same time as its replacement .crds.enabled" }} + {{- end }} + {{- if and (.Values.installCRDs) (not .Values.crds.keep) }} + {{- fail "ERROR: .crds.keep is not compatible with .installCRDs, please use .crds.enabled and .crds.keep instead" }} + {{- end }} +{{- end -}} diff --git a/backing-services/cert-manager/templates/cainjector-config.yaml b/backing-services/cert-manager/templates/cainjector-config.yaml new file mode 100644 index 0000000..994cfa3 --- /dev/null +++ b/backing-services/cert-manager/templates/cainjector-config.yaml @@ -0,0 +1,19 @@ +{{- if .Values.cainjector.config -}} +{{- $config := .Values.cainjector.config -}} +{{- $_ := set $config "apiVersion" (default "cainjector.config.cert-manager.io/v1alpha1" $config.apiVersion) -}} +{{- $_ := set $config "kind" (default "CAInjectorConfiguration" $config.kind) -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "cainjector.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} +data: + config.yaml: | + {{- $config | toYaml | nindent 4 }} +{{- end -}} \ No newline at end of file diff --git a/backing-services/cert-manager/templates/cainjector-deployment.yaml b/backing-services/cert-manager/templates/cainjector-deployment.yaml new file mode 100644 index 0000000..65e6589 --- /dev/null +++ b/backing-services/cert-manager/templates/cainjector-deployment.yaml @@ -0,0 +1,160 @@ +{{- if .Values.cainjector.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "cainjector.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} + {{- with .Values.cainjector.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.cainjector.replicaCount }} + {{- /* The if statement below is equivalent to {{- if $value }} but will also return true for 0. */ -}} + {{- if not (has (quote .Values.global.revisionHistoryLimit) (list "" (quote ""))) }} + revisionHistoryLimit: {{ .Values.global.revisionHistoryLimit }} + {{- end }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- with .Values.cainjector.strategy }} + strategy: + {{- toYaml . | nindent 4 }} + {{- end }} + template: + metadata: + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 8 }} + {{- with .Values.cainjector.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.cainjector.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if and .Values.prometheus.enabled (not (or .Values.prometheus.servicemonitor.enabled .Values.prometheus.podmonitor.enabled)) }} + {{- if not .Values.cainjector.podAnnotations }} + annotations: + {{- end }} + prometheus.io/path: "/metrics" + prometheus.io/scrape: 'true' + prometheus.io/port: '9402' + {{- end }} + spec: + serviceAccountName: {{ template "cainjector.serviceAccountName" . }} + {{- if hasKey .Values.cainjector "automountServiceAccountToken" }} + automountServiceAccountToken: {{ .Values.cainjector.automountServiceAccountToken }} + {{- end }} + enableServiceLinks: {{ .Values.cainjector.enableServiceLinks }} + {{- with .Values.global.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} + {{- with .Values.cainjector.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }}-cainjector + image: "{{ template "image" (tuple .Values.cainjector.image $.Chart.AppVersion) }}" + imagePullPolicy: {{ .Values.cainjector.image.pullPolicy }} + args: + {{- /* The if statement below is equivalent to {{- if $value }} but will also return true for 0. */ -}} + {{- if not (has (quote .Values.global.logLevel) (list "" (quote ""))) }} + - --v={{ .Values.global.logLevel }} + {{- end }} + {{- if .Values.cainjector.config }} + - --config=/var/cert-manager/config/config.yaml + {{- end }} + {{- with .Values.global.leaderElection }} + - --leader-election-namespace={{ .namespace }} + {{- if .leaseDuration }} + - --leader-election-lease-duration={{ .leaseDuration }} + {{- end }} + {{- if .renewDeadline }} + - --leader-election-renew-deadline={{ .renewDeadline }} + {{- end }} + {{- if .retryPeriod }} + - --leader-election-retry-period={{ .retryPeriod }} + {{- end }} + {{- end }} + {{- with .Values.cainjector.featureGates}} + - --feature-gates={{ . }} + {{- end}} + {{- with .Values.cainjector.extraArgs }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- if not .Values.prometheus.enabled }} + - --metrics-listen-address=0 + {{- end }} + {{- if .Values.prometheus.enabled }} + ports: + - containerPort: 9402 + name: http-metrics + protocol: TCP + {{- end }} + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- with .Values.cainjector.extraEnv }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.cainjector.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.cainjector.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if or .Values.cainjector.config .Values.cainjector.volumeMounts }} + volumeMounts: + {{- if .Values.cainjector.config }} + - name: config + mountPath: /var/cert-manager/config + {{- end }} + {{- with .Values.cainjector.volumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} + {{- with .Values.cainjector.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.cainjector.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.cainjector.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.cainjector.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if or .Values.cainjector.volumes .Values.cainjector.config }} + volumes: + {{- if .Values.cainjector.config }} + - name: config + configMap: + name: {{ include "cainjector.fullname" . }} + {{- end }} + {{ with .Values.cainjector.volumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/cert-manager/templates/cainjector-poddisruptionbudget.yaml b/backing-services/cert-manager/templates/cainjector-poddisruptionbudget.yaml new file mode 100644 index 0000000..6a7d609 --- /dev/null +++ b/backing-services/cert-manager/templates/cainjector-poddisruptionbudget.yaml @@ -0,0 +1,29 @@ +{{- if .Values.cainjector.podDisruptionBudget.enabled }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "cainjector.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + + {{- if not (or (hasKey .Values.cainjector.podDisruptionBudget "minAvailable") (hasKey .Values.cainjector.podDisruptionBudget "maxUnavailable")) }} + minAvailable: 1 # Default value because minAvailable and maxUnavailable are not set + {{- end }} + {{- if hasKey .Values.cainjector.podDisruptionBudget "minAvailable" }} + minAvailable: {{ .Values.cainjector.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if hasKey .Values.cainjector.podDisruptionBudget "maxUnavailable" }} + maxUnavailable: {{ .Values.cainjector.podDisruptionBudget.maxUnavailable }} + {{- end }} +{{- end }} diff --git a/backing-services/cert-manager/templates/cainjector-psp-clusterrole.yaml b/backing-services/cert-manager/templates/cainjector-psp-clusterrole.yaml new file mode 100644 index 0000000..b75b9eb --- /dev/null +++ b/backing-services/cert-manager/templates/cainjector-psp-clusterrole.yaml @@ -0,0 +1,20 @@ +{{- if .Values.cainjector.enabled }} +{{- if .Values.global.podSecurityPolicy.enabled }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "cainjector.fullname" . }}-psp + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} +rules: +- apiGroups: ['policy'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "cainjector.fullname" . }} +{{- end }} +{{- end }} diff --git a/backing-services/cert-manager/templates/cainjector-psp-clusterrolebinding.yaml b/backing-services/cert-manager/templates/cainjector-psp-clusterrolebinding.yaml new file mode 100644 index 0000000..e2bfa26 --- /dev/null +++ b/backing-services/cert-manager/templates/cainjector-psp-clusterrolebinding.yaml @@ -0,0 +1,22 @@ +{{- if .Values.cainjector.enabled }} +{{- if .Values.global.podSecurityPolicy.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cainjector.fullname" . }}-psp + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cainjector.fullname" . }}-psp +subjects: + - kind: ServiceAccount + name: {{ template "cainjector.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} +{{- end }} +{{- end }} diff --git a/backing-services/cert-manager/templates/cainjector-psp.yaml b/backing-services/cert-manager/templates/cainjector-psp.yaml new file mode 100644 index 0000000..24f01da --- /dev/null +++ b/backing-services/cert-manager/templates/cainjector-psp.yaml @@ -0,0 +1,51 @@ +{{- if .Values.cainjector.enabled }} +{{- if .Values.global.podSecurityPolicy.enabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "cainjector.fullname" . }} + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} + annotations: + seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default' + seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + {{- if .Values.global.podSecurityPolicy.useAppArmor }} + apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' + apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + {{- end }} +spec: + privileged: false + allowPrivilegeEscalation: false + allowedCapabilities: [] # default set of capabilities are implicitly allowed + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 +{{- end }} +{{- end }} diff --git a/backing-services/cert-manager/templates/cainjector-rbac.yaml b/backing-services/cert-manager/templates/cainjector-rbac.yaml new file mode 100644 index 0000000..511073c --- /dev/null +++ b/backing-services/cert-manager/templates/cainjector-rbac.yaml @@ -0,0 +1,156 @@ +{{- if .Values.cainjector.enabled }} +{{- if .Values.global.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cainjector.fullname" . }} + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} +rules: + - apiGroups: ["cert-manager.io"] + resources: ["certificates"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["events"] + verbs: ["get", "create", "update", "patch"] + - apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations", "mutatingwebhookconfigurations"] + verbs: ["get", "list", "watch", "update", "patch"] + - apiGroups: ["apiregistration.k8s.io"] + resources: ["apiservices"] + verbs: ["get", "list", "watch", "update", "patch"] + - apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch", "update", "patch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cainjector.fullname" . }} + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cainjector.fullname" . }} +subjects: + - name: {{ template "cainjector.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + kind: ServiceAccount + +--- +# leader election rules +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "cainjector.fullname" . }}:leaderelection + namespace: {{ .Values.global.leaderElection.namespace }} + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} +rules: + # Used for leader election by the controller + # cert-manager-cainjector-leader-election is used by the CertificateBased injector controller + # see cmd/cainjector/start.go#L113 + # cert-manager-cainjector-leader-election-core is used by the SecretBased injector controller + # see cmd/cainjector/start.go#L137 + - apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + resourceNames: ["cert-manager-cainjector-leader-election", "cert-manager-cainjector-leader-election-core"] + verbs: ["get", "update", "patch"] + - apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["create"] + +--- + +# grant cert-manager permission to manage the leaderelection configmap in the +# leader election namespace +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "cainjector.fullname" . }}:leaderelection + namespace: {{ .Values.global.leaderElection.namespace }} + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "cainjector.fullname" . }}:leaderelection +subjects: + - kind: ServiceAccount + name: {{ template "cainjector.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} +{{- end }} +{{- end }} +{{- $certmanagerNamespace := include "cert-manager.namespace" . }} +{{- if (.Values.cainjector.config.metricsTLSConfig).dynamic }} +{{- if $certmanagerNamespace | eq .Values.cainjector.config.metricsTLSConfig.dynamic.secretNamespace }} + +--- + +# Metrics server dynamic TLS serving certificate rules +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "cainjector.fullname" . }}:dynamic-serving + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: ["secrets"] + resourceNames: + # Allow cainjector to read and update the metrics CA Secret when dynamic TLS is + # enabled for the metrics server and if the Secret is configured to be in the + # same namespace as cert-manager. + - {{ .Values.cainjector.config.metricsTLSConfig.dynamic.secretName | quote }} + verbs: ["get", "list", "watch", "update"] + # It's not possible to grant CREATE permission on a single resourceName. + - apiGroups: [""] + resources: ["secrets"] + verbs: ["create"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "cainjector.fullname" . }}:dynamic-serving + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "cainjector.fullname" . }}:dynamic-serving +subjects: + - kind: ServiceAccount + name: {{ template "cainjector.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} +{{- end }} +{{- end }} diff --git a/backing-services/cert-manager/templates/cainjector-service.yaml b/backing-services/cert-manager/templates/cainjector-service.yaml new file mode 100644 index 0000000..2ed9178 --- /dev/null +++ b/backing-services/cert-manager/templates/cainjector-service.yaml @@ -0,0 +1,30 @@ +{{- if and .Values.prometheus.enabled (not .Values.prometheus.podmonitor.enabled) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "cainjector.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} +{{- with .Values.cainjector.serviceAnnotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} + {{- with .Values.cainjector.serviceLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + ports: + - protocol: TCP + port: 9402 + name: http-metrics + selector: + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" +{{- end }} diff --git a/backing-services/cert-manager/templates/cainjector-serviceaccount.yaml b/backing-services/cert-manager/templates/cainjector-serviceaccount.yaml new file mode 100644 index 0000000..fedc731 --- /dev/null +++ b/backing-services/cert-manager/templates/cainjector-serviceaccount.yaml @@ -0,0 +1,27 @@ +{{- if .Values.cainjector.enabled }} +{{- if .Values.cainjector.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +automountServiceAccountToken: {{ .Values.cainjector.serviceAccount.automountServiceAccountToken }} +metadata: + name: {{ template "cainjector.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + {{- with .Values.cainjector.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} + {{- with .Values.cainjector.serviceAccount.labels }} + {{ toYaml . | nindent 4 }} + {{- end }} +{{- with .Values.global.imagePullSecrets }} +imagePullSecrets: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/cert-manager/templates/controller-config.yaml b/backing-services/cert-manager/templates/controller-config.yaml new file mode 100644 index 0000000..46d2cc2 --- /dev/null +++ b/backing-services/cert-manager/templates/controller-config.yaml @@ -0,0 +1,19 @@ +{{- if .Values.config -}} +{{- $config := .Values.config -}} +{{- $_ := set $config "apiVersion" (default "controller.config.cert-manager.io/v1alpha1" $config.apiVersion) -}} +{{- $_ := set $config "kind" (default "ControllerConfiguration" $config.kind) -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "cert-manager.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +data: + config.yaml: | + {{- $config | toYaml | nindent 4 }} +{{- end -}} \ No newline at end of file diff --git a/backing-services/cert-manager/templates/crds.yaml b/backing-services/cert-manager/templates/crds.yaml new file mode 100644 index 0000000..00930f9 --- /dev/null +++ b/backing-services/cert-manager/templates/crds.yaml @@ -0,0 +1,12013 @@ +# {{- include "cert-manager.crd-check" . }} +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: certificaterequests.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: cert-manager.io + names: + kind: CertificateRequest + listKind: CertificateRequestList + plural: certificaterequests + shortNames: + - cr + - crs + singular: certificaterequest + categories: + - cert-manager + scope: Namespaced + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Approved")].status + name: Approved + type: string + - jsonPath: .status.conditions[?(@.type=="Denied")].status + name: Denied + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .spec.issuerRef.name + name: Issuer + type: string + - jsonPath: .spec.username + name: Requester + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: |- + A CertificateRequest is used to request a signed certificate from one of the + configured issuers. + + All fields within the CertificateRequest's `spec` are immutable after creation. + A CertificateRequest will either succeed or fail, as denoted by its `Ready` status + condition and its `status.failureTime` field. + + A CertificateRequest is a one-shot resource, meaning it represents a single + point in time request for a certificate and cannot be re-used. + type: object + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + Specification of the desired state of the CertificateRequest resource. + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status + type: object + required: + - issuerRef + - request + properties: + duration: + description: |- + Requested 'duration' (i.e. lifetime) of the Certificate. Note that the + issuer may choose to ignore the requested duration, just like any other + requested attribute. + type: string + extra: + description: |- + Extra contains extra attributes of the user that created the CertificateRequest. + Populated by the cert-manager webhook on creation and immutable. + type: object + additionalProperties: + type: array + items: + type: string + groups: + description: |- + Groups contains group membership of the user that created the CertificateRequest. + Populated by the cert-manager webhook on creation and immutable. + type: array + items: + type: string + x-kubernetes-list-type: atomic + isCA: + description: |- + Requested basic constraints isCA value. Note that the issuer may choose + to ignore the requested isCA value, just like any other requested attribute. + + NOTE: If the CSR in the `Request` field has a BasicConstraints extension, + it must have the same isCA value as specified here. + + If true, this will automatically add the `cert sign` usage to the list + of requested `usages`. + type: boolean + issuerRef: + description: |- + Reference to the issuer responsible for issuing the certificate. + If the issuer is namespace-scoped, it must be in the same namespace + as the Certificate. If the issuer is cluster-scoped, it can be used + from any namespace. + + The `name` field of the reference must always be specified. + type: object + required: + - name + properties: + group: + description: Group of the resource being referred to. + type: string + kind: + description: Kind of the resource being referred to. + type: string + name: + description: Name of the resource being referred to. + type: string + request: + description: |- + The PEM-encoded X.509 certificate signing request to be submitted to the + issuer for signing. + + If the CSR has a BasicConstraints extension, its isCA attribute must + match the `isCA` value of this CertificateRequest. + If the CSR has a KeyUsage extension, its key usages must match the + key usages in the `usages` field of this CertificateRequest. + If the CSR has a ExtKeyUsage extension, its extended key usages + must match the extended key usages in the `usages` field of this + CertificateRequest. + type: string + format: byte + uid: + description: |- + UID contains the uid of the user that created the CertificateRequest. + Populated by the cert-manager webhook on creation and immutable. + type: string + usages: + description: |- + Requested key usages and extended key usages. + + NOTE: If the CSR in the `Request` field has uses the KeyUsage or + ExtKeyUsage extension, these extensions must have the same values + as specified here without any additional values. + + If unset, defaults to `digital signature` and `key encipherment`. + type: array + items: + description: |- + KeyUsage specifies valid usage contexts for keys. + See: + https://tools.ietf.org/html/rfc5280#section-4.2.1.3 + https://tools.ietf.org/html/rfc5280#section-4.2.1.12 + + Valid KeyUsage values are as follows: + "signing", + "digital signature", + "content commitment", + "key encipherment", + "key agreement", + "data encipherment", + "cert sign", + "crl sign", + "encipher only", + "decipher only", + "any", + "server auth", + "client auth", + "code signing", + "email protection", + "s/mime", + "ipsec end system", + "ipsec tunnel", + "ipsec user", + "timestamping", + "ocsp signing", + "microsoft sgc", + "netscape sgc" + type: string + enum: + - signing + - digital signature + - content commitment + - key encipherment + - key agreement + - data encipherment + - cert sign + - crl sign + - encipher only + - decipher only + - any + - server auth + - client auth + - code signing + - email protection + - s/mime + - ipsec end system + - ipsec tunnel + - ipsec user + - timestamping + - ocsp signing + - microsoft sgc + - netscape sgc + username: + description: |- + Username contains the name of the user that created the CertificateRequest. + Populated by the cert-manager webhook on creation and immutable. + type: string + status: + description: |- + Status of the CertificateRequest. + This is set and managed automatically. + Read-only. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status + type: object + properties: + ca: + description: |- + The PEM encoded X.509 certificate of the signer, also known as the CA + (Certificate Authority). + This is set on a best-effort basis by different issuers. + If not set, the CA is assumed to be unknown/not available. + type: string + format: byte + certificate: + description: |- + The PEM encoded X.509 certificate resulting from the certificate + signing request. + If not set, the CertificateRequest has either not been completed or has + failed. More information on failure can be found by checking the + `conditions` field. + type: string + format: byte + conditions: + description: |- + List of status conditions to indicate the status of a CertificateRequest. + Known condition types are `Ready`, `InvalidRequest`, `Approved` and `Denied`. + type: array + items: + description: CertificateRequestCondition contains condition information for a CertificateRequest. + type: object + required: + - status + - type + properties: + lastTransitionTime: + description: |- + LastTransitionTime is the timestamp corresponding to the last status + change of this condition. + type: string + format: date-time + message: + description: |- + Message is a human readable description of the details of the last + transition, complementing reason. + type: string + reason: + description: |- + Reason is a brief machine readable explanation for the condition's last + transition. + type: string + status: + description: Status of the condition, one of (`True`, `False`, `Unknown`). + type: string + enum: + - "True" + - "False" + - Unknown + type: + description: |- + Type of the condition, known values are (`Ready`, `InvalidRequest`, + `Approved`, `Denied`). + type: string + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + failureTime: + description: |- + FailureTime stores the time that this CertificateRequest failed. This is + used to influence garbage collection and back-off. + type: string + format: date-time + served: true + storage: true + +# END crd {{- end }} + +--- +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: certificates.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: cert-manager.io + names: + kind: Certificate + listKind: CertificateList + plural: certificates + shortNames: + - cert + - certs + singular: certificate + categories: + - cert-manager + scope: Namespaced + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .spec.secretName + name: Secret + type: string + - jsonPath: .spec.issuerRef.name + name: Issuer + priority: 1 + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: |- + A Certificate resource should be created to ensure an up to date and signed + X.509 certificate is stored in the Kubernetes Secret resource named in `spec.secretName`. + + The stored certificate will be renewed before it expires (as configured by `spec.renewBefore`). + type: object + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + Specification of the desired state of the Certificate resource. + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status + type: object + required: + - issuerRef + - secretName + properties: + additionalOutputFormats: + description: |- + Defines extra output formats of the private key and signed certificate chain + to be written to this Certificate's target Secret. + + This is a Beta Feature enabled by default. It can be disabled with the + `--feature-gates=AdditionalCertificateOutputFormats=false` option set on both + the controller and webhook components. + type: array + items: + description: |- + CertificateAdditionalOutputFormat defines an additional output format of a + Certificate resource. These contain supplementary data formats of the signed + certificate chain and paired private key. + type: object + required: + - type + properties: + type: + description: |- + Type is the name of the format type that should be written to the + Certificate's target Secret. + type: string + enum: + - DER + - CombinedPEM + commonName: + description: |- + Requested common name X509 certificate subject attribute. + More info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6 + NOTE: TLS clients will ignore this value when any subject alternative name is + set (see https://tools.ietf.org/html/rfc6125#section-6.4.4). + + Should have a length of 64 characters or fewer to avoid generating invalid CSRs. + Cannot be set if the `literalSubject` field is set. + type: string + dnsNames: + description: Requested DNS subject alternative names. + type: array + items: + type: string + duration: + description: |- + Requested 'duration' (i.e. lifetime) of the Certificate. Note that the + issuer may choose to ignore the requested duration, just like any other + requested attribute. + + If unset, this defaults to 90 days. + Minimum accepted duration is 1 hour. + Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration. + type: string + emailAddresses: + description: Requested email subject alternative names. + type: array + items: + type: string + encodeUsagesInRequest: + description: |- + Whether the KeyUsage and ExtKeyUsage extensions should be set in the encoded CSR. + + This option defaults to true, and should only be disabled if the target + issuer does not support CSRs with these X509 KeyUsage/ ExtKeyUsage extensions. + type: boolean + ipAddresses: + description: Requested IP address subject alternative names. + type: array + items: + type: string + isCA: + description: |- + Requested basic constraints isCA value. + The isCA value is used to set the `isCA` field on the created CertificateRequest + resources. Note that the issuer may choose to ignore the requested isCA value, just + like any other requested attribute. + + If true, this will automatically add the `cert sign` usage to the list + of requested `usages`. + type: boolean + issuerRef: + description: |- + Reference to the issuer responsible for issuing the certificate. + If the issuer is namespace-scoped, it must be in the same namespace + as the Certificate. If the issuer is cluster-scoped, it can be used + from any namespace. + + The `name` field of the reference must always be specified. + type: object + required: + - name + properties: + group: + description: Group of the resource being referred to. + type: string + kind: + description: Kind of the resource being referred to. + type: string + name: + description: Name of the resource being referred to. + type: string + keystores: + description: Additional keystore output formats to be stored in the Certificate's Secret. + type: object + properties: + jks: + description: |- + JKS configures options for storing a JKS keystore in the + `spec.secretName` Secret resource. + type: object + required: + - create + - passwordSecretRef + properties: + alias: + description: |- + Alias specifies the alias of the key in the keystore, required by the JKS format. + If not provided, the default alias `certificate` will be used. + type: string + create: + description: |- + Create enables JKS keystore creation for the Certificate. + If true, a file named `keystore.jks` will be created in the target + Secret resource, encrypted using the password stored in + `passwordSecretRef`. + The keystore file will be updated immediately. + If the issuer provided a CA certificate, a file named `truststore.jks` + will also be created in the target Secret resource, encrypted using the + password stored in `passwordSecretRef` + containing the issuing Certificate Authority + type: boolean + passwordSecretRef: + description: |- + PasswordSecretRef is a reference to a key in a Secret resource + containing the password used to encrypt the JKS keystore. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + pkcs12: + description: |- + PKCS12 configures options for storing a PKCS12 keystore in the + `spec.secretName` Secret resource. + type: object + required: + - create + - passwordSecretRef + properties: + create: + description: |- + Create enables PKCS12 keystore creation for the Certificate. + If true, a file named `keystore.p12` will be created in the target + Secret resource, encrypted using the password stored in + `passwordSecretRef`. + The keystore file will be updated immediately. + If the issuer provided a CA certificate, a file named `truststore.p12` will + also be created in the target Secret resource, encrypted using the + password stored in `passwordSecretRef` containing the issuing Certificate + Authority + type: boolean + passwordSecretRef: + description: |- + PasswordSecretRef is a reference to a key in a Secret resource + containing the password used to encrypt the PKCS12 keystore. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + profile: + description: |- + Profile specifies the key and certificate encryption algorithms and the HMAC algorithm + used to create the PKCS12 keystore. Default value is `LegacyRC2` for backward compatibility. + + If provided, allowed values are: + `LegacyRC2`: Deprecated. Not supported by default in OpenSSL 3 or Java 20. + `LegacyDES`: Less secure algorithm. Use this option for maximal compatibility. + `Modern2023`: Secure algorithm. Use this option in case you have to always use secure algorithms + (eg. because of company policy). Please note that the security of the algorithm is not that important + in reality, because the unencrypted certificate and private key are also stored in the Secret. + type: string + enum: + - LegacyRC2 + - LegacyDES + - Modern2023 + literalSubject: + description: |- + Requested X.509 certificate subject, represented using the LDAP "String + Representation of a Distinguished Name" [1]. + Important: the LDAP string format also specifies the order of the attributes + in the subject, this is important when issuing certs for LDAP authentication. + Example: `CN=foo,DC=corp,DC=example,DC=com` + More info [1]: https://datatracker.ietf.org/doc/html/rfc4514 + More info: https://github.com/cert-manager/cert-manager/issues/3203 + More info: https://github.com/cert-manager/cert-manager/issues/4424 + + Cannot be set if the `subject` or `commonName` field is set. + type: string + nameConstraints: + description: |- + x.509 certificate NameConstraint extension which MUST NOT be used in a non-CA certificate. + More Info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.10 + + This is an Alpha Feature and is only enabled with the + `--feature-gates=NameConstraints=true` option set on both + the controller and webhook components. + type: object + properties: + critical: + description: if true then the name constraints are marked critical. + type: boolean + excluded: + description: |- + Excluded contains the constraints which must be disallowed. Any name matching a + restriction in the excluded field is invalid regardless + of information appearing in the permitted + type: object + properties: + dnsDomains: + description: DNSDomains is a list of DNS domains that are permitted or excluded. + type: array + items: + type: string + emailAddresses: + description: EmailAddresses is a list of Email Addresses that are permitted or excluded. + type: array + items: + type: string + ipRanges: + description: |- + IPRanges is a list of IP Ranges that are permitted or excluded. + This should be a valid CIDR notation. + type: array + items: + type: string + uriDomains: + description: URIDomains is a list of URI domains that are permitted or excluded. + type: array + items: + type: string + permitted: + description: Permitted contains the constraints in which the names must be located. + type: object + properties: + dnsDomains: + description: DNSDomains is a list of DNS domains that are permitted or excluded. + type: array + items: + type: string + emailAddresses: + description: EmailAddresses is a list of Email Addresses that are permitted or excluded. + type: array + items: + type: string + ipRanges: + description: |- + IPRanges is a list of IP Ranges that are permitted or excluded. + This should be a valid CIDR notation. + type: array + items: + type: string + uriDomains: + description: URIDomains is a list of URI domains that are permitted or excluded. + type: array + items: + type: string + otherNames: + description: |- + `otherNames` is an escape hatch for SAN that allows any type. We currently restrict the support to string like otherNames, cf RFC 5280 p 37 + Any UTF8 String valued otherName can be passed with by setting the keys oid: x.x.x.x and UTF8Value: somevalue for `otherName`. + Most commonly this would be UPN set with oid: 1.3.6.1.4.1.311.20.2.3 + You should ensure that any OID passed is valid for the UTF8String type as we do not explicitly validate this. + type: array + items: + type: object + properties: + oid: + description: |- + OID is the object identifier for the otherName SAN. + The object identifier must be expressed as a dotted string, for + example, "1.2.840.113556.1.4.221". + type: string + utf8Value: + description: |- + utf8Value is the string value of the otherName SAN. + The utf8Value accepts any valid UTF8 string to set as value for the otherName SAN. + type: string + privateKey: + description: |- + Private key options. These include the key algorithm and size, the used + encoding and the rotation policy. + type: object + properties: + algorithm: + description: |- + Algorithm is the private key algorithm of the corresponding private key + for this certificate. + + If provided, allowed values are either `RSA`, `ECDSA` or `Ed25519`. + If `algorithm` is specified and `size` is not provided, + key size of 2048 will be used for `RSA` key algorithm and + key size of 256 will be used for `ECDSA` key algorithm. + key size is ignored when using the `Ed25519` key algorithm. + type: string + enum: + - RSA + - ECDSA + - Ed25519 + encoding: + description: |- + The private key cryptography standards (PKCS) encoding for this + certificate's private key to be encoded in. + + If provided, allowed values are `PKCS1` and `PKCS8` standing for PKCS#1 + and PKCS#8, respectively. + Defaults to `PKCS1` if not specified. + type: string + enum: + - PKCS1 + - PKCS8 + rotationPolicy: + description: |- + RotationPolicy controls how private keys should be regenerated when a + re-issuance is being processed. + + If set to `Never`, a private key will only be generated if one does not + already exist in the target `spec.secretName`. If one does exist but it + does not have the correct algorithm or size, a warning will be raised + to await user intervention. + If set to `Always`, a private key matching the specified requirements + will be generated whenever a re-issuance occurs. + Default is `Never` for backward compatibility. + type: string + enum: + - Never + - Always + size: + description: |- + Size is the key bit size of the corresponding private key for this certificate. + + If `algorithm` is set to `RSA`, valid values are `2048`, `4096` or `8192`, + and will default to `2048` if not specified. + If `algorithm` is set to `ECDSA`, valid values are `256`, `384` or `521`, + and will default to `256` if not specified. + If `algorithm` is set to `Ed25519`, Size is ignored. + No other values are allowed. + type: integer + renewBefore: + description: |- + How long before the currently issued certificate's expiry cert-manager should + renew the certificate. For example, if a certificate is valid for 60 minutes, + and `renewBefore=10m`, cert-manager will begin to attempt to renew the certificate + 50 minutes after it was issued (i.e. when there are 10 minutes remaining until + the certificate is no longer valid). + + NOTE: The actual lifetime of the issued certificate is used to determine the + renewal time. If an issuer returns a certificate with a different lifetime than + the one requested, cert-manager will use the lifetime of the issued certificate. + + If unset, this defaults to 1/3 of the issued certificate's lifetime. + Minimum accepted value is 5 minutes. + Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration. + Cannot be set if the `renewBeforePercentage` field is set. + type: string + renewBeforePercentage: + description: |- + `renewBeforePercentage` is like `renewBefore`, except it is a relative percentage + rather than an absolute duration. For example, if a certificate is valid for 60 + minutes, and `renewBeforePercentage=25`, cert-manager will begin to attempt to + renew the certificate 45 minutes after it was issued (i.e. when there are 15 + minutes (25%) remaining until the certificate is no longer valid). + + NOTE: The actual lifetime of the issued certificate is used to determine the + renewal time. If an issuer returns a certificate with a different lifetime than + the one requested, cert-manager will use the lifetime of the issued certificate. + + Value must be an integer in the range (0,100). The minimum effective + `renewBefore` derived from the `renewBeforePercentage` and `duration` fields is 5 + minutes. + Cannot be set if the `renewBefore` field is set. + type: integer + format: int32 + revisionHistoryLimit: + description: |- + The maximum number of CertificateRequest revisions that are maintained in + the Certificate's history. Each revision represents a single `CertificateRequest` + created by this Certificate, either when it was created, renewed, or Spec + was changed. Revisions will be removed by oldest first if the number of + revisions exceeds this number. + + If set, revisionHistoryLimit must be a value of `1` or greater. + If unset (`nil`), revisions will not be garbage collected. + Default value is `nil`. + type: integer + format: int32 + secretName: + description: |- + Name of the Secret resource that will be automatically created and + managed by this Certificate resource. It will be populated with a + private key and certificate, signed by the denoted issuer. The Secret + resource lives in the same namespace as the Certificate resource. + type: string + secretTemplate: + description: |- + Defines annotations and labels to be copied to the Certificate's Secret. + Labels and annotations on the Secret will be changed as they appear on the + SecretTemplate when added or removed. SecretTemplate annotations are added + in conjunction with, and cannot overwrite, the base set of annotations + cert-manager sets on the Certificate's Secret. + type: object + properties: + annotations: + description: Annotations is a key value map to be copied to the target Kubernetes Secret. + type: object + additionalProperties: + type: string + labels: + description: Labels is a key value map to be copied to the target Kubernetes Secret. + type: object + additionalProperties: + type: string + subject: + description: |- + Requested set of X509 certificate subject attributes. + More info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6 + + The common name attribute is specified separately in the `commonName` field. + Cannot be set if the `literalSubject` field is set. + type: object + properties: + countries: + description: Countries to be used on the Certificate. + type: array + items: + type: string + localities: + description: Cities to be used on the Certificate. + type: array + items: + type: string + organizationalUnits: + description: Organizational Units to be used on the Certificate. + type: array + items: + type: string + organizations: + description: Organizations to be used on the Certificate. + type: array + items: + type: string + postalCodes: + description: Postal codes to be used on the Certificate. + type: array + items: + type: string + provinces: + description: State/Provinces to be used on the Certificate. + type: array + items: + type: string + serialNumber: + description: Serial number to be used on the Certificate. + type: string + streetAddresses: + description: Street addresses to be used on the Certificate. + type: array + items: + type: string + uris: + description: Requested URI subject alternative names. + type: array + items: + type: string + usages: + description: |- + Requested key usages and extended key usages. + These usages are used to set the `usages` field on the created CertificateRequest + resources. If `encodeUsagesInRequest` is unset or set to `true`, the usages + will additionally be encoded in the `request` field which contains the CSR blob. + + If unset, defaults to `digital signature` and `key encipherment`. + type: array + items: + description: |- + KeyUsage specifies valid usage contexts for keys. + See: + https://tools.ietf.org/html/rfc5280#section-4.2.1.3 + https://tools.ietf.org/html/rfc5280#section-4.2.1.12 + + Valid KeyUsage values are as follows: + "signing", + "digital signature", + "content commitment", + "key encipherment", + "key agreement", + "data encipherment", + "cert sign", + "crl sign", + "encipher only", + "decipher only", + "any", + "server auth", + "client auth", + "code signing", + "email protection", + "s/mime", + "ipsec end system", + "ipsec tunnel", + "ipsec user", + "timestamping", + "ocsp signing", + "microsoft sgc", + "netscape sgc" + type: string + enum: + - signing + - digital signature + - content commitment + - key encipherment + - key agreement + - data encipherment + - cert sign + - crl sign + - encipher only + - decipher only + - any + - server auth + - client auth + - code signing + - email protection + - s/mime + - ipsec end system + - ipsec tunnel + - ipsec user + - timestamping + - ocsp signing + - microsoft sgc + - netscape sgc + status: + description: |- + Status of the Certificate. + This is set and managed automatically. + Read-only. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status + type: object + properties: + conditions: + description: |- + List of status conditions to indicate the status of certificates. + Known condition types are `Ready` and `Issuing`. + type: array + items: + description: CertificateCondition contains condition information for a Certificate. + type: object + required: + - status + - type + properties: + lastTransitionTime: + description: |- + LastTransitionTime is the timestamp corresponding to the last status + change of this condition. + type: string + format: date-time + message: + description: |- + Message is a human readable description of the details of the last + transition, complementing reason. + type: string + observedGeneration: + description: |- + If set, this represents the .metadata.generation that the condition was + set based upon. + For instance, if .metadata.generation is currently 12, but the + .status.condition[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the Certificate. + type: integer + format: int64 + reason: + description: |- + Reason is a brief machine readable explanation for the condition's last + transition. + type: string + status: + description: Status of the condition, one of (`True`, `False`, `Unknown`). + type: string + enum: + - "True" + - "False" + - Unknown + type: + description: Type of the condition, known values are (`Ready`, `Issuing`). + type: string + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + failedIssuanceAttempts: + description: |- + The number of continuous failed issuance attempts up till now. This + field gets removed (if set) on a successful issuance and gets set to + 1 if unset and an issuance has failed. If an issuance has failed, the + delay till the next issuance will be calculated using formula + time.Hour * 2 ^ (failedIssuanceAttempts - 1). + type: integer + lastFailureTime: + description: |- + LastFailureTime is set only if the latest issuance for this + Certificate failed and contains the time of the failure. If an + issuance has failed, the delay till the next issuance will be + calculated using formula time.Hour * 2 ^ (failedIssuanceAttempts - + 1). If the latest issuance has succeeded this field will be unset. + type: string + format: date-time + nextPrivateKeySecretName: + description: |- + The name of the Secret resource containing the private key to be used + for the next certificate iteration. + The keymanager controller will automatically set this field if the + `Issuing` condition is set to `True`. + It will automatically unset this field when the Issuing condition is + not set or False. + type: string + notAfter: + description: |- + The expiration time of the certificate stored in the secret named + by this resource in `spec.secretName`. + type: string + format: date-time + notBefore: + description: |- + The time after which the certificate stored in the secret named + by this resource in `spec.secretName` is valid. + type: string + format: date-time + renewalTime: + description: |- + RenewalTime is the time at which the certificate will be next + renewed. + If not set, no upcoming renewal is scheduled. + type: string + format: date-time + revision: + description: |- + The current 'revision' of the certificate as issued. + + When a CertificateRequest resource is created, it will have the + `cert-manager.io/certificate-revision` set to one greater than the + current value of this field. + + Upon issuance, this field will be set to the value of the annotation + on the CertificateRequest resource used to issue the certificate. + + Persisting the value on the CertificateRequest resource allows the + certificates controller to know whether a request is part of an old + issuance or if it is part of the ongoing revision's issuance by + checking if the revision value in the annotation is greater than this + field. + type: integer + served: true + storage: true + +# END crd {{- end }} + +--- +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: challenges.acme.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: acme.cert-manager.io + names: + kind: Challenge + listKind: ChallengeList + plural: challenges + singular: challenge + categories: + - cert-manager + - cert-manager-acme + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.state + name: State + type: string + - jsonPath: .spec.dnsName + name: Domain + type: string + - jsonPath: .status.reason + name: Reason + priority: 1 + type: string + - description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: Challenge is a type to represent a Challenge request with an ACME server + type: object + required: + - metadata + - spec + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + type: object + required: + - authorizationURL + - dnsName + - issuerRef + - key + - solver + - token + - type + - url + properties: + authorizationURL: + description: |- + The URL to the ACME Authorization resource that this + challenge is a part of. + type: string + dnsName: + description: |- + dnsName is the identifier that this challenge is for, e.g. example.com. + If the requested DNSName is a 'wildcard', this field MUST be set to the + non-wildcard domain, e.g. for `*.example.com`, it must be `example.com`. + type: string + issuerRef: + description: |- + References a properly configured ACME-type Issuer which should + be used to create this Challenge. + If the Issuer does not exist, processing will be retried. + If the Issuer is not an 'ACME' Issuer, an error will be returned and the + Challenge will be marked as failed. + type: object + required: + - name + properties: + group: + description: Group of the resource being referred to. + type: string + kind: + description: Kind of the resource being referred to. + type: string + name: + description: Name of the resource being referred to. + type: string + key: + description: |- + The ACME challenge key for this challenge + For HTTP01 challenges, this is the value that must be responded with to + complete the HTTP01 challenge in the format: + `.`. + For DNS01 challenges, this is the base64 encoded SHA256 sum of the + `.` + text that must be set as the TXT record content. + type: string + solver: + description: |- + Contains the domain solving configuration that should be used to + solve this challenge resource. + type: object + properties: + dns01: + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the DNS01 challenge flow. + type: object + properties: + acmeDNS: + description: |- + Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage + DNS01 challenge records. + type: object + required: + - accountSecretRef + - host + properties: + accountSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + host: + type: string + akamai: + description: Use the Akamai DNS zone management API to manage DNS01 challenge records. + type: object + required: + - accessTokenSecretRef + - clientSecretSecretRef + - clientTokenSecretRef + - serviceConsumerDomain + properties: + accessTokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientSecretSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientTokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + serviceConsumerDomain: + type: string + azureDNS: + description: Use the Microsoft Azure DNS API to manage DNS01 challenge records. + type: object + required: + - resourceGroupName + - subscriptionID + properties: + clientID: + description: |- + Auth: Azure Service Principal: + The ClientID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientSecret and TenantID must also be set. + type: string + clientSecretSecretRef: + description: |- + Auth: Azure Service Principal: + A reference to a Secret containing the password associated with the Service Principal. + If set, ClientID and TenantID must also be set. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + environment: + description: name of the Azure environment (default AzurePublicCloud) + type: string + enum: + - AzurePublicCloud + - AzureChinaCloud + - AzureGermanCloud + - AzureUSGovernmentCloud + hostedZoneName: + description: name of the DNS zone that should be used + type: string + managedIdentity: + description: |- + Auth: Azure Workload Identity or Azure Managed Service Identity: + Settings to enable Azure Workload Identity or Azure Managed Service Identity + If set, ClientID, ClientSecret and TenantID must not be set. + type: object + properties: + clientID: + description: client ID of the managed identity, can not be used at the same time as resourceID + type: string + resourceID: + description: |- + resource ID of the managed identity, can not be used at the same time as clientID + Cannot be used for Azure Managed Service Identity + type: string + resourceGroupName: + description: resource group the DNS zone is located in + type: string + subscriptionID: + description: ID of the Azure subscription + type: string + tenantID: + description: |- + Auth: Azure Service Principal: + The TenantID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientID and ClientSecret must also be set. + type: string + cloudDNS: + description: Use the Google Cloud DNS API to manage DNS01 challenge records. + type: object + required: + - project + properties: + hostedZoneName: + description: |- + HostedZoneName is an optional field that tells cert-manager in which + Cloud DNS zone the challenge record has to be created. + If left empty cert-manager will automatically choose a zone. + type: string + project: + type: string + serviceAccountSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + cloudflare: + description: Use the Cloudflare API to manage DNS01 challenge records. + type: object + properties: + apiKeySecretRef: + description: |- + API key to use to authenticate with Cloudflare. + Note: using an API token to authenticate is now the recommended method + as it allows greater control of permissions. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + apiTokenSecretRef: + description: API token used to authenticate with Cloudflare. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + email: + description: Email of the account, only required when using API key based authentication. + type: string + cnameStrategy: + description: |- + CNAMEStrategy configures how the DNS01 provider should handle CNAME + records when found in DNS zones. + type: string + enum: + - None + - Follow + digitalocean: + description: Use the DigitalOcean DNS API to manage DNS01 challenge records. + type: object + required: + - tokenSecretRef + properties: + tokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + rfc2136: + description: |- + Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) + to manage DNS01 challenge records. + type: object + required: + - nameserver + properties: + nameserver: + description: |- + The IP address or hostname of an authoritative DNS server supporting + RFC2136 in the form host:port. If the host is an IPv6 address it must be + enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. + This field is required. + type: string + tsigAlgorithm: + description: |- + The TSIG Algorithm configured in the DNS supporting RFC2136. Used only + when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. + Supported values are (case-insensitive): ``HMACMD5`` (default), + ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``. + type: string + tsigKeyName: + description: |- + The TSIG Key name configured in the DNS. + If ``tsigSecretSecretRef`` is defined, this field is required. + type: string + tsigSecretSecretRef: + description: |- + The name of the secret containing the TSIG value. + If ``tsigKeyName`` is defined, this field is required. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + route53: + description: Use the AWS Route53 API to manage DNS01 challenge records. + type: object + properties: + accessKeyID: + description: |- + The AccessKeyID is used for authentication. + Cannot be set when SecretAccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: string + accessKeyIDSecretRef: + description: |- + The SecretAccessKey is used for authentication. If set, pull the AWS + access key ID from a key within a Kubernetes Secret. + Cannot be set when AccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + auth: + description: Auth configures how cert-manager authenticates. + type: object + required: + - kubernetes + properties: + kubernetes: + description: |- + Kubernetes authenticates with Route53 using AssumeRoleWithWebIdentity + by passing a bound ServiceAccount token. + type: object + required: + - serviceAccountRef + properties: + serviceAccountRef: + description: |- + A reference to a service account that will be used to request a bound + token (also known as "projected token"). To use this field, you must + configure an RBAC rule to let cert-manager request a token. + type: object + required: + - name + properties: + audiences: + description: |- + TokenAudiences is an optional list of audiences to include in the + token passed to AWS. The default token consisting of the issuer's namespace + and name is always included. + If unset the audience defaults to `sts.amazonaws.com`. + type: array + items: + type: string + name: + description: Name of the ServiceAccount used to request a token. + type: string + hostedZoneID: + description: If set, the provider will manage only this zone in Route53 and will not do a lookup using the route53:ListHostedZonesByName api call. + type: string + region: + description: |- + Override the AWS region. + + Route53 is a global service and does not have regional endpoints but the + region specified here (or via environment variables) is used as a hint to + help compute the correct AWS credential scope and partition when it + connects to Route53. See: + - [Amazon Route 53 endpoints and quotas](https://docs.aws.amazon.com/general/latest/gr/r53.html) + - [Global services](https://docs.aws.amazon.com/whitepapers/latest/aws-fault-isolation-boundaries/global-services.html) + + If you omit this region field, cert-manager will use the region from + AWS_REGION and AWS_DEFAULT_REGION environment variables, if they are set + in the cert-manager controller Pod. + + The `region` field is not needed if you use [IAM Roles for Service Accounts (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html). + Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: + [Amazon EKS Pod Identity Webhook](https://github.com/aws/amazon-eks-pod-identity-webhook). + In this case this `region` field value is ignored. + + The `region` field is not needed if you use [EKS Pod Identities](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html). + Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: + [Amazon EKS Pod Identity Agent](https://github.com/aws/eks-pod-identity-agent), + In this case this `region` field value is ignored. + type: string + role: + description: |- + Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey + or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata + type: string + secretAccessKeySecretRef: + description: |- + The SecretAccessKey is used for authentication. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + webhook: + description: |- + Configure an external webhook based DNS01 challenge solver to manage + DNS01 challenge records. + type: object + required: + - groupName + - solverName + properties: + config: + description: |- + Additional configuration that should be passed to the webhook apiserver + when challenges are processed. + This can contain arbitrary JSON data. + Secret values should not be specified in this stanza. + If secret values are needed (e.g. credentials for a DNS service), you + should use a SecretKeySelector to reference a Secret resource. + For details on the schema of this field, consult the webhook provider + implementation's documentation. + x-kubernetes-preserve-unknown-fields: true + groupName: + description: |- + The API group name that should be used when POSTing ChallengePayload + resources to the webhook apiserver. + This should be the same as the GroupName specified in the webhook + provider implementation. + type: string + solverName: + description: |- + The name of the solver to use, as defined in the webhook provider + implementation. + This will typically be the name of the provider, e.g. 'cloudflare'. + type: string + http01: + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the HTTP01 challenge flow. + It is not possible to obtain certificates for wildcard domain names + (e.g. `*.example.com`) using the HTTP01 challenge mechanism. + type: object + properties: + gatewayHTTPRoute: + description: |- + The Gateway API is a sig-network community API that models service networking + in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will + create HTTPRoutes with the specified labels in the same namespace as the challenge. + This solver is experimental, and fields / behaviour may change in the future. + type: object + properties: + labels: + description: |- + Custom labels that will be applied to HTTPRoutes created by cert-manager + while solving HTTP-01 challenges. + type: object + additionalProperties: + type: string + parentRefs: + description: |- + When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. + cert-manager needs to know which parentRefs should be used when creating + the HTTPRoute. Usually, the parentRef references a Gateway. See: + https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways + type: array + items: + description: |- + ParentReference identifies an API object (usually a Gateway) that can be considered + a parent of this resource (usually a route). There are two kinds of parent resources + with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + type: object + required: + - name + properties: + group: + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + type: string + default: gateway.networking.k8s.io + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + kind: + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + type: string + default: Gateway + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + name: + description: |- + Name is the name of the referent. + + Support: Core + type: string + maxLength: 253 + minLength: 1 + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + Support: Core + type: string + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port must match both specified values. + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + type: integer + format: int32 + maximum: 65535 + minimum: 1 + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + type: string + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + podTemplate: + description: |- + Optional pod template used to configure the ACME challenge solver pods + used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the pod used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: |- + PodSpec defines overrides for the HTTP01 challenge solver pod. + Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. + All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node matches the corresponding matchExpressions; the + node(s) with the highest sum are the most preferred. + type: array + items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + x-kubernetes-list-type: atomic + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the anti-affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + x-kubernetes-list-type: atomic + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + type: object + properties: + name: + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + default: "" + x-kubernetes-map-type: atomic + nodeSelector: + description: |- + NodeSelector is a selector which must be true for the pod to fit on a node. + Selector which must match a node's labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + securityContext: + description: If specified, the pod's security context + type: object + properties: + fsGroup: + description: |- + A special supplemental group that applies to all containers in a pod. + Some volume types allow the Kubelet to change the ownership of that volume + to be owned by the pod: + + 1. The owning GID will be the FSGroup + 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- + + If unset, the Kubelet will not modify the ownership and permissions of any volume. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + fsGroupChangePolicy: + description: |- + fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + before being exposed inside Pod. This field will only apply to + volume types which support fsGroup based ownership(and permissions). + It will have no effect on ephemeral volume types such as: secret, configmaps + and emptydir. + Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. + Note that this field cannot be set when spec.os.name is windows. + type: string + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + seLinuxOptions: + description: |- + The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in SecurityContext. If set in + both SecurityContext and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + type: object + properties: + level: + description: Level is SELinux level label that applies to the container. + type: string + role: + description: Role is a SELinux role label that applies to the container. + type: string + type: + description: Type is a SELinux type label that applies to the container. + type: string + user: + description: User is a SELinux user label that applies to the container. + type: string + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + type: object + required: + - type + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + supplementalGroups: + description: |- + A list of groups applied to the first process run in each container, in addition + to the container's primary GID, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container process. If unspecified, + no additional groups are added to any container. Note that group memberships + defined in the container image for the uid of the container process are still effective, + even if they are not included in this list. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + type: integer + format: int64 + sysctls: + description: |- + Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + sysctls (by the container runtime) might fail to launch. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + description: Sysctl defines a kernel parameter to be set + type: object + required: + - name + - value + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + type: object + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + type: integer + format: int64 + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + serviceType: + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + ingress: + description: |- + The ingress based HTTP01 challenge solver will solve challenges by + creating or modifying Ingress resources in order to route requests for + '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are + provisioned by cert-manager for each Challenge to be completed. + type: object + properties: + class: + description: |- + This field configures the annotation `kubernetes.io/ingress.class` when + creating Ingress resources to solve ACME challenges that use this + challenge solver. Only one of `class`, `name` or `ingressClassName` may + be specified. + type: string + ingressClassName: + description: |- + This field configures the field `ingressClassName` on the created Ingress + resources used to solve ACME challenges that use this challenge solver. + This is the recommended way of configuring the ingress class. Only one of + `class`, `name` or `ingressClassName` may be specified. + type: string + ingressTemplate: + description: |- + Optional ingress template used to configure the ACME challenge solver + ingress used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the ingress used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + name: + description: |- + The name of the ingress resource that should have ACME challenge solving + routes inserted into it in order to solve HTTP01 challenges. + This is typically used in conjunction with ingress controllers like + ingress-gce, which maintains a 1:1 mapping between external IPs and + ingress resources. Only one of `class`, `name` or `ingressClassName` may + be specified. + type: string + podTemplate: + description: |- + Optional pod template used to configure the ACME challenge solver pods + used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the pod used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: |- + PodSpec defines overrides for the HTTP01 challenge solver pod. + Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. + All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node matches the corresponding matchExpressions; the + node(s) with the highest sum are the most preferred. + type: array + items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + x-kubernetes-list-type: atomic + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the anti-affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + x-kubernetes-list-type: atomic + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + type: object + properties: + name: + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + default: "" + x-kubernetes-map-type: atomic + nodeSelector: + description: |- + NodeSelector is a selector which must be true for the pod to fit on a node. + Selector which must match a node's labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + securityContext: + description: If specified, the pod's security context + type: object + properties: + fsGroup: + description: |- + A special supplemental group that applies to all containers in a pod. + Some volume types allow the Kubelet to change the ownership of that volume + to be owned by the pod: + + 1. The owning GID will be the FSGroup + 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- + + If unset, the Kubelet will not modify the ownership and permissions of any volume. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + fsGroupChangePolicy: + description: |- + fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + before being exposed inside Pod. This field will only apply to + volume types which support fsGroup based ownership(and permissions). + It will have no effect on ephemeral volume types such as: secret, configmaps + and emptydir. + Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. + Note that this field cannot be set when spec.os.name is windows. + type: string + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + seLinuxOptions: + description: |- + The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in SecurityContext. If set in + both SecurityContext and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + type: object + properties: + level: + description: Level is SELinux level label that applies to the container. + type: string + role: + description: Role is a SELinux role label that applies to the container. + type: string + type: + description: Type is a SELinux type label that applies to the container. + type: string + user: + description: User is a SELinux user label that applies to the container. + type: string + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + type: object + required: + - type + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + supplementalGroups: + description: |- + A list of groups applied to the first process run in each container, in addition + to the container's primary GID, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container process. If unspecified, + no additional groups are added to any container. Note that group memberships + defined in the container image for the uid of the container process are still effective, + even if they are not included in this list. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + type: integer + format: int64 + sysctls: + description: |- + Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + sysctls (by the container runtime) might fail to launch. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + description: Sysctl defines a kernel parameter to be set + type: object + required: + - name + - value + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + type: object + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + type: integer + format: int64 + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + serviceType: + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + selector: + description: |- + Selector selects a set of DNSNames on the Certificate resource that + should be solved using this challenge solver. + If not specified, the solver will be treated as the 'default' solver + with the lowest priority, i.e. if any other solver has a more specific + match, it will be used instead. + type: object + properties: + dnsNames: + description: |- + List of DNSNames that this solver will be used to solve. + If specified and a match is found, a dnsNames selector will take + precedence over a dnsZones selector. + If multiple solvers match with the same dnsNames value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. + type: array + items: + type: string + dnsZones: + description: |- + List of DNSZones that this solver will be used to solve. + The most specific DNS zone match specified here will take precedence + over other DNS zone matches, so a solver specifying sys.example.com + will be selected over one specifying example.com for the domain + www.sys.example.com. + If multiple solvers match with the same dnsZones value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. + type: array + items: + type: string + matchLabels: + description: |- + A label selector that is used to refine the set of certificate's that + this challenge solver will apply to. + type: object + additionalProperties: + type: string + token: + description: |- + The ACME challenge token for this challenge. + This is the raw value returned from the ACME server. + type: string + type: + description: |- + The type of ACME challenge this resource represents. + One of "HTTP-01" or "DNS-01". + type: string + enum: + - HTTP-01 + - DNS-01 + url: + description: |- + The URL of the ACME Challenge resource for this challenge. + This can be used to lookup details about the status of this challenge. + type: string + wildcard: + description: |- + wildcard will be true if this challenge is for a wildcard identifier, + for example '*.example.com'. + type: boolean + status: + type: object + properties: + presented: + description: |- + presented will be set to true if the challenge values for this challenge + are currently 'presented'. + This *does not* imply the self check is passing. Only that the values + have been 'submitted' for the appropriate challenge mechanism (i.e. the + DNS01 TXT record has been presented, or the HTTP01 configuration has been + configured). + type: boolean + processing: + description: |- + Used to denote whether this challenge should be processed or not. + This field will only be set to true by the 'scheduling' component. + It will only be set to false by the 'challenges' controller, after the + challenge has reached a final state or timed out. + If this field is set to false, the challenge controller will not take + any more action. + type: boolean + reason: + description: |- + Contains human readable information on why the Challenge is in the + current state. + type: string + state: + description: |- + Contains the current 'state' of the challenge. + If not set, the state of the challenge is unknown. + type: string + enum: + - valid + - ready + - pending + - processing + - invalid + - expired + - errored + served: true + storage: true + subresources: + status: {} + +# END crd {{- end }} + +--- +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: clusterissuers.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: cert-manager.io + names: + kind: ClusterIssuer + listKind: ClusterIssuerList + plural: clusterissuers + singular: clusterissuer + categories: + - cert-manager + scope: Cluster + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: |- + A ClusterIssuer represents a certificate issuing authority which can be + referenced as part of `issuerRef` fields. + It is similar to an Issuer, however it is cluster-scoped and therefore can + be referenced by resources that exist in *any* namespace, not just the same + namespace as the referent. + type: object + required: + - spec + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Desired state of the ClusterIssuer resource. + type: object + properties: + acme: + description: |- + ACME configures this issuer to communicate with a RFC8555 (ACME) server + to obtain signed x509 certificates. + type: object + required: + - privateKeySecretRef + - server + properties: + caBundle: + description: |- + Base64-encoded bundle of PEM CAs which can be used to validate the certificate + chain presented by the ACME server. + Mutually exclusive with SkipTLSVerify; prefer using CABundle to prevent various + kinds of security vulnerabilities. + If CABundle and SkipTLSVerify are unset, the system certificate bundle inside + the container is used to validate the TLS connection. + type: string + format: byte + disableAccountKeyGeneration: + description: |- + Enables or disables generating a new ACME account key. + If true, the Issuer resource will *not* request a new account but will expect + the account key to be supplied via an existing secret. + If false, the cert-manager system will generate a new ACME account key + for the Issuer. + Defaults to false. + type: boolean + email: + description: |- + Email is the email address to be associated with the ACME account. + This field is optional, but it is strongly recommended to be set. + It will be used to contact you in case of issues with your account or + certificates, including expiry notification emails. + This field may be updated after the account is initially registered. + type: string + enableDurationFeature: + description: |- + Enables requesting a Not After date on certificates that matches the + duration of the certificate. This is not supported by all ACME servers + like Let's Encrypt. If set to true when the ACME server does not support + it, it will create an error on the Order. + Defaults to false. + type: boolean + externalAccountBinding: + description: |- + ExternalAccountBinding is a reference to a CA external account of the ACME + server. + If set, upon registration cert-manager will attempt to associate the given + external account credentials with the registered ACME account. + type: object + required: + - keyID + - keySecretRef + properties: + keyAlgorithm: + description: |- + Deprecated: keyAlgorithm field exists for historical compatibility + reasons and should not be used. The algorithm is now hardcoded to HS256 + in golang/x/crypto/acme. + type: string + enum: + - HS256 + - HS384 + - HS512 + keyID: + description: keyID is the ID of the CA key that the External Account is bound to. + type: string + keySecretRef: + description: |- + keySecretRef is a Secret Key Selector referencing a data item in a Kubernetes + Secret which holds the symmetric MAC key of the External Account Binding. + The `key` is the index string that is paired with the key data in the + Secret and should not be confused with the key data itself, or indeed with + the External Account Binding keyID above. + The secret key stored in the Secret **must** be un-padded, base64 URL + encoded data. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + preferredChain: + description: |- + PreferredChain is the chain to use if the ACME server outputs multiple. + PreferredChain is no guarantee that this one gets delivered by the ACME + endpoint. + For example, for Let's Encrypt's DST crosssign you would use: + "DST Root CA X3" or "ISRG Root X1" for the newer Let's Encrypt root CA. + This value picks the first certificate bundle in the combined set of + ACME default and alternative chains that has a root-most certificate with + this value as its issuer's commonname. + type: string + maxLength: 64 + privateKeySecretRef: + description: |- + PrivateKey is the name of a Kubernetes Secret resource that will be used to + store the automatically generated ACME account private key. + Optionally, a `key` may be specified to select a specific entry within + the named Secret resource. + If `key` is not specified, a default of `tls.key` will be used. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + server: + description: |- + Server is the URL used to access the ACME server's 'directory' endpoint. + For example, for Let's Encrypt's staging endpoint, you would use: + "https://acme-staging-v02.api.letsencrypt.org/directory". + Only ACME v2 endpoints (i.e. RFC 8555) are supported. + type: string + skipTLSVerify: + description: |- + INSECURE: Enables or disables validation of the ACME server TLS certificate. + If true, requests to the ACME server will not have the TLS certificate chain + validated. + Mutually exclusive with CABundle; prefer using CABundle to prevent various + kinds of security vulnerabilities. + Only enable this option in development environments. + If CABundle and SkipTLSVerify are unset, the system certificate bundle inside + the container is used to validate the TLS connection. + Defaults to false. + type: boolean + solvers: + description: |- + Solvers is a list of challenge solvers that will be used to solve + ACME challenges for the matching domains. + Solver configurations must be provided in order to obtain certificates + from an ACME server. + For more information, see: https://cert-manager.io/docs/configuration/acme/ + type: array + items: + description: |- + An ACMEChallengeSolver describes how to solve ACME challenges for the issuer it is part of. + A selector may be provided to use different solving strategies for different DNS names. + Only one of HTTP01 or DNS01 must be provided. + type: object + properties: + dns01: + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the DNS01 challenge flow. + type: object + properties: + acmeDNS: + description: |- + Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage + DNS01 challenge records. + type: object + required: + - accountSecretRef + - host + properties: + accountSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + host: + type: string + akamai: + description: Use the Akamai DNS zone management API to manage DNS01 challenge records. + type: object + required: + - accessTokenSecretRef + - clientSecretSecretRef + - clientTokenSecretRef + - serviceConsumerDomain + properties: + accessTokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientSecretSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientTokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + serviceConsumerDomain: + type: string + azureDNS: + description: Use the Microsoft Azure DNS API to manage DNS01 challenge records. + type: object + required: + - resourceGroupName + - subscriptionID + properties: + clientID: + description: |- + Auth: Azure Service Principal: + The ClientID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientSecret and TenantID must also be set. + type: string + clientSecretSecretRef: + description: |- + Auth: Azure Service Principal: + A reference to a Secret containing the password associated with the Service Principal. + If set, ClientID and TenantID must also be set. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + environment: + description: name of the Azure environment (default AzurePublicCloud) + type: string + enum: + - AzurePublicCloud + - AzureChinaCloud + - AzureGermanCloud + - AzureUSGovernmentCloud + hostedZoneName: + description: name of the DNS zone that should be used + type: string + managedIdentity: + description: |- + Auth: Azure Workload Identity or Azure Managed Service Identity: + Settings to enable Azure Workload Identity or Azure Managed Service Identity + If set, ClientID, ClientSecret and TenantID must not be set. + type: object + properties: + clientID: + description: client ID of the managed identity, can not be used at the same time as resourceID + type: string + resourceID: + description: |- + resource ID of the managed identity, can not be used at the same time as clientID + Cannot be used for Azure Managed Service Identity + type: string + resourceGroupName: + description: resource group the DNS zone is located in + type: string + subscriptionID: + description: ID of the Azure subscription + type: string + tenantID: + description: |- + Auth: Azure Service Principal: + The TenantID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientID and ClientSecret must also be set. + type: string + cloudDNS: + description: Use the Google Cloud DNS API to manage DNS01 challenge records. + type: object + required: + - project + properties: + hostedZoneName: + description: |- + HostedZoneName is an optional field that tells cert-manager in which + Cloud DNS zone the challenge record has to be created. + If left empty cert-manager will automatically choose a zone. + type: string + project: + type: string + serviceAccountSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + cloudflare: + description: Use the Cloudflare API to manage DNS01 challenge records. + type: object + properties: + apiKeySecretRef: + description: |- + API key to use to authenticate with Cloudflare. + Note: using an API token to authenticate is now the recommended method + as it allows greater control of permissions. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + apiTokenSecretRef: + description: API token used to authenticate with Cloudflare. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + email: + description: Email of the account, only required when using API key based authentication. + type: string + cnameStrategy: + description: |- + CNAMEStrategy configures how the DNS01 provider should handle CNAME + records when found in DNS zones. + type: string + enum: + - None + - Follow + digitalocean: + description: Use the DigitalOcean DNS API to manage DNS01 challenge records. + type: object + required: + - tokenSecretRef + properties: + tokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + rfc2136: + description: |- + Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) + to manage DNS01 challenge records. + type: object + required: + - nameserver + properties: + nameserver: + description: |- + The IP address or hostname of an authoritative DNS server supporting + RFC2136 in the form host:port. If the host is an IPv6 address it must be + enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. + This field is required. + type: string + tsigAlgorithm: + description: |- + The TSIG Algorithm configured in the DNS supporting RFC2136. Used only + when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. + Supported values are (case-insensitive): ``HMACMD5`` (default), + ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``. + type: string + tsigKeyName: + description: |- + The TSIG Key name configured in the DNS. + If ``tsigSecretSecretRef`` is defined, this field is required. + type: string + tsigSecretSecretRef: + description: |- + The name of the secret containing the TSIG value. + If ``tsigKeyName`` is defined, this field is required. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + route53: + description: Use the AWS Route53 API to manage DNS01 challenge records. + type: object + properties: + accessKeyID: + description: |- + The AccessKeyID is used for authentication. + Cannot be set when SecretAccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: string + accessKeyIDSecretRef: + description: |- + The SecretAccessKey is used for authentication. If set, pull the AWS + access key ID from a key within a Kubernetes Secret. + Cannot be set when AccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + auth: + description: Auth configures how cert-manager authenticates. + type: object + required: + - kubernetes + properties: + kubernetes: + description: |- + Kubernetes authenticates with Route53 using AssumeRoleWithWebIdentity + by passing a bound ServiceAccount token. + type: object + required: + - serviceAccountRef + properties: + serviceAccountRef: + description: |- + A reference to a service account that will be used to request a bound + token (also known as "projected token"). To use this field, you must + configure an RBAC rule to let cert-manager request a token. + type: object + required: + - name + properties: + audiences: + description: |- + TokenAudiences is an optional list of audiences to include in the + token passed to AWS. The default token consisting of the issuer's namespace + and name is always included. + If unset the audience defaults to `sts.amazonaws.com`. + type: array + items: + type: string + name: + description: Name of the ServiceAccount used to request a token. + type: string + hostedZoneID: + description: If set, the provider will manage only this zone in Route53 and will not do a lookup using the route53:ListHostedZonesByName api call. + type: string + region: + description: |- + Override the AWS region. + + Route53 is a global service and does not have regional endpoints but the + region specified here (or via environment variables) is used as a hint to + help compute the correct AWS credential scope and partition when it + connects to Route53. See: + - [Amazon Route 53 endpoints and quotas](https://docs.aws.amazon.com/general/latest/gr/r53.html) + - [Global services](https://docs.aws.amazon.com/whitepapers/latest/aws-fault-isolation-boundaries/global-services.html) + + If you omit this region field, cert-manager will use the region from + AWS_REGION and AWS_DEFAULT_REGION environment variables, if they are set + in the cert-manager controller Pod. + + The `region` field is not needed if you use [IAM Roles for Service Accounts (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html). + Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: + [Amazon EKS Pod Identity Webhook](https://github.com/aws/amazon-eks-pod-identity-webhook). + In this case this `region` field value is ignored. + + The `region` field is not needed if you use [EKS Pod Identities](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html). + Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: + [Amazon EKS Pod Identity Agent](https://github.com/aws/eks-pod-identity-agent), + In this case this `region` field value is ignored. + type: string + role: + description: |- + Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey + or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata + type: string + secretAccessKeySecretRef: + description: |- + The SecretAccessKey is used for authentication. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + webhook: + description: |- + Configure an external webhook based DNS01 challenge solver to manage + DNS01 challenge records. + type: object + required: + - groupName + - solverName + properties: + config: + description: |- + Additional configuration that should be passed to the webhook apiserver + when challenges are processed. + This can contain arbitrary JSON data. + Secret values should not be specified in this stanza. + If secret values are needed (e.g. credentials for a DNS service), you + should use a SecretKeySelector to reference a Secret resource. + For details on the schema of this field, consult the webhook provider + implementation's documentation. + x-kubernetes-preserve-unknown-fields: true + groupName: + description: |- + The API group name that should be used when POSTing ChallengePayload + resources to the webhook apiserver. + This should be the same as the GroupName specified in the webhook + provider implementation. + type: string + solverName: + description: |- + The name of the solver to use, as defined in the webhook provider + implementation. + This will typically be the name of the provider, e.g. 'cloudflare'. + type: string + http01: + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the HTTP01 challenge flow. + It is not possible to obtain certificates for wildcard domain names + (e.g. `*.example.com`) using the HTTP01 challenge mechanism. + type: object + properties: + gatewayHTTPRoute: + description: |- + The Gateway API is a sig-network community API that models service networking + in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will + create HTTPRoutes with the specified labels in the same namespace as the challenge. + This solver is experimental, and fields / behaviour may change in the future. + type: object + properties: + labels: + description: |- + Custom labels that will be applied to HTTPRoutes created by cert-manager + while solving HTTP-01 challenges. + type: object + additionalProperties: + type: string + parentRefs: + description: |- + When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. + cert-manager needs to know which parentRefs should be used when creating + the HTTPRoute. Usually, the parentRef references a Gateway. See: + https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways + type: array + items: + description: |- + ParentReference identifies an API object (usually a Gateway) that can be considered + a parent of this resource (usually a route). There are two kinds of parent resources + with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + type: object + required: + - name + properties: + group: + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + type: string + default: gateway.networking.k8s.io + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + kind: + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + type: string + default: Gateway + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + name: + description: |- + Name is the name of the referent. + + Support: Core + type: string + maxLength: 253 + minLength: 1 + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + Support: Core + type: string + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port must match both specified values. + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + type: integer + format: int32 + maximum: 65535 + minimum: 1 + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + type: string + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + podTemplate: + description: |- + Optional pod template used to configure the ACME challenge solver pods + used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the pod used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: |- + PodSpec defines overrides for the HTTP01 challenge solver pod. + Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. + All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node matches the corresponding matchExpressions; the + node(s) with the highest sum are the most preferred. + type: array + items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + x-kubernetes-list-type: atomic + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the anti-affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + x-kubernetes-list-type: atomic + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + type: object + properties: + name: + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + default: "" + x-kubernetes-map-type: atomic + nodeSelector: + description: |- + NodeSelector is a selector which must be true for the pod to fit on a node. + Selector which must match a node's labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + securityContext: + description: If specified, the pod's security context + type: object + properties: + fsGroup: + description: |- + A special supplemental group that applies to all containers in a pod. + Some volume types allow the Kubelet to change the ownership of that volume + to be owned by the pod: + + 1. The owning GID will be the FSGroup + 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- + + If unset, the Kubelet will not modify the ownership and permissions of any volume. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + fsGroupChangePolicy: + description: |- + fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + before being exposed inside Pod. This field will only apply to + volume types which support fsGroup based ownership(and permissions). + It will have no effect on ephemeral volume types such as: secret, configmaps + and emptydir. + Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. + Note that this field cannot be set when spec.os.name is windows. + type: string + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + seLinuxOptions: + description: |- + The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in SecurityContext. If set in + both SecurityContext and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + type: object + properties: + level: + description: Level is SELinux level label that applies to the container. + type: string + role: + description: Role is a SELinux role label that applies to the container. + type: string + type: + description: Type is a SELinux type label that applies to the container. + type: string + user: + description: User is a SELinux user label that applies to the container. + type: string + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + type: object + required: + - type + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + supplementalGroups: + description: |- + A list of groups applied to the first process run in each container, in addition + to the container's primary GID, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container process. If unspecified, + no additional groups are added to any container. Note that group memberships + defined in the container image for the uid of the container process are still effective, + even if they are not included in this list. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + type: integer + format: int64 + sysctls: + description: |- + Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + sysctls (by the container runtime) might fail to launch. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + description: Sysctl defines a kernel parameter to be set + type: object + required: + - name + - value + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + type: object + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + type: integer + format: int64 + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + serviceType: + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + ingress: + description: |- + The ingress based HTTP01 challenge solver will solve challenges by + creating or modifying Ingress resources in order to route requests for + '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are + provisioned by cert-manager for each Challenge to be completed. + type: object + properties: + class: + description: |- + This field configures the annotation `kubernetes.io/ingress.class` when + creating Ingress resources to solve ACME challenges that use this + challenge solver. Only one of `class`, `name` or `ingressClassName` may + be specified. + type: string + ingressClassName: + description: |- + This field configures the field `ingressClassName` on the created Ingress + resources used to solve ACME challenges that use this challenge solver. + This is the recommended way of configuring the ingress class. Only one of + `class`, `name` or `ingressClassName` may be specified. + type: string + ingressTemplate: + description: |- + Optional ingress template used to configure the ACME challenge solver + ingress used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the ingress used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + name: + description: |- + The name of the ingress resource that should have ACME challenge solving + routes inserted into it in order to solve HTTP01 challenges. + This is typically used in conjunction with ingress controllers like + ingress-gce, which maintains a 1:1 mapping between external IPs and + ingress resources. Only one of `class`, `name` or `ingressClassName` may + be specified. + type: string + podTemplate: + description: |- + Optional pod template used to configure the ACME challenge solver pods + used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the pod used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: |- + PodSpec defines overrides for the HTTP01 challenge solver pod. + Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. + All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node matches the corresponding matchExpressions; the + node(s) with the highest sum are the most preferred. + type: array + items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + x-kubernetes-list-type: atomic + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the anti-affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + x-kubernetes-list-type: atomic + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + type: object + properties: + name: + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + default: "" + x-kubernetes-map-type: atomic + nodeSelector: + description: |- + NodeSelector is a selector which must be true for the pod to fit on a node. + Selector which must match a node's labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + securityContext: + description: If specified, the pod's security context + type: object + properties: + fsGroup: + description: |- + A special supplemental group that applies to all containers in a pod. + Some volume types allow the Kubelet to change the ownership of that volume + to be owned by the pod: + + 1. The owning GID will be the FSGroup + 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- + + If unset, the Kubelet will not modify the ownership and permissions of any volume. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + fsGroupChangePolicy: + description: |- + fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + before being exposed inside Pod. This field will only apply to + volume types which support fsGroup based ownership(and permissions). + It will have no effect on ephemeral volume types such as: secret, configmaps + and emptydir. + Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. + Note that this field cannot be set when spec.os.name is windows. + type: string + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + seLinuxOptions: + description: |- + The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in SecurityContext. If set in + both SecurityContext and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + type: object + properties: + level: + description: Level is SELinux level label that applies to the container. + type: string + role: + description: Role is a SELinux role label that applies to the container. + type: string + type: + description: Type is a SELinux type label that applies to the container. + type: string + user: + description: User is a SELinux user label that applies to the container. + type: string + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + type: object + required: + - type + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + supplementalGroups: + description: |- + A list of groups applied to the first process run in each container, in addition + to the container's primary GID, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container process. If unspecified, + no additional groups are added to any container. Note that group memberships + defined in the container image for the uid of the container process are still effective, + even if they are not included in this list. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + type: integer + format: int64 + sysctls: + description: |- + Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + sysctls (by the container runtime) might fail to launch. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + description: Sysctl defines a kernel parameter to be set + type: object + required: + - name + - value + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + type: object + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + type: integer + format: int64 + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + serviceType: + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + selector: + description: |- + Selector selects a set of DNSNames on the Certificate resource that + should be solved using this challenge solver. + If not specified, the solver will be treated as the 'default' solver + with the lowest priority, i.e. if any other solver has a more specific + match, it will be used instead. + type: object + properties: + dnsNames: + description: |- + List of DNSNames that this solver will be used to solve. + If specified and a match is found, a dnsNames selector will take + precedence over a dnsZones selector. + If multiple solvers match with the same dnsNames value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. + type: array + items: + type: string + dnsZones: + description: |- + List of DNSZones that this solver will be used to solve. + The most specific DNS zone match specified here will take precedence + over other DNS zone matches, so a solver specifying sys.example.com + will be selected over one specifying example.com for the domain + www.sys.example.com. + If multiple solvers match with the same dnsZones value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. + type: array + items: + type: string + matchLabels: + description: |- + A label selector that is used to refine the set of certificate's that + this challenge solver will apply to. + type: object + additionalProperties: + type: string + ca: + description: |- + CA configures this issuer to sign certificates using a signing CA keypair + stored in a Secret resource. + This is used to build internal PKIs that are managed by cert-manager. + type: object + required: + - secretName + properties: + crlDistributionPoints: + description: |- + The CRL distribution points is an X.509 v3 certificate extension which identifies + the location of the CRL from which the revocation of this certificate can be checked. + If not set, certificates will be issued without distribution points set. + type: array + items: + type: string + issuingCertificateURLs: + description: |- + IssuingCertificateURLs is a list of URLs which this issuer should embed into certificates + it creates. See https://www.rfc-editor.org/rfc/rfc5280#section-4.2.2.1 for more details. + As an example, such a URL might be "http://ca.domain.com/ca.crt". + type: array + items: + type: string + ocspServers: + description: |- + The OCSP server list is an X.509 v3 extension that defines a list of + URLs of OCSP responders. The OCSP responders can be queried for the + revocation status of an issued certificate. If not set, the + certificate will be issued with no OCSP servers set. For example, an + OCSP server URL could be "http://ocsp.int-x3.letsencrypt.org". + type: array + items: + type: string + secretName: + description: |- + SecretName is the name of the secret used to sign Certificates issued + by this Issuer. + type: string + selfSigned: + description: |- + SelfSigned configures this issuer to 'self sign' certificates using the + private key used to create the CertificateRequest object. + type: object + properties: + crlDistributionPoints: + description: |- + The CRL distribution points is an X.509 v3 certificate extension which identifies + the location of the CRL from which the revocation of this certificate can be checked. + If not set certificate will be issued without CDP. Values are strings. + type: array + items: + type: string + vault: + description: |- + Vault configures this issuer to sign certificates using a HashiCorp Vault + PKI backend. + type: object + required: + - auth + - path + - server + properties: + auth: + description: Auth configures how cert-manager authenticates with the Vault server. + type: object + properties: + appRole: + description: |- + AppRole authenticates with Vault using the App Role auth mechanism, + with the role and secret stored in a Kubernetes Secret resource. + type: object + required: + - path + - roleId + - secretRef + properties: + path: + description: |- + Path where the App Role authentication backend is mounted in Vault, e.g: + "approle" + type: string + roleId: + description: |- + RoleID configured in the App Role authentication backend when setting + up the authentication backend in Vault. + type: string + secretRef: + description: |- + Reference to a key in a Secret that contains the App Role secret used + to authenticate with Vault. + The `key` field must be specified and denotes which entry within the Secret + resource is used as the app role secret. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientCertificate: + description: |- + ClientCertificate authenticates with Vault by presenting a client + certificate during the request's TLS handshake. + Works only when using HTTPS protocol. + type: object + properties: + mountPath: + description: |- + The Vault mountPath here is the mount path to use when authenticating with + Vault. For example, setting a value to `/v1/auth/foo`, will use the path + `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the + default value "/v1/auth/cert" will be used. + type: string + name: + description: |- + Name of the certificate role to authenticate against. + If not set, matching any certificate role, if available. + type: string + secretName: + description: |- + Reference to Kubernetes Secret of type "kubernetes.io/tls" (hence containing + tls.crt and tls.key) used to authenticate to Vault using TLS client + authentication. + type: string + kubernetes: + description: |- + Kubernetes authenticates with Vault by passing the ServiceAccount + token stored in the named Secret resource to the Vault server. + type: object + required: + - role + properties: + mountPath: + description: |- + The Vault mountPath here is the mount path to use when authenticating with + Vault. For example, setting a value to `/v1/auth/foo`, will use the path + `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the + default value "/v1/auth/kubernetes" will be used. + type: string + role: + description: |- + A required field containing the Vault Role to assume. A Role binds a + Kubernetes ServiceAccount with a set of Vault policies. + type: string + secretRef: + description: |- + The required Secret field containing a Kubernetes ServiceAccount JWT used + for authenticating with Vault. Use of 'ambient credentials' is not + supported. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + serviceAccountRef: + description: |- + A reference to a service account that will be used to request a bound + token (also known as "projected token"). Compared to using "secretRef", + using this field means that you don't rely on statically bound tokens. To + use this field, you must configure an RBAC rule to let cert-manager + request a token. + type: object + required: + - name + properties: + audiences: + description: |- + TokenAudiences is an optional list of extra audiences to include in the token passed to Vault. The default token + consisting of the issuer's namespace and name is always included. + type: array + items: + type: string + name: + description: Name of the ServiceAccount used to request a token. + type: string + tokenSecretRef: + description: TokenSecretRef authenticates with Vault by presenting a token. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + caBundle: + description: |- + Base64-encoded bundle of PEM CAs which will be used to validate the certificate + chain presented by Vault. Only used if using HTTPS to connect to Vault and + ignored for HTTP connections. + Mutually exclusive with CABundleSecretRef. + If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in + the cert-manager controller container is used to validate the TLS connection. + type: string + format: byte + caBundleSecretRef: + description: |- + Reference to a Secret containing a bundle of PEM-encoded CAs to use when + verifying the certificate chain presented by Vault when using HTTPS. + Mutually exclusive with CABundle. + If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in + the cert-manager controller container is used to validate the TLS connection. + If no key for the Secret is specified, cert-manager will default to 'ca.crt'. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientCertSecretRef: + description: |- + Reference to a Secret containing a PEM-encoded Client Certificate to use when the + Vault server requires mTLS. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientKeySecretRef: + description: |- + Reference to a Secret containing a PEM-encoded Client Private Key to use when the + Vault server requires mTLS. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1" + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + type: string + path: + description: |- + Path is the mount path of the Vault PKI backend's `sign` endpoint, e.g: + "my_pki_mount/sign/my-role-name". + type: string + server: + description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' + type: string + venafi: + description: |- + Venafi configures this issuer to sign certificates using a Venafi TPP + or Venafi Cloud policy zone. + type: object + required: + - zone + properties: + cloud: + description: |- + Cloud specifies the Venafi cloud configuration settings. + Only one of TPP or Cloud may be specified. + type: object + required: + - apiTokenSecretRef + properties: + apiTokenSecretRef: + description: APITokenSecretRef is a secret key selector for the Venafi Cloud API token. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + url: + description: |- + URL is the base URL for Venafi Cloud. + Defaults to "https://api.venafi.cloud/v1". + type: string + tpp: + description: |- + TPP specifies Trust Protection Platform configuration settings. + Only one of TPP or Cloud may be specified. + type: object + required: + - credentialsRef + - url + properties: + caBundle: + description: |- + Base64-encoded bundle of PEM CAs which will be used to validate the certificate + chain presented by the TPP server. Only used if using HTTPS; ignored for HTTP. + If undefined, the certificate bundle in the cert-manager controller container + is used to validate the chain. + type: string + format: byte + caBundleSecretRef: + description: |- + Reference to a Secret containing a base64-encoded bundle of PEM CAs + which will be used to validate the certificate chain presented by the TPP server. + Only used if using HTTPS; ignored for HTTP. Mutually exclusive with CABundle. + If neither CABundle nor CABundleSecretRef is defined, the certificate bundle in + the cert-manager controller container is used to validate the TLS connection. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + credentialsRef: + description: |- + CredentialsRef is a reference to a Secret containing the Venafi TPP API credentials. + The secret must contain the key 'access-token' for the Access Token Authentication, + or two keys, 'username' and 'password' for the API Keys Authentication. + type: object + required: + - name + properties: + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + url: + description: |- + URL is the base URL for the vedsdk endpoint of the Venafi TPP instance, + for example: "https://tpp.example.com/vedsdk". + type: string + zone: + description: |- + Zone is the Venafi Policy Zone to use for this issuer. + All requests made to the Venafi platform will be restricted by the named + zone policy. + This field is required. + type: string + status: + description: Status of the ClusterIssuer. This is set and managed automatically. + type: object + properties: + acme: + description: |- + ACME specific status options. + This field should only be set if the Issuer is configured to use an ACME + server to issue certificates. + type: object + properties: + lastPrivateKeyHash: + description: |- + LastPrivateKeyHash is a hash of the private key associated with the latest + registered ACME account, in order to track changes made to registered account + associated with the Issuer + type: string + lastRegisteredEmail: + description: |- + LastRegisteredEmail is the email associated with the latest registered + ACME account, in order to track changes made to registered account + associated with the Issuer + type: string + uri: + description: |- + URI is the unique account identifier, which can also be used to retrieve + account details from the CA + type: string + conditions: + description: |- + List of status conditions to indicate the status of a CertificateRequest. + Known condition types are `Ready`. + type: array + items: + description: IssuerCondition contains condition information for an Issuer. + type: object + required: + - status + - type + properties: + lastTransitionTime: + description: |- + LastTransitionTime is the timestamp corresponding to the last status + change of this condition. + type: string + format: date-time + message: + description: |- + Message is a human readable description of the details of the last + transition, complementing reason. + type: string + observedGeneration: + description: |- + If set, this represents the .metadata.generation that the condition was + set based upon. + For instance, if .metadata.generation is currently 12, but the + .status.condition[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the Issuer. + type: integer + format: int64 + reason: + description: |- + Reason is a brief machine readable explanation for the condition's last + transition. + type: string + status: + description: Status of the condition, one of (`True`, `False`, `Unknown`). + type: string + enum: + - "True" + - "False" + - Unknown + type: + description: Type of the condition, known values are (`Ready`). + type: string + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + served: true + storage: true + +# END crd {{- end }} + +--- +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: issuers.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + app.kubernetes.io/component: "crds" + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: cert-manager.io + names: + kind: Issuer + listKind: IssuerList + plural: issuers + singular: issuer + categories: + - cert-manager + scope: Namespaced + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: |- + An Issuer represents a certificate issuing authority which can be + referenced as part of `issuerRef` fields. + It is scoped to a single namespace and can therefore only be referenced by + resources within the same namespace. + type: object + required: + - spec + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Desired state of the Issuer resource. + type: object + properties: + acme: + description: |- + ACME configures this issuer to communicate with a RFC8555 (ACME) server + to obtain signed x509 certificates. + type: object + required: + - privateKeySecretRef + - server + properties: + caBundle: + description: |- + Base64-encoded bundle of PEM CAs which can be used to validate the certificate + chain presented by the ACME server. + Mutually exclusive with SkipTLSVerify; prefer using CABundle to prevent various + kinds of security vulnerabilities. + If CABundle and SkipTLSVerify are unset, the system certificate bundle inside + the container is used to validate the TLS connection. + type: string + format: byte + disableAccountKeyGeneration: + description: |- + Enables or disables generating a new ACME account key. + If true, the Issuer resource will *not* request a new account but will expect + the account key to be supplied via an existing secret. + If false, the cert-manager system will generate a new ACME account key + for the Issuer. + Defaults to false. + type: boolean + email: + description: |- + Email is the email address to be associated with the ACME account. + This field is optional, but it is strongly recommended to be set. + It will be used to contact you in case of issues with your account or + certificates, including expiry notification emails. + This field may be updated after the account is initially registered. + type: string + enableDurationFeature: + description: |- + Enables requesting a Not After date on certificates that matches the + duration of the certificate. This is not supported by all ACME servers + like Let's Encrypt. If set to true when the ACME server does not support + it, it will create an error on the Order. + Defaults to false. + type: boolean + externalAccountBinding: + description: |- + ExternalAccountBinding is a reference to a CA external account of the ACME + server. + If set, upon registration cert-manager will attempt to associate the given + external account credentials with the registered ACME account. + type: object + required: + - keyID + - keySecretRef + properties: + keyAlgorithm: + description: |- + Deprecated: keyAlgorithm field exists for historical compatibility + reasons and should not be used. The algorithm is now hardcoded to HS256 + in golang/x/crypto/acme. + type: string + enum: + - HS256 + - HS384 + - HS512 + keyID: + description: keyID is the ID of the CA key that the External Account is bound to. + type: string + keySecretRef: + description: |- + keySecretRef is a Secret Key Selector referencing a data item in a Kubernetes + Secret which holds the symmetric MAC key of the External Account Binding. + The `key` is the index string that is paired with the key data in the + Secret and should not be confused with the key data itself, or indeed with + the External Account Binding keyID above. + The secret key stored in the Secret **must** be un-padded, base64 URL + encoded data. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + preferredChain: + description: |- + PreferredChain is the chain to use if the ACME server outputs multiple. + PreferredChain is no guarantee that this one gets delivered by the ACME + endpoint. + For example, for Let's Encrypt's DST crosssign you would use: + "DST Root CA X3" or "ISRG Root X1" for the newer Let's Encrypt root CA. + This value picks the first certificate bundle in the combined set of + ACME default and alternative chains that has a root-most certificate with + this value as its issuer's commonname. + type: string + maxLength: 64 + privateKeySecretRef: + description: |- + PrivateKey is the name of a Kubernetes Secret resource that will be used to + store the automatically generated ACME account private key. + Optionally, a `key` may be specified to select a specific entry within + the named Secret resource. + If `key` is not specified, a default of `tls.key` will be used. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + server: + description: |- + Server is the URL used to access the ACME server's 'directory' endpoint. + For example, for Let's Encrypt's staging endpoint, you would use: + "https://acme-staging-v02.api.letsencrypt.org/directory". + Only ACME v2 endpoints (i.e. RFC 8555) are supported. + type: string + skipTLSVerify: + description: |- + INSECURE: Enables or disables validation of the ACME server TLS certificate. + If true, requests to the ACME server will not have the TLS certificate chain + validated. + Mutually exclusive with CABundle; prefer using CABundle to prevent various + kinds of security vulnerabilities. + Only enable this option in development environments. + If CABundle and SkipTLSVerify are unset, the system certificate bundle inside + the container is used to validate the TLS connection. + Defaults to false. + type: boolean + solvers: + description: |- + Solvers is a list of challenge solvers that will be used to solve + ACME challenges for the matching domains. + Solver configurations must be provided in order to obtain certificates + from an ACME server. + For more information, see: https://cert-manager.io/docs/configuration/acme/ + type: array + items: + description: |- + An ACMEChallengeSolver describes how to solve ACME challenges for the issuer it is part of. + A selector may be provided to use different solving strategies for different DNS names. + Only one of HTTP01 or DNS01 must be provided. + type: object + properties: + dns01: + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the DNS01 challenge flow. + type: object + properties: + acmeDNS: + description: |- + Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage + DNS01 challenge records. + type: object + required: + - accountSecretRef + - host + properties: + accountSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + host: + type: string + akamai: + description: Use the Akamai DNS zone management API to manage DNS01 challenge records. + type: object + required: + - accessTokenSecretRef + - clientSecretSecretRef + - clientTokenSecretRef + - serviceConsumerDomain + properties: + accessTokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientSecretSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientTokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + serviceConsumerDomain: + type: string + azureDNS: + description: Use the Microsoft Azure DNS API to manage DNS01 challenge records. + type: object + required: + - resourceGroupName + - subscriptionID + properties: + clientID: + description: |- + Auth: Azure Service Principal: + The ClientID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientSecret and TenantID must also be set. + type: string + clientSecretSecretRef: + description: |- + Auth: Azure Service Principal: + A reference to a Secret containing the password associated with the Service Principal. + If set, ClientID and TenantID must also be set. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + environment: + description: name of the Azure environment (default AzurePublicCloud) + type: string + enum: + - AzurePublicCloud + - AzureChinaCloud + - AzureGermanCloud + - AzureUSGovernmentCloud + hostedZoneName: + description: name of the DNS zone that should be used + type: string + managedIdentity: + description: |- + Auth: Azure Workload Identity or Azure Managed Service Identity: + Settings to enable Azure Workload Identity or Azure Managed Service Identity + If set, ClientID, ClientSecret and TenantID must not be set. + type: object + properties: + clientID: + description: client ID of the managed identity, can not be used at the same time as resourceID + type: string + resourceID: + description: |- + resource ID of the managed identity, can not be used at the same time as clientID + Cannot be used for Azure Managed Service Identity + type: string + resourceGroupName: + description: resource group the DNS zone is located in + type: string + subscriptionID: + description: ID of the Azure subscription + type: string + tenantID: + description: |- + Auth: Azure Service Principal: + The TenantID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientID and ClientSecret must also be set. + type: string + cloudDNS: + description: Use the Google Cloud DNS API to manage DNS01 challenge records. + type: object + required: + - project + properties: + hostedZoneName: + description: |- + HostedZoneName is an optional field that tells cert-manager in which + Cloud DNS zone the challenge record has to be created. + If left empty cert-manager will automatically choose a zone. + type: string + project: + type: string + serviceAccountSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + cloudflare: + description: Use the Cloudflare API to manage DNS01 challenge records. + type: object + properties: + apiKeySecretRef: + description: |- + API key to use to authenticate with Cloudflare. + Note: using an API token to authenticate is now the recommended method + as it allows greater control of permissions. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + apiTokenSecretRef: + description: API token used to authenticate with Cloudflare. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + email: + description: Email of the account, only required when using API key based authentication. + type: string + cnameStrategy: + description: |- + CNAMEStrategy configures how the DNS01 provider should handle CNAME + records when found in DNS zones. + type: string + enum: + - None + - Follow + digitalocean: + description: Use the DigitalOcean DNS API to manage DNS01 challenge records. + type: object + required: + - tokenSecretRef + properties: + tokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + rfc2136: + description: |- + Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) + to manage DNS01 challenge records. + type: object + required: + - nameserver + properties: + nameserver: + description: |- + The IP address or hostname of an authoritative DNS server supporting + RFC2136 in the form host:port. If the host is an IPv6 address it must be + enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. + This field is required. + type: string + tsigAlgorithm: + description: |- + The TSIG Algorithm configured in the DNS supporting RFC2136. Used only + when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. + Supported values are (case-insensitive): ``HMACMD5`` (default), + ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``. + type: string + tsigKeyName: + description: |- + The TSIG Key name configured in the DNS. + If ``tsigSecretSecretRef`` is defined, this field is required. + type: string + tsigSecretSecretRef: + description: |- + The name of the secret containing the TSIG value. + If ``tsigKeyName`` is defined, this field is required. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + route53: + description: Use the AWS Route53 API to manage DNS01 challenge records. + type: object + properties: + accessKeyID: + description: |- + The AccessKeyID is used for authentication. + Cannot be set when SecretAccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: string + accessKeyIDSecretRef: + description: |- + The SecretAccessKey is used for authentication. If set, pull the AWS + access key ID from a key within a Kubernetes Secret. + Cannot be set when AccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + auth: + description: Auth configures how cert-manager authenticates. + type: object + required: + - kubernetes + properties: + kubernetes: + description: |- + Kubernetes authenticates with Route53 using AssumeRoleWithWebIdentity + by passing a bound ServiceAccount token. + type: object + required: + - serviceAccountRef + properties: + serviceAccountRef: + description: |- + A reference to a service account that will be used to request a bound + token (also known as "projected token"). To use this field, you must + configure an RBAC rule to let cert-manager request a token. + type: object + required: + - name + properties: + audiences: + description: |- + TokenAudiences is an optional list of audiences to include in the + token passed to AWS. The default token consisting of the issuer's namespace + and name is always included. + If unset the audience defaults to `sts.amazonaws.com`. + type: array + items: + type: string + name: + description: Name of the ServiceAccount used to request a token. + type: string + hostedZoneID: + description: If set, the provider will manage only this zone in Route53 and will not do a lookup using the route53:ListHostedZonesByName api call. + type: string + region: + description: |- + Override the AWS region. + + Route53 is a global service and does not have regional endpoints but the + region specified here (or via environment variables) is used as a hint to + help compute the correct AWS credential scope and partition when it + connects to Route53. See: + - [Amazon Route 53 endpoints and quotas](https://docs.aws.amazon.com/general/latest/gr/r53.html) + - [Global services](https://docs.aws.amazon.com/whitepapers/latest/aws-fault-isolation-boundaries/global-services.html) + + If you omit this region field, cert-manager will use the region from + AWS_REGION and AWS_DEFAULT_REGION environment variables, if they are set + in the cert-manager controller Pod. + + The `region` field is not needed if you use [IAM Roles for Service Accounts (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html). + Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: + [Amazon EKS Pod Identity Webhook](https://github.com/aws/amazon-eks-pod-identity-webhook). + In this case this `region` field value is ignored. + + The `region` field is not needed if you use [EKS Pod Identities](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html). + Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: + [Amazon EKS Pod Identity Agent](https://github.com/aws/eks-pod-identity-agent), + In this case this `region` field value is ignored. + type: string + role: + description: |- + Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey + or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata + type: string + secretAccessKeySecretRef: + description: |- + The SecretAccessKey is used for authentication. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + webhook: + description: |- + Configure an external webhook based DNS01 challenge solver to manage + DNS01 challenge records. + type: object + required: + - groupName + - solverName + properties: + config: + description: |- + Additional configuration that should be passed to the webhook apiserver + when challenges are processed. + This can contain arbitrary JSON data. + Secret values should not be specified in this stanza. + If secret values are needed (e.g. credentials for a DNS service), you + should use a SecretKeySelector to reference a Secret resource. + For details on the schema of this field, consult the webhook provider + implementation's documentation. + x-kubernetes-preserve-unknown-fields: true + groupName: + description: |- + The API group name that should be used when POSTing ChallengePayload + resources to the webhook apiserver. + This should be the same as the GroupName specified in the webhook + provider implementation. + type: string + solverName: + description: |- + The name of the solver to use, as defined in the webhook provider + implementation. + This will typically be the name of the provider, e.g. 'cloudflare'. + type: string + http01: + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the HTTP01 challenge flow. + It is not possible to obtain certificates for wildcard domain names + (e.g. `*.example.com`) using the HTTP01 challenge mechanism. + type: object + properties: + gatewayHTTPRoute: + description: |- + The Gateway API is a sig-network community API that models service networking + in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will + create HTTPRoutes with the specified labels in the same namespace as the challenge. + This solver is experimental, and fields / behaviour may change in the future. + type: object + properties: + labels: + description: |- + Custom labels that will be applied to HTTPRoutes created by cert-manager + while solving HTTP-01 challenges. + type: object + additionalProperties: + type: string + parentRefs: + description: |- + When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. + cert-manager needs to know which parentRefs should be used when creating + the HTTPRoute. Usually, the parentRef references a Gateway. See: + https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways + type: array + items: + description: |- + ParentReference identifies an API object (usually a Gateway) that can be considered + a parent of this resource (usually a route). There are two kinds of parent resources + with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + type: object + required: + - name + properties: + group: + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + type: string + default: gateway.networking.k8s.io + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + kind: + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + type: string + default: Gateway + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + name: + description: |- + Name is the name of the referent. + + Support: Core + type: string + maxLength: 253 + minLength: 1 + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + Support: Core + type: string + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port must match both specified values. + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + type: integer + format: int32 + maximum: 65535 + minimum: 1 + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + type: string + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + podTemplate: + description: |- + Optional pod template used to configure the ACME challenge solver pods + used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the pod used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: |- + PodSpec defines overrides for the HTTP01 challenge solver pod. + Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. + All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node matches the corresponding matchExpressions; the + node(s) with the highest sum are the most preferred. + type: array + items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + x-kubernetes-list-type: atomic + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the anti-affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + x-kubernetes-list-type: atomic + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + type: object + properties: + name: + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + default: "" + x-kubernetes-map-type: atomic + nodeSelector: + description: |- + NodeSelector is a selector which must be true for the pod to fit on a node. + Selector which must match a node's labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + securityContext: + description: If specified, the pod's security context + type: object + properties: + fsGroup: + description: |- + A special supplemental group that applies to all containers in a pod. + Some volume types allow the Kubelet to change the ownership of that volume + to be owned by the pod: + + 1. The owning GID will be the FSGroup + 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- + + If unset, the Kubelet will not modify the ownership and permissions of any volume. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + fsGroupChangePolicy: + description: |- + fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + before being exposed inside Pod. This field will only apply to + volume types which support fsGroup based ownership(and permissions). + It will have no effect on ephemeral volume types such as: secret, configmaps + and emptydir. + Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. + Note that this field cannot be set when spec.os.name is windows. + type: string + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + seLinuxOptions: + description: |- + The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in SecurityContext. If set in + both SecurityContext and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + type: object + properties: + level: + description: Level is SELinux level label that applies to the container. + type: string + role: + description: Role is a SELinux role label that applies to the container. + type: string + type: + description: Type is a SELinux type label that applies to the container. + type: string + user: + description: User is a SELinux user label that applies to the container. + type: string + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + type: object + required: + - type + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + supplementalGroups: + description: |- + A list of groups applied to the first process run in each container, in addition + to the container's primary GID, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container process. If unspecified, + no additional groups are added to any container. Note that group memberships + defined in the container image for the uid of the container process are still effective, + even if they are not included in this list. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + type: integer + format: int64 + sysctls: + description: |- + Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + sysctls (by the container runtime) might fail to launch. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + description: Sysctl defines a kernel parameter to be set + type: object + required: + - name + - value + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + type: object + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + type: integer + format: int64 + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + serviceType: + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + ingress: + description: |- + The ingress based HTTP01 challenge solver will solve challenges by + creating or modifying Ingress resources in order to route requests for + '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are + provisioned by cert-manager for each Challenge to be completed. + type: object + properties: + class: + description: |- + This field configures the annotation `kubernetes.io/ingress.class` when + creating Ingress resources to solve ACME challenges that use this + challenge solver. Only one of `class`, `name` or `ingressClassName` may + be specified. + type: string + ingressClassName: + description: |- + This field configures the field `ingressClassName` on the created Ingress + resources used to solve ACME challenges that use this challenge solver. + This is the recommended way of configuring the ingress class. Only one of + `class`, `name` or `ingressClassName` may be specified. + type: string + ingressTemplate: + description: |- + Optional ingress template used to configure the ACME challenge solver + ingress used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the ingress used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + name: + description: |- + The name of the ingress resource that should have ACME challenge solving + routes inserted into it in order to solve HTTP01 challenges. + This is typically used in conjunction with ingress controllers like + ingress-gce, which maintains a 1:1 mapping between external IPs and + ingress resources. Only one of `class`, `name` or `ingressClassName` may + be specified. + type: string + podTemplate: + description: |- + Optional pod template used to configure the ACME challenge solver pods + used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the pod used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: |- + PodSpec defines overrides for the HTTP01 challenge solver pod. + Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. + All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node matches the corresponding matchExpressions; the + node(s) with the highest sum are the most preferred. + type: array + items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + x-kubernetes-list-type: atomic + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the anti-affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + x-kubernetes-list-type: atomic + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + type: object + properties: + name: + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + default: "" + x-kubernetes-map-type: atomic + nodeSelector: + description: |- + NodeSelector is a selector which must be true for the pod to fit on a node. + Selector which must match a node's labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + securityContext: + description: If specified, the pod's security context + type: object + properties: + fsGroup: + description: |- + A special supplemental group that applies to all containers in a pod. + Some volume types allow the Kubelet to change the ownership of that volume + to be owned by the pod: + + 1. The owning GID will be the FSGroup + 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- + + If unset, the Kubelet will not modify the ownership and permissions of any volume. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + fsGroupChangePolicy: + description: |- + fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + before being exposed inside Pod. This field will only apply to + volume types which support fsGroup based ownership(and permissions). + It will have no effect on ephemeral volume types such as: secret, configmaps + and emptydir. + Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. + Note that this field cannot be set when spec.os.name is windows. + type: string + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + seLinuxOptions: + description: |- + The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in SecurityContext. If set in + both SecurityContext and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + type: object + properties: + level: + description: Level is SELinux level label that applies to the container. + type: string + role: + description: Role is a SELinux role label that applies to the container. + type: string + type: + description: Type is a SELinux type label that applies to the container. + type: string + user: + description: User is a SELinux user label that applies to the container. + type: string + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + type: object + required: + - type + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + supplementalGroups: + description: |- + A list of groups applied to the first process run in each container, in addition + to the container's primary GID, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container process. If unspecified, + no additional groups are added to any container. Note that group memberships + defined in the container image for the uid of the container process are still effective, + even if they are not included in this list. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + type: integer + format: int64 + sysctls: + description: |- + Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + sysctls (by the container runtime) might fail to launch. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + description: Sysctl defines a kernel parameter to be set + type: object + required: + - name + - value + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + type: object + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + type: integer + format: int64 + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + serviceType: + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + selector: + description: |- + Selector selects a set of DNSNames on the Certificate resource that + should be solved using this challenge solver. + If not specified, the solver will be treated as the 'default' solver + with the lowest priority, i.e. if any other solver has a more specific + match, it will be used instead. + type: object + properties: + dnsNames: + description: |- + List of DNSNames that this solver will be used to solve. + If specified and a match is found, a dnsNames selector will take + precedence over a dnsZones selector. + If multiple solvers match with the same dnsNames value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. + type: array + items: + type: string + dnsZones: + description: |- + List of DNSZones that this solver will be used to solve. + The most specific DNS zone match specified here will take precedence + over other DNS zone matches, so a solver specifying sys.example.com + will be selected over one specifying example.com for the domain + www.sys.example.com. + If multiple solvers match with the same dnsZones value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. + type: array + items: + type: string + matchLabels: + description: |- + A label selector that is used to refine the set of certificate's that + this challenge solver will apply to. + type: object + additionalProperties: + type: string + ca: + description: |- + CA configures this issuer to sign certificates using a signing CA keypair + stored in a Secret resource. + This is used to build internal PKIs that are managed by cert-manager. + type: object + required: + - secretName + properties: + crlDistributionPoints: + description: |- + The CRL distribution points is an X.509 v3 certificate extension which identifies + the location of the CRL from which the revocation of this certificate can be checked. + If not set, certificates will be issued without distribution points set. + type: array + items: + type: string + issuingCertificateURLs: + description: |- + IssuingCertificateURLs is a list of URLs which this issuer should embed into certificates + it creates. See https://www.rfc-editor.org/rfc/rfc5280#section-4.2.2.1 for more details. + As an example, such a URL might be "http://ca.domain.com/ca.crt". + type: array + items: + type: string + ocspServers: + description: |- + The OCSP server list is an X.509 v3 extension that defines a list of + URLs of OCSP responders. The OCSP responders can be queried for the + revocation status of an issued certificate. If not set, the + certificate will be issued with no OCSP servers set. For example, an + OCSP server URL could be "http://ocsp.int-x3.letsencrypt.org". + type: array + items: + type: string + secretName: + description: |- + SecretName is the name of the secret used to sign Certificates issued + by this Issuer. + type: string + selfSigned: + description: |- + SelfSigned configures this issuer to 'self sign' certificates using the + private key used to create the CertificateRequest object. + type: object + properties: + crlDistributionPoints: + description: |- + The CRL distribution points is an X.509 v3 certificate extension which identifies + the location of the CRL from which the revocation of this certificate can be checked. + If not set certificate will be issued without CDP. Values are strings. + type: array + items: + type: string + vault: + description: |- + Vault configures this issuer to sign certificates using a HashiCorp Vault + PKI backend. + type: object + required: + - auth + - path + - server + properties: + auth: + description: Auth configures how cert-manager authenticates with the Vault server. + type: object + properties: + appRole: + description: |- + AppRole authenticates with Vault using the App Role auth mechanism, + with the role and secret stored in a Kubernetes Secret resource. + type: object + required: + - path + - roleId + - secretRef + properties: + path: + description: |- + Path where the App Role authentication backend is mounted in Vault, e.g: + "approle" + type: string + roleId: + description: |- + RoleID configured in the App Role authentication backend when setting + up the authentication backend in Vault. + type: string + secretRef: + description: |- + Reference to a key in a Secret that contains the App Role secret used + to authenticate with Vault. + The `key` field must be specified and denotes which entry within the Secret + resource is used as the app role secret. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientCertificate: + description: |- + ClientCertificate authenticates with Vault by presenting a client + certificate during the request's TLS handshake. + Works only when using HTTPS protocol. + type: object + properties: + mountPath: + description: |- + The Vault mountPath here is the mount path to use when authenticating with + Vault. For example, setting a value to `/v1/auth/foo`, will use the path + `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the + default value "/v1/auth/cert" will be used. + type: string + name: + description: |- + Name of the certificate role to authenticate against. + If not set, matching any certificate role, if available. + type: string + secretName: + description: |- + Reference to Kubernetes Secret of type "kubernetes.io/tls" (hence containing + tls.crt and tls.key) used to authenticate to Vault using TLS client + authentication. + type: string + kubernetes: + description: |- + Kubernetes authenticates with Vault by passing the ServiceAccount + token stored in the named Secret resource to the Vault server. + type: object + required: + - role + properties: + mountPath: + description: |- + The Vault mountPath here is the mount path to use when authenticating with + Vault. For example, setting a value to `/v1/auth/foo`, will use the path + `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the + default value "/v1/auth/kubernetes" will be used. + type: string + role: + description: |- + A required field containing the Vault Role to assume. A Role binds a + Kubernetes ServiceAccount with a set of Vault policies. + type: string + secretRef: + description: |- + The required Secret field containing a Kubernetes ServiceAccount JWT used + for authenticating with Vault. Use of 'ambient credentials' is not + supported. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + serviceAccountRef: + description: |- + A reference to a service account that will be used to request a bound + token (also known as "projected token"). Compared to using "secretRef", + using this field means that you don't rely on statically bound tokens. To + use this field, you must configure an RBAC rule to let cert-manager + request a token. + type: object + required: + - name + properties: + audiences: + description: |- + TokenAudiences is an optional list of extra audiences to include in the token passed to Vault. The default token + consisting of the issuer's namespace and name is always included. + type: array + items: + type: string + name: + description: Name of the ServiceAccount used to request a token. + type: string + tokenSecretRef: + description: TokenSecretRef authenticates with Vault by presenting a token. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + caBundle: + description: |- + Base64-encoded bundle of PEM CAs which will be used to validate the certificate + chain presented by Vault. Only used if using HTTPS to connect to Vault and + ignored for HTTP connections. + Mutually exclusive with CABundleSecretRef. + If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in + the cert-manager controller container is used to validate the TLS connection. + type: string + format: byte + caBundleSecretRef: + description: |- + Reference to a Secret containing a bundle of PEM-encoded CAs to use when + verifying the certificate chain presented by Vault when using HTTPS. + Mutually exclusive with CABundle. + If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in + the cert-manager controller container is used to validate the TLS connection. + If no key for the Secret is specified, cert-manager will default to 'ca.crt'. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientCertSecretRef: + description: |- + Reference to a Secret containing a PEM-encoded Client Certificate to use when the + Vault server requires mTLS. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientKeySecretRef: + description: |- + Reference to a Secret containing a PEM-encoded Client Private Key to use when the + Vault server requires mTLS. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1" + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + type: string + path: + description: |- + Path is the mount path of the Vault PKI backend's `sign` endpoint, e.g: + "my_pki_mount/sign/my-role-name". + type: string + server: + description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' + type: string + venafi: + description: |- + Venafi configures this issuer to sign certificates using a Venafi TPP + or Venafi Cloud policy zone. + type: object + required: + - zone + properties: + cloud: + description: |- + Cloud specifies the Venafi cloud configuration settings. + Only one of TPP or Cloud may be specified. + type: object + required: + - apiTokenSecretRef + properties: + apiTokenSecretRef: + description: APITokenSecretRef is a secret key selector for the Venafi Cloud API token. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + url: + description: |- + URL is the base URL for Venafi Cloud. + Defaults to "https://api.venafi.cloud/v1". + type: string + tpp: + description: |- + TPP specifies Trust Protection Platform configuration settings. + Only one of TPP or Cloud may be specified. + type: object + required: + - credentialsRef + - url + properties: + caBundle: + description: |- + Base64-encoded bundle of PEM CAs which will be used to validate the certificate + chain presented by the TPP server. Only used if using HTTPS; ignored for HTTP. + If undefined, the certificate bundle in the cert-manager controller container + is used to validate the chain. + type: string + format: byte + caBundleSecretRef: + description: |- + Reference to a Secret containing a base64-encoded bundle of PEM CAs + which will be used to validate the certificate chain presented by the TPP server. + Only used if using HTTPS; ignored for HTTP. Mutually exclusive with CABundle. + If neither CABundle nor CABundleSecretRef is defined, the certificate bundle in + the cert-manager controller container is used to validate the TLS connection. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + credentialsRef: + description: |- + CredentialsRef is a reference to a Secret containing the Venafi TPP API credentials. + The secret must contain the key 'access-token' for the Access Token Authentication, + or two keys, 'username' and 'password' for the API Keys Authentication. + type: object + required: + - name + properties: + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + url: + description: |- + URL is the base URL for the vedsdk endpoint of the Venafi TPP instance, + for example: "https://tpp.example.com/vedsdk". + type: string + zone: + description: |- + Zone is the Venafi Policy Zone to use for this issuer. + All requests made to the Venafi platform will be restricted by the named + zone policy. + This field is required. + type: string + status: + description: Status of the Issuer. This is set and managed automatically. + type: object + properties: + acme: + description: |- + ACME specific status options. + This field should only be set if the Issuer is configured to use an ACME + server to issue certificates. + type: object + properties: + lastPrivateKeyHash: + description: |- + LastPrivateKeyHash is a hash of the private key associated with the latest + registered ACME account, in order to track changes made to registered account + associated with the Issuer + type: string + lastRegisteredEmail: + description: |- + LastRegisteredEmail is the email associated with the latest registered + ACME account, in order to track changes made to registered account + associated with the Issuer + type: string + uri: + description: |- + URI is the unique account identifier, which can also be used to retrieve + account details from the CA + type: string + conditions: + description: |- + List of status conditions to indicate the status of a CertificateRequest. + Known condition types are `Ready`. + type: array + items: + description: IssuerCondition contains condition information for an Issuer. + type: object + required: + - status + - type + properties: + lastTransitionTime: + description: |- + LastTransitionTime is the timestamp corresponding to the last status + change of this condition. + type: string + format: date-time + message: + description: |- + Message is a human readable description of the details of the last + transition, complementing reason. + type: string + observedGeneration: + description: |- + If set, this represents the .metadata.generation that the condition was + set based upon. + For instance, if .metadata.generation is currently 12, but the + .status.condition[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the Issuer. + type: integer + format: int64 + reason: + description: |- + Reason is a brief machine readable explanation for the condition's last + transition. + type: string + status: + description: Status of the condition, one of (`True`, `False`, `Unknown`). + type: string + enum: + - "True" + - "False" + - Unknown + type: + description: Type of the condition, known values are (`Ready`). + type: string + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + served: true + storage: true + +# END crd {{- end }} + +--- +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: orders.acme.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + app.kubernetes.io/component: "crds" + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: acme.cert-manager.io + names: + kind: Order + listKind: OrderList + plural: orders + singular: order + categories: + - cert-manager + - cert-manager-acme + scope: Namespaced + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.state + name: State + type: string + - jsonPath: .spec.issuerRef.name + name: Issuer + priority: 1 + type: string + - jsonPath: .status.reason + name: Reason + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: Order is a type to represent an Order with an ACME server + type: object + required: + - metadata + - spec + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + type: object + required: + - issuerRef + - request + properties: + commonName: + description: |- + CommonName is the common name as specified on the DER encoded CSR. + If specified, this value must also be present in `dnsNames` or `ipAddresses`. + This field must match the corresponding field on the DER encoded CSR. + type: string + dnsNames: + description: |- + DNSNames is a list of DNS names that should be included as part of the Order + validation process. + This field must match the corresponding field on the DER encoded CSR. + type: array + items: + type: string + duration: + description: |- + Duration is the duration for the not after date for the requested certificate. + this is set on order creation as pe the ACME spec. + type: string + ipAddresses: + description: |- + IPAddresses is a list of IP addresses that should be included as part of the Order + validation process. + This field must match the corresponding field on the DER encoded CSR. + type: array + items: + type: string + issuerRef: + description: |- + IssuerRef references a properly configured ACME-type Issuer which should + be used to create this Order. + If the Issuer does not exist, processing will be retried. + If the Issuer is not an 'ACME' Issuer, an error will be returned and the + Order will be marked as failed. + type: object + required: + - name + properties: + group: + description: Group of the resource being referred to. + type: string + kind: + description: Kind of the resource being referred to. + type: string + name: + description: Name of the resource being referred to. + type: string + request: + description: |- + Certificate signing request bytes in DER encoding. + This will be used when finalizing the order. + This field must be set on the order. + type: string + format: byte + status: + type: object + properties: + authorizations: + description: |- + Authorizations contains data returned from the ACME server on what + authorizations must be completed in order to validate the DNS names + specified on the Order. + type: array + items: + description: |- + ACMEAuthorization contains data returned from the ACME server on an + authorization that must be completed in order validate a DNS name on an ACME + Order resource. + type: object + required: + - url + properties: + challenges: + description: |- + Challenges specifies the challenge types offered by the ACME server. + One of these challenge types will be selected when validating the DNS + name and an appropriate Challenge resource will be created to perform + the ACME challenge process. + type: array + items: + description: |- + Challenge specifies a challenge offered by the ACME server for an Order. + An appropriate Challenge resource can be created to perform the ACME + challenge process. + type: object + required: + - token + - type + - url + properties: + token: + description: |- + Token is the token that must be presented for this challenge. + This is used to compute the 'key' that must also be presented. + type: string + type: + description: |- + Type is the type of challenge being offered, e.g. 'http-01', 'dns-01', + 'tls-sni-01', etc. + This is the raw value retrieved from the ACME server. + Only 'http-01' and 'dns-01' are supported by cert-manager, other values + will be ignored. + type: string + url: + description: |- + URL is the URL of this challenge. It can be used to retrieve additional + metadata about the Challenge from the ACME server. + type: string + identifier: + description: Identifier is the DNS name to be validated as part of this authorization + type: string + initialState: + description: |- + InitialState is the initial state of the ACME authorization when first + fetched from the ACME server. + If an Authorization is already 'valid', the Order controller will not + create a Challenge resource for the authorization. This will occur when + working with an ACME server that enables 'authz reuse' (such as Let's + Encrypt's production endpoint). + If not set and 'identifier' is set, the state is assumed to be pending + and a Challenge will be created. + type: string + enum: + - valid + - ready + - pending + - processing + - invalid + - expired + - errored + url: + description: URL is the URL of the Authorization that must be completed + type: string + wildcard: + description: |- + Wildcard will be true if this authorization is for a wildcard DNS name. + If this is true, the identifier will be the *non-wildcard* version of + the DNS name. + For example, if '*.example.com' is the DNS name being validated, this + field will be 'true' and the 'identifier' field will be 'example.com'. + type: boolean + certificate: + description: |- + Certificate is a copy of the PEM encoded certificate for this Order. + This field will be populated after the order has been successfully + finalized with the ACME server, and the order has transitioned to the + 'valid' state. + type: string + format: byte + failureTime: + description: |- + FailureTime stores the time that this order failed. + This is used to influence garbage collection and back-off. + type: string + format: date-time + finalizeURL: + description: |- + FinalizeURL of the Order. + This is used to obtain certificates for this order once it has been completed. + type: string + reason: + description: |- + Reason optionally provides more information about a why the order is in + the current state. + type: string + state: + description: |- + State contains the current state of this Order resource. + States 'success' and 'expired' are 'final' + type: string + enum: + - valid + - ready + - pending + - processing + - invalid + - expired + - errored + url: + description: |- + URL of the Order. + This will initially be empty when the resource is first created. + The Order controller will populate this field when the Order is first processed. + This field will be immutable after it is initially set. + type: string + served: true + storage: true + +# END crd {{- end }} diff --git a/backing-services/cert-manager/templates/deployment.yaml b/backing-services/cert-manager/templates/deployment.yaml new file mode 100644 index 0000000..e6f3f68 --- /dev/null +++ b/backing-services/cert-manager/templates/deployment.yaml @@ -0,0 +1,231 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "cert-manager.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ template "cert-manager.name" . }} + app.kubernetes.io/name: {{ template "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} + {{- with .Values.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.replicaCount }} + {{- /* The if statement below is equivalent to {{- if $value }} but will also return true for 0. */ -}} + {{- if not (has (quote .Values.global.revisionHistoryLimit) (list "" (quote ""))) }} + revisionHistoryLimit: {{ .Values.global.revisionHistoryLimit }} + {{- end }} + selector: + matchLabels: + app.kubernetes.io/name: {{ template "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- with .Values.strategy }} + strategy: + {{- toYaml . | nindent 4 }} + {{- end }} + template: + metadata: + labels: + app: {{ template "cert-manager.name" . }} + app.kubernetes.io/name: {{ template "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if and .Values.prometheus.enabled (not (or .Values.prometheus.servicemonitor.enabled .Values.prometheus.podmonitor.enabled)) }} + {{- if not .Values.podAnnotations }} + annotations: + {{- end }} + prometheus.io/path: "/metrics" + prometheus.io/scrape: 'true' + prometheus.io/port: '9402' + {{- end }} + spec: + serviceAccountName: {{ template "cert-manager.serviceAccountName" . }} + {{- if hasKey .Values "automountServiceAccountToken" }} + automountServiceAccountToken: {{ .Values.automountServiceAccountToken }} + {{- end }} + enableServiceLinks: {{ .Values.enableServiceLinks }} + {{- with .Values.global.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if or .Values.volumes .Values.config}} + volumes: + {{- if .Values.config }} + - name: config + configMap: + name: {{ include "cert-manager.fullname" . }} + {{- end }} + {{ with .Values.volumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + containers: + - name: {{ .Chart.Name }}-controller + image: "{{ template "image" (tuple .Values.image $.Chart.AppVersion) }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + {{- /* The if statement below is equivalent to {{- if $value }} but will also return true for 0. */ -}} + {{- if not (has (quote .Values.global.logLevel) (list "" (quote ""))) }} + - --v={{ .Values.global.logLevel }} + {{- end }} + {{- if .Values.config }} + - --config=/var/cert-manager/config/config.yaml + {{- end }} + {{- $config := default .Values.config "" }} + {{- if .Values.clusterResourceNamespace }} + - --cluster-resource-namespace={{ .Values.clusterResourceNamespace }} + {{- else }} + - --cluster-resource-namespace=$(POD_NAMESPACE) + {{- end }} + {{- with .Values.global.leaderElection }} + - --leader-election-namespace={{ .namespace }} + {{- if .leaseDuration }} + - --leader-election-lease-duration={{ .leaseDuration }} + {{- end }} + {{- if .renewDeadline }} + - --leader-election-renew-deadline={{ .renewDeadline }} + {{- end }} + {{- if .retryPeriod }} + - --leader-election-retry-period={{ .retryPeriod }} + {{- end }} + {{- end }} + {{- with .Values.acmesolver.image }} + - --acme-http01-solver-image={{- if .registry -}}{{ .registry }}/{{- end -}}{{ .repository }}{{- if (.digest) -}} @{{ .digest }}{{- else -}}:{{ default $.Chart.AppVersion .tag }} {{- end -}} + {{- end }} + {{- with .Values.extraArgs }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.ingressShim }} + {{- if .defaultIssuerName }} + - --default-issuer-name={{ .defaultIssuerName }} + {{- end }} + {{- if .defaultIssuerKind }} + - --default-issuer-kind={{ .defaultIssuerKind }} + {{- end }} + {{- if .defaultIssuerGroup }} + - --default-issuer-group={{ .defaultIssuerGroup }} + {{- end }} + {{- end }} + {{- if .Values.featureGates }} + - --feature-gates={{ .Values.featureGates }} + {{- end }} + {{- if .Values.maxConcurrentChallenges }} + - --max-concurrent-challenges={{ .Values.maxConcurrentChallenges }} + {{- end }} + {{- if .Values.enableCertificateOwnerRef }} + - --enable-certificate-owner-ref=true + {{- end }} + {{- if .Values.dns01RecursiveNameserversOnly }} + - --dns01-recursive-nameservers-only=true + {{- end }} + {{- with .Values.dns01RecursiveNameservers }} + - --dns01-recursive-nameservers={{ . }} + {{- end }} + {{- if .Values.disableAutoApproval }} + - --controllers=-certificaterequests-approver + {{- end }} + ports: + - containerPort: 9402 + name: http-metrics + protocol: TCP + - containerPort: 9403 + name: http-healthz + protocol: TCP + {{- with .Values.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if or .Values.config .Values.volumeMounts }} + volumeMounts: + {{- if .Values.config }} + - name: config + mountPath: /var/cert-manager/config + {{- end }} + {{- with .Values.volumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- with .Values.extraEnv }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.http_proxy }} + - name: HTTP_PROXY + value: {{ . }} + {{- end }} + {{- with .Values.https_proxy }} + - name: HTTPS_PROXY + value: {{ . }} + {{- end }} + {{- with .Values.no_proxy }} + - name: NO_PROXY + value: {{ . }} + {{- end }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + + {{- with .Values.livenessProbe }} + {{- if .enabled }} + # LivenessProbe settings are based on those used for the Kubernetes + # controller-manager. See: + # https://github.com/kubernetes/kubernetes/blob/806b30170c61a38fedd54cc9ede4cd6275a1ad3b/cmd/kubeadm/app/util/staticpod/utils.go#L241-L245 + livenessProbe: + httpGet: + port: http-healthz + path: /livez + scheme: HTTP + initialDelaySeconds: {{ .initialDelaySeconds }} + periodSeconds: {{ .periodSeconds }} + timeoutSeconds: {{ .timeoutSeconds }} + successThreshold: {{ .successThreshold }} + failureThreshold: {{ .failureThreshold }} + {{- end }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.podDnsPolicy }} + dnsPolicy: {{ . }} + {{- end }} + {{- with .Values.podDnsConfig }} + dnsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.hostAliases }} + hostAliases: {{ toYaml . | nindent 8 }} + {{- end }} \ No newline at end of file diff --git a/backing-services/cert-manager/templates/extras-objects.yaml b/backing-services/cert-manager/templates/extras-objects.yaml new file mode 100644 index 0000000..9ec3a7e --- /dev/null +++ b/backing-services/cert-manager/templates/extras-objects.yaml @@ -0,0 +1,4 @@ +{{ range .Values.extraObjects }} +--- +{{ tpl . $ }} +{{ end }} diff --git a/backing-services/cert-manager/templates/networkpolicy-egress.yaml b/backing-services/cert-manager/templates/networkpolicy-egress.yaml new file mode 100644 index 0000000..37f90bd --- /dev/null +++ b/backing-services/cert-manager/templates/networkpolicy-egress.yaml @@ -0,0 +1,19 @@ +{{- if .Values.webhook.networkPolicy.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ template "webhook.fullname" . }}-allow-egress + namespace: {{ include "cert-manager.namespace" . }} +spec: + egress: + {{- with .Values.webhook.networkPolicy.egress }} + {{- toYaml . | nindent 2 }} + {{- end }} + podSelector: + matchLabels: + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + policyTypes: + - Egress +{{- end }} diff --git a/backing-services/cert-manager/templates/networkpolicy-webhooks.yaml b/backing-services/cert-manager/templates/networkpolicy-webhooks.yaml new file mode 100644 index 0000000..3a0ed7a --- /dev/null +++ b/backing-services/cert-manager/templates/networkpolicy-webhooks.yaml @@ -0,0 +1,21 @@ +{{- if .Values.webhook.networkPolicy.enabled }} + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ template "webhook.fullname" . }}-allow-ingress + namespace: {{ include "cert-manager.namespace" . }} +spec: + ingress: + {{- with .Values.webhook.networkPolicy.ingress }} + {{- toYaml . | nindent 2 }} + {{- end }} + podSelector: + matchLabels: + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + policyTypes: + - Ingress + +{{- end }} diff --git a/backing-services/cert-manager/templates/poddisruptionbudget.yaml b/backing-services/cert-manager/templates/poddisruptionbudget.yaml new file mode 100644 index 0000000..ae71eed --- /dev/null +++ b/backing-services/cert-manager/templates/poddisruptionbudget.yaml @@ -0,0 +1,29 @@ +{{- if .Values.podDisruptionBudget.enabled }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "cert-manager.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + + {{- if not (or (hasKey .Values.podDisruptionBudget "minAvailable") (hasKey .Values.podDisruptionBudget "maxUnavailable")) }} + minAvailable: 1 # Default value because minAvailable and maxUnavailable are not set + {{- end }} + {{- if hasKey .Values.podDisruptionBudget "minAvailable" }} + minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if hasKey .Values.podDisruptionBudget "maxUnavailable" }} + maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} + {{- end }} +{{- end }} diff --git a/backing-services/cert-manager/templates/podmonitor.yaml b/backing-services/cert-manager/templates/podmonitor.yaml new file mode 100644 index 0000000..83f7e1e --- /dev/null +++ b/backing-services/cert-manager/templates/podmonitor.yaml @@ -0,0 +1,63 @@ +{{- if and .Values.prometheus.enabled (and .Values.prometheus.podmonitor.enabled .Values.prometheus.servicemonitor.enabled) }} +{{- fail "Either .Values.prometheus.podmonitor.enabled or .Values.prometheus.servicemonitor.enabled can be enabled at a time, but not both." }} +{{- else if and .Values.prometheus.enabled .Values.prometheus.podmonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + name: {{ template "cert-manager.fullname" . }} +{{- if .Values.prometheus.podmonitor.namespace }} + namespace: {{ .Values.prometheus.podmonitor.namespace }} +{{- else }} + namespace: {{ include "cert-manager.namespace" . }} +{{- end }} + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} + prometheus: {{ .Values.prometheus.podmonitor.prometheusInstance }} + {{- with .Values.prometheus.podmonitor.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- if .Values.prometheus.podmonitor.annotations }} + annotations: + {{- with .Values.prometheus.podmonitor.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} +spec: + jobLabel: {{ template "cert-manager.fullname" . }} + selector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - {{ include "cainjector.name" . }} + - {{ template "cert-manager.name" . }} + - {{ include "webhook.name" . }} + - key: app.kubernetes.io/instance + operator: In + values: + - {{ .Release.Name }} + - key: app.kubernetes.io/component + operator: In + values: + - cainjector + - controller + - webhook +{{- if .Values.prometheus.podmonitor.namespace }} + namespaceSelector: + matchNames: + - {{ include "cert-manager.namespace" . }} +{{- end }} + podMetricsEndpoints: + - port: http-metrics + path: {{ .Values.prometheus.podmonitor.path }} + interval: {{ .Values.prometheus.podmonitor.interval }} + scrapeTimeout: {{ .Values.prometheus.podmonitor.scrapeTimeout }} + honorLabels: {{ .Values.prometheus.podmonitor.honorLabels }} + {{- with .Values.prometheus.podmonitor.endpointAdditionalProperties }} + {{- toYaml . | nindent 6 }} + {{- end }} +{{- end }} diff --git a/backing-services/cert-manager/templates/psp-clusterrole.yaml b/backing-services/cert-manager/templates/psp-clusterrole.yaml new file mode 100644 index 0000000..1d40a02 --- /dev/null +++ b/backing-services/cert-manager/templates/psp-clusterrole.yaml @@ -0,0 +1,18 @@ +{{- if .Values.global.podSecurityPolicy.enabled }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "cert-manager.fullname" . }}-psp + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +rules: +- apiGroups: ['policy'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "cert-manager.fullname" . }} +{{- end }} diff --git a/backing-services/cert-manager/templates/psp-clusterrolebinding.yaml b/backing-services/cert-manager/templates/psp-clusterrolebinding.yaml new file mode 100644 index 0000000..4f09b6b --- /dev/null +++ b/backing-services/cert-manager/templates/psp-clusterrolebinding.yaml @@ -0,0 +1,20 @@ +{{- if .Values.global.podSecurityPolicy.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cert-manager.fullname" . }}-psp + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cert-manager.fullname" . }}-psp +subjects: + - kind: ServiceAccount + name: {{ template "cert-manager.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} +{{- end }} diff --git a/backing-services/cert-manager/templates/psp.yaml b/backing-services/cert-manager/templates/psp.yaml new file mode 100644 index 0000000..9e99f5c --- /dev/null +++ b/backing-services/cert-manager/templates/psp.yaml @@ -0,0 +1,49 @@ +{{- if .Values.global.podSecurityPolicy.enabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "cert-manager.fullname" . }} + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} + annotations: + seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default' + seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + {{- if .Values.global.podSecurityPolicy.useAppArmor }} + apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' + apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + {{- end }} +spec: + privileged: false + allowPrivilegeEscalation: false + allowedCapabilities: [] # default set of capabilities are implicitly allowed + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 +{{- end }} diff --git a/backing-services/cert-manager/templates/rbac.yaml b/backing-services/cert-manager/templates/rbac.yaml new file mode 100644 index 0000000..baae425 --- /dev/null +++ b/backing-services/cert-manager/templates/rbac.yaml @@ -0,0 +1,617 @@ +{{- if .Values.global.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "cert-manager.fullname" . }}:leaderelection + namespace: {{ .Values.global.leaderElection.namespace }} + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +rules: + - apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + resourceNames: ["cert-manager-controller"] + verbs: ["get", "update", "patch"] + - apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["create"] + +--- + +# grant cert-manager permission to manage the leaderelection configmap in the +# leader election namespace +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "cert-manager.fullname" . }}:leaderelection + namespace: {{ .Values.global.leaderElection.namespace }} + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "cert-manager.fullname" . }}:leaderelection +subjects: + - kind: ServiceAccount + name: {{ template "cert-manager.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + +--- + +{{- if .Values.serviceAccount.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "cert-manager.serviceAccountName" . }}-tokenrequest + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: ["serviceaccounts/token"] + resourceNames: ["{{ template "cert-manager.serviceAccountName" . }}"] + verbs: ["create"] + +--- + +# grant cert-manager permission to create tokens for the serviceaccount +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "cert-manager.fullname" . }}-{{ template "cert-manager.serviceAccountName" . }}-tokenrequest + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "cert-manager.serviceAccountName" . }}-tokenrequest +subjects: + - kind: ServiceAccount + name: {{ template "cert-manager.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} +{{- end }} + +--- + +# Issuer controller role +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-issuers + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +rules: + - apiGroups: ["cert-manager.io"] + resources: ["issuers", "issuers/status"] + verbs: ["update", "patch"] + - apiGroups: ["cert-manager.io"] + resources: ["issuers"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch", "create", "update", "delete"] + - apiGroups: [""] + resources: ["events"] + verbs: ["create", "patch"] +--- + +# ClusterIssuer controller role +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-clusterissuers + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +rules: + - apiGroups: ["cert-manager.io"] + resources: ["clusterissuers", "clusterissuers/status"] + verbs: ["update", "patch"] + - apiGroups: ["cert-manager.io"] + resources: ["clusterissuers"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch", "create", "update", "delete"] + - apiGroups: [""] + resources: ["events"] + verbs: ["create", "patch"] + +--- + +# Certificates controller role +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-certificates + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +rules: + - apiGroups: ["cert-manager.io"] + resources: ["certificates", "certificates/status", "certificaterequests", "certificaterequests/status"] + verbs: ["update", "patch"] + - apiGroups: ["cert-manager.io"] + resources: ["certificates", "certificaterequests", "clusterissuers", "issuers"] + verbs: ["get", "list", "watch"] + # We require these rules to support users with the OwnerReferencesPermissionEnforcement + # admission controller enabled: + # https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#ownerreferencespermissionenforcement + - apiGroups: ["cert-manager.io"] + resources: ["certificates/finalizers", "certificaterequests/finalizers"] + verbs: ["update"] + - apiGroups: ["acme.cert-manager.io"] + resources: ["orders"] + verbs: ["create", "delete", "get", "list", "watch"] + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch", "create", "update", "delete", "patch"] + - apiGroups: [""] + resources: ["events"] + verbs: ["create", "patch"] + +--- + +# Orders controller role +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-orders + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +rules: + - apiGroups: ["acme.cert-manager.io"] + resources: ["orders", "orders/status"] + verbs: ["update", "patch"] + - apiGroups: ["acme.cert-manager.io"] + resources: ["orders", "challenges"] + verbs: ["get", "list", "watch"] + - apiGroups: ["cert-manager.io"] + resources: ["clusterissuers", "issuers"] + verbs: ["get", "list", "watch"] + - apiGroups: ["acme.cert-manager.io"] + resources: ["challenges"] + verbs: ["create", "delete"] + # We require these rules to support users with the OwnerReferencesPermissionEnforcement + # admission controller enabled: + # https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#ownerreferencespermissionenforcement + - apiGroups: ["acme.cert-manager.io"] + resources: ["orders/finalizers"] + verbs: ["update"] + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["events"] + verbs: ["create", "patch"] + +--- + +# Challenges controller role +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-challenges + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +rules: + # Use to update challenge resource status + - apiGroups: ["acme.cert-manager.io"] + resources: ["challenges", "challenges/status"] + verbs: ["update", "patch"] + # Used to watch challenge resources + - apiGroups: ["acme.cert-manager.io"] + resources: ["challenges"] + verbs: ["get", "list", "watch"] + # Used to watch challenges, issuer and clusterissuer resources + - apiGroups: ["cert-manager.io"] + resources: ["issuers", "clusterissuers"] + verbs: ["get", "list", "watch"] + # Need to be able to retrieve ACME account private key to complete challenges + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch"] + # Used to create events + - apiGroups: [""] + resources: ["events"] + verbs: ["create", "patch"] + # HTTP01 rules + - apiGroups: [""] + resources: ["pods", "services"] + verbs: ["get", "list", "watch", "create", "delete"] + - apiGroups: ["networking.k8s.io"] + resources: ["ingresses"] + verbs: ["get", "list", "watch", "create", "delete", "update"] + - apiGroups: [ "gateway.networking.k8s.io" ] + resources: [ "httproutes" ] + verbs: ["get", "list", "watch", "create", "delete", "update"] + # We require the ability to specify a custom hostname when we are creating + # new ingress resources. + # See: https://github.com/openshift/origin/blob/21f191775636f9acadb44fa42beeb4f75b255532/pkg/route/apiserver/admission/ingress_admission.go#L84-L148 + - apiGroups: ["route.openshift.io"] + resources: ["routes/custom-host"] + verbs: ["create"] + # We require these rules to support users with the OwnerReferencesPermissionEnforcement + # admission controller enabled: + # https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#ownerreferencespermissionenforcement + - apiGroups: ["acme.cert-manager.io"] + resources: ["challenges/finalizers"] + verbs: ["update"] + # DNS01 rules (duplicated above) + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch"] + +--- + +# ingress-shim controller role +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-ingress-shim + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +rules: + - apiGroups: ["cert-manager.io"] + resources: ["certificates", "certificaterequests"] + verbs: ["create", "update", "delete"] + - apiGroups: ["cert-manager.io"] + resources: ["certificates", "certificaterequests", "issuers", "clusterissuers"] + verbs: ["get", "list", "watch"] + - apiGroups: ["networking.k8s.io"] + resources: ["ingresses"] + verbs: ["get", "list", "watch"] + # We require these rules to support users with the OwnerReferencesPermissionEnforcement + # admission controller enabled: + # https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#ownerreferencespermissionenforcement + - apiGroups: ["networking.k8s.io"] + resources: ["ingresses/finalizers"] + verbs: ["update"] + - apiGroups: ["gateway.networking.k8s.io"] + resources: ["gateways", "httproutes"] + verbs: ["get", "list", "watch"] + - apiGroups: ["gateway.networking.k8s.io"] + resources: ["gateways/finalizers", "httproutes/finalizers"] + verbs: ["update"] + - apiGroups: [""] + resources: ["events"] + verbs: ["create", "patch"] + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-issuers + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cert-manager.fullname" . }}-controller-issuers +subjects: + - name: {{ template "cert-manager.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + kind: ServiceAccount + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-clusterissuers + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cert-manager.fullname" . }}-controller-clusterissuers +subjects: + - name: {{ template "cert-manager.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + kind: ServiceAccount + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-certificates + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cert-manager.fullname" . }}-controller-certificates +subjects: + - name: {{ template "cert-manager.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + kind: ServiceAccount + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-orders + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cert-manager.fullname" . }}-controller-orders +subjects: + - name: {{ template "cert-manager.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + kind: ServiceAccount + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-challenges + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cert-manager.fullname" . }}-controller-challenges +subjects: + - name: {{ template "cert-manager.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + kind: ServiceAccount + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-ingress-shim + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cert-manager.fullname" . }}-controller-ingress-shim +subjects: + - name: {{ template "cert-manager.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + kind: ServiceAccount + +{{- if .Values.global.rbac.aggregateClusterRoles }} +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-cluster-view + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} + rbac.authorization.k8s.io/aggregate-to-cluster-reader: "true" +rules: + - apiGroups: ["cert-manager.io"] + resources: ["clusterissuers"] + verbs: ["get", "list", "watch"] + +{{- end }} +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-view + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} + {{- if .Values.global.rbac.aggregateClusterRoles }} + rbac.authorization.k8s.io/aggregate-to-view: "true" + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-admin: "true" + rbac.authorization.k8s.io/aggregate-to-cluster-reader: "true" + {{- end }} +rules: + - apiGroups: ["cert-manager.io"] + resources: ["certificates", "certificaterequests", "issuers"] + verbs: ["get", "list", "watch"] + - apiGroups: ["acme.cert-manager.io"] + resources: ["challenges", "orders"] + verbs: ["get", "list", "watch"] + + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-edit + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} + {{- if .Values.global.rbac.aggregateClusterRoles }} + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-admin: "true" + {{- end }} +rules: + - apiGroups: ["cert-manager.io"] + resources: ["certificates", "certificaterequests", "issuers"] + verbs: ["create", "delete", "deletecollection", "patch", "update"] + - apiGroups: ["cert-manager.io"] + resources: ["certificates/status"] + verbs: ["update"] + - apiGroups: ["acme.cert-manager.io"] + resources: ["challenges", "orders"] + verbs: ["create", "delete", "deletecollection", "patch", "update"] + +--- + +{{- if not .Values.disableAutoApproval -}} + +# Permission to approve CertificateRequests referencing cert-manager.io Issuers and ClusterIssuers +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-approve:cert-manager-io + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cert-manager" + {{- include "labels" . | nindent 4 }} +rules: + - apiGroups: ["cert-manager.io"] + resources: ["signers"] + verbs: ["approve"] + {{- with .Values.approveSignerNames }} + resourceNames: + {{- range . }} + - {{ . | quote }} + {{- end }} + {{- end }} + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-approve:cert-manager-io + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cert-manager" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cert-manager.fullname" . }}-controller-approve:cert-manager-io +subjects: + - name: {{ template "cert-manager.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + kind: ServiceAccount + +--- + +{{- end -}} + +# Permission to: +# - Update and sign CertificateSigningRequests referencing cert-manager.io Issuers and ClusterIssuers +# - Perform SubjectAccessReviews to test whether users are able to reference Namespaced Issuers +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-certificatesigningrequests + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cert-manager" + {{- include "labels" . | nindent 4 }} +rules: + - apiGroups: ["certificates.k8s.io"] + resources: ["certificatesigningrequests"] + verbs: ["get", "list", "watch", "update"] + - apiGroups: ["certificates.k8s.io"] + resources: ["certificatesigningrequests/status"] + verbs: ["update", "patch"] + - apiGroups: ["certificates.k8s.io"] + resources: ["signers"] + resourceNames: ["issuers.cert-manager.io/*", "clusterissuers.cert-manager.io/*"] + verbs: ["sign"] + - apiGroups: ["authorization.k8s.io"] + resources: ["subjectaccessreviews"] + verbs: ["create"] + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-certificatesigningrequests + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cert-manager" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cert-manager.fullname" . }}-controller-certificatesigningrequests +subjects: + - name: {{ template "cert-manager.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + kind: ServiceAccount +{{- end }} diff --git a/backing-services/cert-manager/templates/service.yaml b/backing-services/cert-manager/templates/service.yaml new file mode 100644 index 0000000..360ec64 --- /dev/null +++ b/backing-services/cert-manager/templates/service.yaml @@ -0,0 +1,37 @@ +{{- if and .Values.prometheus.enabled (not .Values.prometheus.podmonitor.enabled) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "cert-manager.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} +{{- with .Values.serviceAnnotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} + {{- with .Values.serviceLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + {{- if .Values.serviceIPFamilyPolicy }} + ipFamilyPolicy: {{ .Values.serviceIPFamilyPolicy }} + {{- end }} + {{- if .Values.serviceIPFamilies }} + ipFamilies: {{ .Values.serviceIPFamilies | toYaml | nindent 2 }} + {{- end }} + ports: + - protocol: TCP + port: 9402 + name: tcp-prometheus-servicemonitor + targetPort: {{ .Values.prometheus.servicemonitor.targetPort }} + selector: + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" +{{- end }} diff --git a/backing-services/cert-manager/templates/serviceaccount.yaml b/backing-services/cert-manager/templates/serviceaccount.yaml new file mode 100644 index 0000000..87fc00e --- /dev/null +++ b/backing-services/cert-manager/templates/serviceaccount.yaml @@ -0,0 +1,25 @@ +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +{{- with .Values.global.imagePullSecrets }} +imagePullSecrets: + {{- toYaml . | nindent 2 }} +{{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +metadata: + name: {{ template "cert-manager.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} + {{- with .Values.serviceAccount.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/cert-manager/templates/servicemonitor.yaml b/backing-services/cert-manager/templates/servicemonitor.yaml new file mode 100644 index 0000000..dd1beec --- /dev/null +++ b/backing-services/cert-manager/templates/servicemonitor.yaml @@ -0,0 +1,63 @@ +{{- if and .Values.prometheus.enabled (and .Values.prometheus.podmonitor.enabled .Values.prometheus.servicemonitor.enabled) }} +{{- fail "Either .Values.prometheus.podmonitor.enabled or .Values.prometheus.servicemonitor.enabled can be enabled at a time, but not both." }} +{{- else if and .Values.prometheus.enabled .Values.prometheus.servicemonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "cert-manager.fullname" . }} +{{- if .Values.prometheus.servicemonitor.namespace }} + namespace: {{ .Values.prometheus.servicemonitor.namespace }} +{{- else }} + namespace: {{ include "cert-manager.namespace" . }} +{{- end }} + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} + prometheus: {{ .Values.prometheus.servicemonitor.prometheusInstance }} + {{- with .Values.prometheus.servicemonitor.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- if .Values.prometheus.servicemonitor.annotations }} + annotations: + {{- with .Values.prometheus.servicemonitor.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} +spec: + jobLabel: {{ template "cert-manager.fullname" . }} + selector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - {{ include "cainjector.name" . }} + - {{ template "cert-manager.name" . }} + - {{ include "webhook.name" . }} + - key: app.kubernetes.io/instance + operator: In + values: + - {{ .Release.Name }} + - key: app.kubernetes.io/component + operator: In + values: + - cainjector + - controller + - webhook +{{- if .Values.prometheus.servicemonitor.namespace }} + namespaceSelector: + matchNames: + - {{ include "cert-manager.namespace" . }} +{{- end }} + endpoints: + - targetPort: {{ .Values.prometheus.servicemonitor.targetPort }} + path: {{ .Values.prometheus.servicemonitor.path }} + interval: {{ .Values.prometheus.servicemonitor.interval }} + scrapeTimeout: {{ .Values.prometheus.servicemonitor.scrapeTimeout }} + honorLabels: {{ .Values.prometheus.servicemonitor.honorLabels }} + {{- with .Values.prometheus.servicemonitor.endpointAdditionalProperties }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/cert-manager/templates/startupapicheck-job.yaml b/backing-services/cert-manager/templates/startupapicheck-job.yaml new file mode 100644 index 0000000..183cff4 --- /dev/null +++ b/backing-services/cert-manager/templates/startupapicheck-job.yaml @@ -0,0 +1,95 @@ +{{- if .Values.startupapicheck.enabled }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "startupapicheck.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "startupapicheck.name" . }} + app.kubernetes.io/name: {{ include "startupapicheck.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "startupapicheck" + {{- include "labels" . | nindent 4 }} + {{- with .Values.startupapicheck.jobAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + backoffLimit: {{ .Values.startupapicheck.backoffLimit }} + template: + metadata: + labels: + app: {{ include "startupapicheck.name" . }} + app.kubernetes.io/name: {{ include "startupapicheck.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "startupapicheck" + {{- include "labels" . | nindent 8 }} + {{- with .Values.startupapicheck.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.startupapicheck.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + restartPolicy: OnFailure + serviceAccountName: {{ template "startupapicheck.serviceAccountName" . }} + {{- if hasKey .Values.startupapicheck "automountServiceAccountToken" }} + automountServiceAccountToken: {{ .Values.startupapicheck.automountServiceAccountToken }} + {{- end }} + enableServiceLinks: {{ .Values.startupapicheck.enableServiceLinks }} + {{- with .Values.global.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} + {{- with .Values.startupapicheck.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }}-startupapicheck + image: "{{ template "image" (tuple .Values.startupapicheck.image $.Chart.AppVersion) }}" + imagePullPolicy: {{ .Values.startupapicheck.image.pullPolicy }} + args: + - check + - api + - --wait={{ .Values.startupapicheck.timeout }} + {{- with .Values.startupapicheck.extraArgs }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.startupapicheck.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- with .Values.startupapicheck.extraEnv }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.startupapicheck.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.startupapicheck.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.startupapicheck.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.startupapicheck.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.startupapicheck.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.startupapicheck.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/backing-services/cert-manager/templates/startupapicheck-psp-clusterrole.yaml b/backing-services/cert-manager/templates/startupapicheck-psp-clusterrole.yaml new file mode 100644 index 0000000..dacd4be --- /dev/null +++ b/backing-services/cert-manager/templates/startupapicheck-psp-clusterrole.yaml @@ -0,0 +1,24 @@ +{{- if .Values.startupapicheck.enabled }} +{{- if .Values.global.podSecurityPolicy.enabled }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "startupapicheck.fullname" . }}-psp + labels: + app: {{ include "startupapicheck.name" . }} + app.kubernetes.io/name: {{ include "startupapicheck.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "startupapicheck" + {{- include "labels" . | nindent 4 }} + {{- with .Values.startupapicheck.rbac.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +rules: +- apiGroups: ['policy'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "startupapicheck.fullname" . }} +{{- end }} +{{- end }} diff --git a/backing-services/cert-manager/templates/startupapicheck-psp-clusterrolebinding.yaml b/backing-services/cert-manager/templates/startupapicheck-psp-clusterrolebinding.yaml new file mode 100644 index 0000000..54d5a42 --- /dev/null +++ b/backing-services/cert-manager/templates/startupapicheck-psp-clusterrolebinding.yaml @@ -0,0 +1,26 @@ +{{- if .Values.startupapicheck.enabled }} +{{- if .Values.global.podSecurityPolicy.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "startupapicheck.fullname" . }}-psp + labels: + app: {{ include "startupapicheck.name" . }} + app.kubernetes.io/name: {{ include "startupapicheck.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "startupapicheck" + {{- include "labels" . | nindent 4 }} + {{- with .Values.startupapicheck.rbac.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "startupapicheck.fullname" . }}-psp +subjects: + - kind: ServiceAccount + name: {{ template "startupapicheck.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} +{{- end }} +{{- end }} diff --git a/backing-services/cert-manager/templates/startupapicheck-psp.yaml b/backing-services/cert-manager/templates/startupapicheck-psp.yaml new file mode 100644 index 0000000..f09d60d --- /dev/null +++ b/backing-services/cert-manager/templates/startupapicheck-psp.yaml @@ -0,0 +1,51 @@ +{{- if .Values.startupapicheck.enabled }} +{{- if .Values.global.podSecurityPolicy.enabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "startupapicheck.fullname" . }} + labels: + app: {{ include "startupapicheck.name" . }} + app.kubernetes.io/name: {{ include "startupapicheck.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "startupapicheck" + {{- include "labels" . | nindent 4 }} + annotations: + seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default' + seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + {{- if .Values.global.podSecurityPolicy.useAppArmor }} + apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' + apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + {{- end }} + {{- with .Values.startupapicheck.rbac.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + privileged: false + allowPrivilegeEscalation: false + allowedCapabilities: [] # default set of capabilities are implicitly allowed + volumes: + - 'projected' + - 'secret' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 +{{- end }} +{{- end }} diff --git a/backing-services/cert-manager/templates/startupapicheck-rbac.yaml b/backing-services/cert-manager/templates/startupapicheck-rbac.yaml new file mode 100644 index 0000000..ab8c30f --- /dev/null +++ b/backing-services/cert-manager/templates/startupapicheck-rbac.yaml @@ -0,0 +1,48 @@ +{{- if .Values.startupapicheck.enabled }} +{{- if .Values.global.rbac.create }} +# create certificate role +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "startupapicheck.fullname" . }}:create-cert + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "startupapicheck.name" . }} + app.kubernetes.io/name: {{ include "startupapicheck.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "startupapicheck" + {{- include "labels" . | nindent 4 }} + {{- with .Values.startupapicheck.rbac.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +rules: + - apiGroups: ["cert-manager.io"] + resources: ["certificaterequests"] + verbs: ["create"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "startupapicheck.fullname" . }}:create-cert + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "startupapicheck.name" . }} + app.kubernetes.io/name: {{ include "startupapicheck.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "startupapicheck" + {{- include "labels" . | nindent 4 }} + {{- with .Values.startupapicheck.rbac.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "startupapicheck.fullname" . }}:create-cert +subjects: + - kind: ServiceAccount + name: {{ template "startupapicheck.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} +{{- end }} +{{- end }} diff --git a/backing-services/cert-manager/templates/startupapicheck-serviceaccount.yaml b/backing-services/cert-manager/templates/startupapicheck-serviceaccount.yaml new file mode 100644 index 0000000..8c41760 --- /dev/null +++ b/backing-services/cert-manager/templates/startupapicheck-serviceaccount.yaml @@ -0,0 +1,27 @@ +{{- if .Values.startupapicheck.enabled }} +{{- if .Values.startupapicheck.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +automountServiceAccountToken: {{ .Values.startupapicheck.serviceAccount.automountServiceAccountToken }} +metadata: + name: {{ template "startupapicheck.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + {{- with .Values.startupapicheck.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + app: {{ include "startupapicheck.name" . }} + app.kubernetes.io/name: {{ include "startupapicheck.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "startupapicheck" + {{- include "labels" . | nindent 4 }} + {{- with .Values.startupapicheck.serviceAccount.labels }} + {{ toYaml . | nindent 4 }} + {{- end }} +{{- with .Values.global.imagePullSecrets }} +imagePullSecrets: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/cert-manager/templates/webhook-config.yaml b/backing-services/cert-manager/templates/webhook-config.yaml new file mode 100644 index 0000000..cd8b67f --- /dev/null +++ b/backing-services/cert-manager/templates/webhook-config.yaml @@ -0,0 +1,19 @@ +{{- if .Values.webhook.config -}} +{{- $config := .Values.webhook.config -}} +{{- $_ := set $config "apiVersion" (default "webhook.config.cert-manager.io/v1alpha1" $config.apiVersion) -}} +{{- $_ := set $config "kind" (default "WebhookConfiguration" $config.kind) -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "webhook.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} +data: + config.yaml: | + {{- $config | toYaml | nindent 4 }} +{{- end -}} \ No newline at end of file diff --git a/backing-services/cert-manager/templates/webhook-deployment.yaml b/backing-services/cert-manager/templates/webhook-deployment.yaml new file mode 100644 index 0000000..1535589 --- /dev/null +++ b/backing-services/cert-manager/templates/webhook-deployment.yaml @@ -0,0 +1,211 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "webhook.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} + {{- with .Values.webhook.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.webhook.replicaCount }} + {{- /* The if statement below is equivalent to {{- if $value }} but will also return true for 0. */ -}} + {{- if not (has (quote .Values.global.revisionHistoryLimit) (list "" (quote ""))) }} + revisionHistoryLimit: {{ .Values.global.revisionHistoryLimit }} + {{- end }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- with .Values.webhook.strategy }} + strategy: + {{- toYaml . | nindent 4 }} + {{- end }} + template: + metadata: + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 8 }} + {{- with .Values.webhook.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.webhook.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if and .Values.prometheus.enabled (not (or .Values.prometheus.servicemonitor.enabled .Values.prometheus.podmonitor.enabled)) }} + {{- if not .Values.webhook.podAnnotations }} + annotations: + {{- end }} + prometheus.io/path: "/metrics" + prometheus.io/scrape: 'true' + prometheus.io/port: '9402' + {{- end }} + spec: + serviceAccountName: {{ template "webhook.serviceAccountName" . }} + {{- if hasKey .Values.webhook "automountServiceAccountToken" }} + automountServiceAccountToken: {{ .Values.webhook.automountServiceAccountToken }} + {{- end }} + enableServiceLinks: {{ .Values.webhook.enableServiceLinks }} + {{- with .Values.global.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} + {{- with .Values.webhook.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.webhook.hostNetwork }} + hostNetwork: true + {{- end }} + {{- if .Values.webhook.hostNetwork }} + dnsPolicy: ClusterFirstWithHostNet + {{- end }} + containers: + - name: {{ .Chart.Name }}-webhook + image: "{{ template "image" (tuple .Values.webhook.image $.Chart.AppVersion) }}" + imagePullPolicy: {{ .Values.webhook.image.pullPolicy }} + args: + {{- /* The if statement below is equivalent to {{- if $value }} but will also return true for 0. */ -}} + {{- if not (has (quote .Values.global.logLevel) (list "" (quote ""))) }} + - --v={{ .Values.global.logLevel }} + {{- end }} + {{- if .Values.webhook.config }} + - --config=/var/cert-manager/config/config.yaml + {{- end }} + {{- $config := default .Values.webhook.config "" }} + {{ if not $config.securePort -}} + - --secure-port={{ .Values.webhook.securePort }} + {{- end }} + {{- if .Values.webhook.featureGates }} + - --feature-gates={{ .Values.webhook.featureGates }} + {{- end }} + {{- $tlsConfig := default $config.tlsConfig "" }} + {{ if or (not $config.tlsConfig) (and (not $tlsConfig.dynamic) (not $tlsConfig.filesystem) ) -}} + - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) + - --dynamic-serving-ca-secret-name={{ template "webhook.fullname" . }}-ca + - --dynamic-serving-dns-names={{ template "webhook.fullname" . }} + - --dynamic-serving-dns-names={{ template "webhook.fullname" . }}.$(POD_NAMESPACE) + - --dynamic-serving-dns-names={{ template "webhook.fullname" . }}.$(POD_NAMESPACE).svc + {{ if .Values.webhook.url.host }} + - --dynamic-serving-dns-names={{ .Values.webhook.url.host }} + {{- end }} + {{- end }} + {{- with .Values.webhook.extraArgs }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- if not .Values.prometheus.enabled }} + - --metrics-listen-address=0 + {{- end }} + ports: + - name: https + protocol: TCP + {{- if $config.securePort }} + containerPort: {{ $config.securePort }} + {{- else if .Values.webhook.securePort }} + containerPort: {{ .Values.webhook.securePort }} + {{- else }} + containerPort: 6443 + {{- end }} + - name: healthcheck + protocol: TCP + {{- if $config.healthzPort }} + containerPort: {{ $config.healthzPort }} + {{- else }} + containerPort: 6080 + {{- end }} + {{- if .Values.prometheus.enabled }} + - containerPort: 9402 + name: http-metrics + protocol: TCP + {{- end }} + livenessProbe: + httpGet: + path: /livez + {{- if $config.healthzPort }} + port: {{ $config.healthzPort }} + {{- else }} + port: 6080 + {{- end }} + scheme: HTTP + initialDelaySeconds: {{ .Values.webhook.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.webhook.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.webhook.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.webhook.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.webhook.livenessProbe.failureThreshold }} + readinessProbe: + httpGet: + path: /healthz + {{- if $config.healthzPort }} + port: {{ $config.healthzPort }} + {{- else }} + port: 6080 + {{- end }} + scheme: HTTP + initialDelaySeconds: {{ .Values.webhook.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.webhook.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.webhook.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.webhook.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.webhook.readinessProbe.failureThreshold }} + {{- with .Values.webhook.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- with .Values.webhook.extraEnv }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.webhook.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if or .Values.webhook.config .Values.webhook.volumeMounts }} + volumeMounts: + {{- if .Values.webhook.config }} + - name: config + mountPath: /var/cert-manager/config + {{- end }} + {{- with .Values.webhook.volumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} + {{- with .Values.webhook.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.webhook.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.webhook.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.webhook.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if or .Values.webhook.config .Values.webhook.volumes }} + volumes: + {{- if .Values.webhook.config }} + - name: config + configMap: + name: {{ include "webhook.fullname" . }} + {{- end }} + {{- with .Values.webhook.volumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} diff --git a/backing-services/cert-manager/templates/webhook-mutating-webhook.yaml b/backing-services/cert-manager/templates/webhook-mutating-webhook.yaml new file mode 100644 index 0000000..9ea2977 --- /dev/null +++ b/backing-services/cert-manager/templates/webhook-mutating-webhook.yaml @@ -0,0 +1,48 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: {{ include "webhook.fullname" . }} + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} + annotations: + cert-manager.io/inject-ca-from-secret: {{ printf "%s/%s-ca" (include "cert-manager.namespace" .) (include "webhook.fullname" .) | quote }} + {{- with .Values.webhook.mutatingWebhookConfigurationAnnotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +webhooks: + - name: webhook.cert-manager.io + {{- with .Values.webhook.mutatingWebhookConfiguration.namespaceSelector }} + namespaceSelector: + {{- toYaml . | nindent 6 }} + {{- end }} + rules: + - apiGroups: + - "cert-manager.io" + apiVersions: + - "v1" + operations: + - CREATE + resources: + - "certificaterequests" + admissionReviewVersions: ["v1"] + # This webhook only accepts v1 cert-manager resources. + # Equivalent matchPolicy ensures that non-v1 resource requests are sent to + # this webhook (after the resources have been converted to v1). + matchPolicy: Equivalent + timeoutSeconds: {{ .Values.webhook.timeoutSeconds }} + failurePolicy: Fail + # Only include 'sideEffects' field in Kubernetes 1.12+ + sideEffects: None + clientConfig: + {{- if .Values.webhook.url.host }} + url: https://{{ .Values.webhook.url.host }}/mutate + {{- else }} + service: + name: {{ template "webhook.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} + path: /mutate + {{- end }} \ No newline at end of file diff --git a/backing-services/cert-manager/templates/webhook-poddisruptionbudget.yaml b/backing-services/cert-manager/templates/webhook-poddisruptionbudget.yaml new file mode 100644 index 0000000..ab2a481 --- /dev/null +++ b/backing-services/cert-manager/templates/webhook-poddisruptionbudget.yaml @@ -0,0 +1,29 @@ +{{- if .Values.webhook.podDisruptionBudget.enabled }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "webhook.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + + {{- if not (or (hasKey .Values.webhook.podDisruptionBudget "minAvailable") (hasKey .Values.webhook.podDisruptionBudget "maxUnavailable")) }} + minAvailable: 1 # Default value because minAvailable and maxUnavailable are not set + {{- end }} + {{- if hasKey .Values.webhook.podDisruptionBudget "minAvailable" }} + minAvailable: {{ .Values.webhook.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if hasKey .Values.webhook.podDisruptionBudget "maxUnavailable" }} + maxUnavailable: {{ .Values.webhook.podDisruptionBudget.maxUnavailable }} + {{- end }} +{{- end }} diff --git a/backing-services/cert-manager/templates/webhook-psp-clusterrole.yaml b/backing-services/cert-manager/templates/webhook-psp-clusterrole.yaml new file mode 100644 index 0000000..f6fa4c5 --- /dev/null +++ b/backing-services/cert-manager/templates/webhook-psp-clusterrole.yaml @@ -0,0 +1,18 @@ +{{- if .Values.global.podSecurityPolicy.enabled }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "webhook.fullname" . }}-psp + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} +rules: +- apiGroups: ['policy'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "webhook.fullname" . }} +{{- end }} diff --git a/backing-services/cert-manager/templates/webhook-psp-clusterrolebinding.yaml b/backing-services/cert-manager/templates/webhook-psp-clusterrolebinding.yaml new file mode 100644 index 0000000..858df8f --- /dev/null +++ b/backing-services/cert-manager/templates/webhook-psp-clusterrolebinding.yaml @@ -0,0 +1,20 @@ +{{- if .Values.global.podSecurityPolicy.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "webhook.fullname" . }}-psp + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "webhook.fullname" . }}-psp +subjects: + - kind: ServiceAccount + name: {{ template "webhook.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} +{{- end }} diff --git a/backing-services/cert-manager/templates/webhook-psp.yaml b/backing-services/cert-manager/templates/webhook-psp.yaml new file mode 100644 index 0000000..4d5d959 --- /dev/null +++ b/backing-services/cert-manager/templates/webhook-psp.yaml @@ -0,0 +1,54 @@ +{{- if .Values.global.podSecurityPolicy.enabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "webhook.fullname" . }} + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} + annotations: + seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default' + seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + {{- if .Values.global.podSecurityPolicy.useAppArmor }} + apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' + apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + {{- end }} +spec: + privileged: false + allowPrivilegeEscalation: false + allowedCapabilities: [] # default set of capabilities are implicitly allowed + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + hostNetwork: {{ .Values.webhook.hostNetwork }} + {{- if .Values.webhook.hostNetwork }} + hostPorts: + - max: {{ .Values.webhook.securePort }} + min: {{ .Values.webhook.securePort }} + {{- end }} + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 +{{- end }} diff --git a/backing-services/cert-manager/templates/webhook-rbac.yaml b/backing-services/cert-manager/templates/webhook-rbac.yaml new file mode 100644 index 0000000..b99325e --- /dev/null +++ b/backing-services/cert-manager/templates/webhook-rbac.yaml @@ -0,0 +1,90 @@ +{{- if .Values.global.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "webhook.fullname" . }}:dynamic-serving + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} +rules: +- apiGroups: [""] + resources: ["secrets"] + resourceNames: + - '{{ template "webhook.fullname" . }}-ca' + {{- $certmanagerNamespace := include "cert-manager.namespace" . }} + {{- with (.Values.webhook.config.metricsTLSConfig).dynamic }} + {{- if $certmanagerNamespace | eq .secretNamespace }} + # Allow webhook to read and update the metrics CA Secret when dynamic TLS is + # enabled for the metrics server and if the Secret is configured to be in the + # same namespace as cert-manager. + - {{ .secretName | quote }} + {{- end }} + {{- end }} + verbs: ["get", "list", "watch", "update"] +# It's not possible to grant CREATE permission on a single resourceName. +- apiGroups: [""] + resources: ["secrets"] + verbs: ["create"] +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "webhook.fullname" . }}:dynamic-serving + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "webhook.fullname" . }}:dynamic-serving +subjects: +- kind: ServiceAccount + name: {{ template "webhook.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "webhook.fullname" . }}:subjectaccessreviews + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} +rules: +- apiGroups: ["authorization.k8s.io"] + resources: ["subjectaccessreviews"] + verbs: ["create"] +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "webhook.fullname" . }}:subjectaccessreviews + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "webhook.fullname" . }}:subjectaccessreviews +subjects: +- kind: ServiceAccount + name: {{ template "webhook.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} +{{- end }} diff --git a/backing-services/cert-manager/templates/webhook-service.yaml b/backing-services/cert-manager/templates/webhook-service.yaml new file mode 100644 index 0000000..cd5010f --- /dev/null +++ b/backing-services/cert-manager/templates/webhook-service.yaml @@ -0,0 +1,44 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "webhook.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} +{{- with .Values.webhook.serviceAnnotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} + {{- with .Values.webhook.serviceLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.webhook.serviceType }} + {{- if .Values.webhook.serviceIPFamilyPolicy }} + ipFamilyPolicy: {{ .Values.webhook.serviceIPFamilyPolicy }} + {{- end }} + {{- if .Values.webhook.serviceIPFamilies }} + ipFamilies: {{ .Values.webhook.serviceIPFamilies | toYaml | nindent 2 }} + {{- end }} + {{- with .Values.webhook.loadBalancerIP }} + loadBalancerIP: {{ . }} + {{- end }} + ports: + - name: https + port: 443 + protocol: TCP + targetPort: "https" +{{- if and .Values.prometheus.enabled (not .Values.prometheus.podmonitor.enabled) }} + - name: metrics + port: 9402 + protocol: TCP + targetPort: "http-metrics" +{{- end }} + selector: + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" diff --git a/backing-services/cert-manager/templates/webhook-serviceaccount.yaml b/backing-services/cert-manager/templates/webhook-serviceaccount.yaml new file mode 100644 index 0000000..dff5c06 --- /dev/null +++ b/backing-services/cert-manager/templates/webhook-serviceaccount.yaml @@ -0,0 +1,25 @@ +{{- if .Values.webhook.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +automountServiceAccountToken: {{ .Values.webhook.serviceAccount.automountServiceAccountToken }} +metadata: + name: {{ template "webhook.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + {{- with .Values.webhook.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} + {{- with .Values.webhook.serviceAccount.labels }} + {{ toYaml . | nindent 4 }} + {{- end }} +{{- with .Values.global.imagePullSecrets }} +imagePullSecrets: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end }} diff --git a/backing-services/cert-manager/templates/webhook-validating-webhook.yaml b/backing-services/cert-manager/templates/webhook-validating-webhook.yaml new file mode 100644 index 0000000..76235fd --- /dev/null +++ b/backing-services/cert-manager/templates/webhook-validating-webhook.yaml @@ -0,0 +1,49 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: {{ include "webhook.fullname" . }} + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} + annotations: + cert-manager.io/inject-ca-from-secret: {{ printf "%s/%s-ca" (include "cert-manager.namespace" .) (include "webhook.fullname" .) | quote}} + {{- with .Values.webhook.validatingWebhookConfigurationAnnotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +webhooks: + - name: webhook.cert-manager.io + {{- with .Values.webhook.validatingWebhookConfiguration.namespaceSelector }} + namespaceSelector: + {{- toYaml . | nindent 6 }} + {{- end }} + rules: + - apiGroups: + - "cert-manager.io" + - "acme.cert-manager.io" + apiVersions: + - "v1" + operations: + - CREATE + - UPDATE + resources: + - "*/*" + admissionReviewVersions: ["v1"] + # This webhook only accepts v1 cert-manager resources. + # Equivalent matchPolicy ensures that non-v1 resource requests are sent to + # this webhook (after the resources have been converted to v1). + matchPolicy: Equivalent + timeoutSeconds: {{ .Values.webhook.timeoutSeconds }} + failurePolicy: Fail + sideEffects: None + clientConfig: + {{- if .Values.webhook.url.host }} + url: https://{{ .Values.webhook.url.host }}/validate + {{- else }} + service: + name: {{ template "webhook.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} + path: /validate + {{- end }} diff --git a/backing-services/cert-manager/values.schema.json b/backing-services/cert-manager/values.schema.json new file mode 100644 index 0000000..d04da90 --- /dev/null +++ b/backing-services/cert-manager/values.schema.json @@ -0,0 +1,2135 @@ +{ + "$defs": { + "helm-values": { + "additionalProperties": false, + "properties": { + "acmesolver": { + "$ref": "#/$defs/helm-values.acmesolver" + }, + "affinity": { + "$ref": "#/$defs/helm-values.affinity" + }, + "approveSignerNames": { + "$ref": "#/$defs/helm-values.approveSignerNames" + }, + "automountServiceAccountToken": { + "$ref": "#/$defs/helm-values.automountServiceAccountToken" + }, + "cainjector": { + "$ref": "#/$defs/helm-values.cainjector" + }, + "clusterResourceNamespace": { + "$ref": "#/$defs/helm-values.clusterResourceNamespace" + }, + "config": { + "$ref": "#/$defs/helm-values.config" + }, + "containerSecurityContext": { + "$ref": "#/$defs/helm-values.containerSecurityContext" + }, + "crds": { + "$ref": "#/$defs/helm-values.crds" + }, + "creator": { + "$ref": "#/$defs/helm-values.creator" + }, + "deploymentAnnotations": { + "$ref": "#/$defs/helm-values.deploymentAnnotations" + }, + "disableAutoApproval": { + "$ref": "#/$defs/helm-values.disableAutoApproval" + }, + "dns01RecursiveNameservers": { + "$ref": "#/$defs/helm-values.dns01RecursiveNameservers" + }, + "dns01RecursiveNameserversOnly": { + "$ref": "#/$defs/helm-values.dns01RecursiveNameserversOnly" + }, + "enableCertificateOwnerRef": { + "$ref": "#/$defs/helm-values.enableCertificateOwnerRef" + }, + "enableServiceLinks": { + "$ref": "#/$defs/helm-values.enableServiceLinks" + }, + "enabled": { + "$ref": "#/$defs/helm-values.enabled" + }, + "extraArgs": { + "$ref": "#/$defs/helm-values.extraArgs" + }, + "extraEnv": { + "$ref": "#/$defs/helm-values.extraEnv" + }, + "extraObjects": { + "$ref": "#/$defs/helm-values.extraObjects" + }, + "featureGates": { + "$ref": "#/$defs/helm-values.featureGates" + }, + "fullnameOverride": { + "$ref": "#/$defs/helm-values.fullnameOverride" + }, + "global": { + "$ref": "#/$defs/helm-values.global" + }, + "hostAliases": { + "$ref": "#/$defs/helm-values.hostAliases" + }, + "http_proxy": { + "$ref": "#/$defs/helm-values.http_proxy" + }, + "https_proxy": { + "$ref": "#/$defs/helm-values.https_proxy" + }, + "image": { + "$ref": "#/$defs/helm-values.image" + }, + "ingressShim": { + "$ref": "#/$defs/helm-values.ingressShim" + }, + "installCRDs": { + "$ref": "#/$defs/helm-values.installCRDs" + }, + "livenessProbe": { + "$ref": "#/$defs/helm-values.livenessProbe" + }, + "maxConcurrentChallenges": { + "$ref": "#/$defs/helm-values.maxConcurrentChallenges" + }, + "nameOverride": { + "$ref": "#/$defs/helm-values.nameOverride" + }, + "namespace": { + "$ref": "#/$defs/helm-values.namespace" + }, + "no_proxy": { + "$ref": "#/$defs/helm-values.no_proxy" + }, + "nodeSelector": { + "$ref": "#/$defs/helm-values.nodeSelector" + }, + "podAnnotations": { + "$ref": "#/$defs/helm-values.podAnnotations" + }, + "podDisruptionBudget": { + "$ref": "#/$defs/helm-values.podDisruptionBudget" + }, + "podDnsConfig": { + "$ref": "#/$defs/helm-values.podDnsConfig" + }, + "podDnsPolicy": { + "$ref": "#/$defs/helm-values.podDnsPolicy" + }, + "podLabels": { + "$ref": "#/$defs/helm-values.podLabels" + }, + "prometheus": { + "$ref": "#/$defs/helm-values.prometheus" + }, + "replicaCount": { + "$ref": "#/$defs/helm-values.replicaCount" + }, + "resources": { + "$ref": "#/$defs/helm-values.resources" + }, + "securityContext": { + "$ref": "#/$defs/helm-values.securityContext" + }, + "serviceAccount": { + "$ref": "#/$defs/helm-values.serviceAccount" + }, + "serviceAnnotations": { + "$ref": "#/$defs/helm-values.serviceAnnotations" + }, + "serviceIPFamilies": { + "$ref": "#/$defs/helm-values.serviceIPFamilies" + }, + "serviceIPFamilyPolicy": { + "$ref": "#/$defs/helm-values.serviceIPFamilyPolicy" + }, + "serviceLabels": { + "$ref": "#/$defs/helm-values.serviceLabels" + }, + "startupapicheck": { + "$ref": "#/$defs/helm-values.startupapicheck" + }, + "strategy": { + "$ref": "#/$defs/helm-values.strategy" + }, + "tolerations": { + "$ref": "#/$defs/helm-values.tolerations" + }, + "topologySpreadConstraints": { + "$ref": "#/$defs/helm-values.topologySpreadConstraints" + }, + "volumeMounts": { + "$ref": "#/$defs/helm-values.volumeMounts" + }, + "volumes": { + "$ref": "#/$defs/helm-values.volumes" + }, + "webhook": { + "$ref": "#/$defs/helm-values.webhook" + } + }, + "type": "object" + }, + "helm-values.acmesolver": { + "additionalProperties": false, + "properties": { + "image": { + "$ref": "#/$defs/helm-values.acmesolver.image" + } + }, + "type": "object" + }, + "helm-values.acmesolver.image": { + "additionalProperties": false, + "properties": { + "digest": { + "$ref": "#/$defs/helm-values.acmesolver.image.digest" + }, + "pullPolicy": { + "$ref": "#/$defs/helm-values.acmesolver.image.pullPolicy" + }, + "registry": { + "$ref": "#/$defs/helm-values.acmesolver.image.registry" + }, + "repository": { + "$ref": "#/$defs/helm-values.acmesolver.image.repository" + }, + "tag": { + "$ref": "#/$defs/helm-values.acmesolver.image.tag" + } + }, + "type": "object" + }, + "helm-values.acmesolver.image.digest": { + "description": "Setting a digest will override any tag.", + "type": "string" + }, + "helm-values.acmesolver.image.pullPolicy": { + "default": "IfNotPresent", + "description": "Kubernetes imagePullPolicy on Deployment.", + "type": "string" + }, + "helm-values.acmesolver.image.registry": { + "description": "The container registry to pull the acmesolver image from.", + "type": "string" + }, + "helm-values.acmesolver.image.repository": { + "default": "quay.io/jetstack/cert-manager-acmesolver", + "description": "The container image for the cert-manager acmesolver.", + "type": "string" + }, + "helm-values.acmesolver.image.tag": { + "description": "Override the image tag to deploy by setting this variable. If no value is set, the chart's appVersion is used.", + "type": "string" + }, + "helm-values.affinity": { + "default": {}, + "description": "A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core).\n\nFor example:\naffinity:\n nodeAffinity:\n requiredDuringSchedulingIgnoredDuringExecution:\n nodeSelectorTerms:\n - matchExpressions:\n - key: foo.bar.com/role\n operator: In\n values:\n - master", + "type": "object" + }, + "helm-values.approveSignerNames": { + "default": [ + "issuers.cert-manager.io/*", + "clusterissuers.cert-manager.io/*" + ], + "description": "List of signer names that cert-manager will approve by default. CertificateRequests referencing these signer names will be auto-approved by cert-manager. Defaults to just approving the cert-manager.io Issuer and ClusterIssuer issuers. When set to an empty array, ALL issuers will be auto-approved by cert-manager. To disable the auto-approval, because eg. you are using approver-policy, you can enable 'disableAutoApproval'.\nref: https://cert-manager.io/docs/concepts/certificaterequest/#approval", + "items": {}, + "type": "array" + }, + "helm-values.automountServiceAccountToken": { + "description": "Automounting API credentials for a particular pod.", + "type": "boolean" + }, + "helm-values.cainjector": { + "additionalProperties": false, + "properties": { + "affinity": { + "$ref": "#/$defs/helm-values.cainjector.affinity" + }, + "automountServiceAccountToken": { + "$ref": "#/$defs/helm-values.cainjector.automountServiceAccountToken" + }, + "config": { + "$ref": "#/$defs/helm-values.cainjector.config" + }, + "containerSecurityContext": { + "$ref": "#/$defs/helm-values.cainjector.containerSecurityContext" + }, + "deploymentAnnotations": { + "$ref": "#/$defs/helm-values.cainjector.deploymentAnnotations" + }, + "enableServiceLinks": { + "$ref": "#/$defs/helm-values.cainjector.enableServiceLinks" + }, + "enabled": { + "$ref": "#/$defs/helm-values.cainjector.enabled" + }, + "extraArgs": { + "$ref": "#/$defs/helm-values.cainjector.extraArgs" + }, + "extraEnv": { + "$ref": "#/$defs/helm-values.cainjector.extraEnv" + }, + "featureGates": { + "$ref": "#/$defs/helm-values.cainjector.featureGates" + }, + "image": { + "$ref": "#/$defs/helm-values.cainjector.image" + }, + "nodeSelector": { + "$ref": "#/$defs/helm-values.cainjector.nodeSelector" + }, + "podAnnotations": { + "$ref": "#/$defs/helm-values.cainjector.podAnnotations" + }, + "podDisruptionBudget": { + "$ref": "#/$defs/helm-values.cainjector.podDisruptionBudget" + }, + "podLabels": { + "$ref": "#/$defs/helm-values.cainjector.podLabels" + }, + "replicaCount": { + "$ref": "#/$defs/helm-values.cainjector.replicaCount" + }, + "resources": { + "$ref": "#/$defs/helm-values.cainjector.resources" + }, + "securityContext": { + "$ref": "#/$defs/helm-values.cainjector.securityContext" + }, + "serviceAccount": { + "$ref": "#/$defs/helm-values.cainjector.serviceAccount" + }, + "serviceAnnotations": { + "$ref": "#/$defs/helm-values.cainjector.serviceAnnotations" + }, + "serviceLabels": { + "$ref": "#/$defs/helm-values.cainjector.serviceLabels" + }, + "strategy": { + "$ref": "#/$defs/helm-values.cainjector.strategy" + }, + "tolerations": { + "$ref": "#/$defs/helm-values.cainjector.tolerations" + }, + "topologySpreadConstraints": { + "$ref": "#/$defs/helm-values.cainjector.topologySpreadConstraints" + }, + "volumeMounts": { + "$ref": "#/$defs/helm-values.cainjector.volumeMounts" + }, + "volumes": { + "$ref": "#/$defs/helm-values.cainjector.volumes" + } + }, + "type": "object" + }, + "helm-values.cainjector.affinity": { + "default": {}, + "description": "A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core).\n\nFor example:\naffinity:\n nodeAffinity:\n requiredDuringSchedulingIgnoredDuringExecution:\n nodeSelectorTerms:\n - matchExpressions:\n - key: foo.bar.com/role\n operator: In\n values:\n - master", + "type": "object" + }, + "helm-values.cainjector.automountServiceAccountToken": { + "description": "Automounting API credentials for a particular pod.", + "type": "boolean" + }, + "helm-values.cainjector.config": { + "default": {}, + "description": "This is used to configure options for the cainjector pod. It allows setting options that are usually provided via flags.\n\nIf `apiVersion` and `kind` are unspecified they default to the current latest version (currently `cainjector.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself.\n\nFor example:\napiVersion: cainjector.config.cert-manager.io/v1alpha1\nkind: CAInjectorConfiguration\nlogging:\n verbosity: 2\n format: text\nleaderElectionConfig:\n namespace: kube-system\n# Configure the metrics server for TLS\n# See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls\nmetricsTLSConfig:\n dynamic:\n secretNamespace: \"cert-manager\"\n secretName: \"cert-manager-metrics-ca\"\n dnsNames:\n - cert-manager-metrics", + "type": "object" + }, + "helm-values.cainjector.containerSecurityContext": { + "default": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + }, + "readOnlyRootFilesystem": true + }, + "description": "Container Security Context to be set on the cainjector component container. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/).", + "type": "object" + }, + "helm-values.cainjector.deploymentAnnotations": { + "description": "Optional additional annotations to add to the cainjector Deployment.", + "type": "object" + }, + "helm-values.cainjector.enableServiceLinks": { + "default": false, + "description": "enableServiceLinks indicates whether information about services should be injected into the pod's environment variables, matching the syntax of Docker links.", + "type": "boolean" + }, + "helm-values.cainjector.enabled": { + "default": true, + "description": "Create the CA Injector deployment", + "type": "boolean" + }, + "helm-values.cainjector.extraArgs": { + "default": [], + "description": "Additional command line flags to pass to cert-manager cainjector binary. To see all available flags run `docker run quay.io/jetstack/cert-manager-cainjector: --help`.", + "items": {}, + "type": "array" + }, + "helm-values.cainjector.extraEnv": { + "default": [], + "description": "Additional environment variables to pass to cert-manager cainjector binary.\nFor example:\nextraEnv:\n- name: SOME_VAR\n value: 'some value'", + "items": {}, + "type": "array" + }, + "helm-values.cainjector.featureGates": { + "default": "", + "description": "Comma separated list of feature gates that should be enabled on the cainjector pod.", + "type": "string" + }, + "helm-values.cainjector.image": { + "additionalProperties": false, + "properties": { + "digest": { + "$ref": "#/$defs/helm-values.cainjector.image.digest" + }, + "pullPolicy": { + "$ref": "#/$defs/helm-values.cainjector.image.pullPolicy" + }, + "registry": { + "$ref": "#/$defs/helm-values.cainjector.image.registry" + }, + "repository": { + "$ref": "#/$defs/helm-values.cainjector.image.repository" + }, + "tag": { + "$ref": "#/$defs/helm-values.cainjector.image.tag" + } + }, + "type": "object" + }, + "helm-values.cainjector.image.digest": { + "description": "Setting a digest will override any tag.", + "type": "string" + }, + "helm-values.cainjector.image.pullPolicy": { + "default": "IfNotPresent", + "description": "Kubernetes imagePullPolicy on Deployment.", + "type": "string" + }, + "helm-values.cainjector.image.registry": { + "description": "The container registry to pull the cainjector image from.", + "type": "string" + }, + "helm-values.cainjector.image.repository": { + "default": "quay.io/jetstack/cert-manager-cainjector", + "description": "The container image for the cert-manager cainjector", + "type": "string" + }, + "helm-values.cainjector.image.tag": { + "description": "Override the image tag to deploy by setting this variable. If no value is set, the chart's appVersion will be used.", + "type": "string" + }, + "helm-values.cainjector.nodeSelector": { + "default": { + "kubernetes.io/os": "linux" + }, + "description": "The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with matching labels. For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/).\n\nThis default ensures that Pods are only scheduled to Linux nodes. It prevents Pods being scheduled to Windows nodes in a mixed OS cluster.", + "type": "object" + }, + "helm-values.cainjector.podAnnotations": { + "description": "Optional additional annotations to add to the cainjector Pods.", + "type": "object" + }, + "helm-values.cainjector.podDisruptionBudget": { + "additionalProperties": false, + "properties": { + "enabled": { + "$ref": "#/$defs/helm-values.cainjector.podDisruptionBudget.enabled" + }, + "maxUnavailable": { + "$ref": "#/$defs/helm-values.cainjector.podDisruptionBudget.maxUnavailable" + }, + "minAvailable": { + "$ref": "#/$defs/helm-values.cainjector.podDisruptionBudget.minAvailable" + } + }, + "type": "object" + }, + "helm-values.cainjector.podDisruptionBudget.enabled": { + "default": false, + "description": "Enable or disable the PodDisruptionBudget resource.\n\nThis prevents downtime during voluntary disruptions such as during a Node upgrade. For example, the PodDisruptionBudget will block `kubectl drain` if it is used on the Node where the only remaining cert-manager\nPod is currently running.", + "type": "boolean" + }, + "helm-values.cainjector.podDisruptionBudget.maxUnavailable": { + "description": "`maxUnavailable` configures the maximum unavailable pods for disruptions. It can either be set to\nan integer (e.g. 1) or a percentage value (e.g. 25%).\nCannot be used if `minAvailable` is set." + }, + "helm-values.cainjector.podDisruptionBudget.minAvailable": { + "description": "`minAvailable` configures the minimum available pods for disruptions. It can either be set to\nan integer (e.g. 1) or a percentage value (e.g. 25%).\nCannot be used if `maxUnavailable` is set." + }, + "helm-values.cainjector.podLabels": { + "default": {}, + "description": "Optional additional labels to add to the CA Injector Pods.", + "type": "object" + }, + "helm-values.cainjector.replicaCount": { + "default": 1, + "description": "The number of replicas of the cert-manager cainjector to run.\n\nThe default is 1, but in production set this to 2 or 3 to provide high availability.\n\nIf `replicas > 1`, consider setting `cainjector.podDisruptionBudget.enabled=true`.\n\nNote that cert-manager uses leader election to ensure that there can only be a single instance active at a time.", + "type": "number" + }, + "helm-values.cainjector.resources": { + "default": {}, + "description": "Resources to provide to the cert-manager cainjector pod.\n\nFor example:\nrequests:\n cpu: 10m\n memory: 32Mi\nFor more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/).", + "type": "object" + }, + "helm-values.cainjector.securityContext": { + "default": { + "runAsNonRoot": true, + "seccompProfile": { + "type": "RuntimeDefault" + } + }, + "description": "Pod Security Context to be set on the cainjector component Pod. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/).", + "type": "object" + }, + "helm-values.cainjector.serviceAccount": { + "additionalProperties": false, + "properties": { + "annotations": { + "$ref": "#/$defs/helm-values.cainjector.serviceAccount.annotations" + }, + "automountServiceAccountToken": { + "$ref": "#/$defs/helm-values.cainjector.serviceAccount.automountServiceAccountToken" + }, + "create": { + "$ref": "#/$defs/helm-values.cainjector.serviceAccount.create" + }, + "labels": { + "$ref": "#/$defs/helm-values.cainjector.serviceAccount.labels" + }, + "name": { + "$ref": "#/$defs/helm-values.cainjector.serviceAccount.name" + } + }, + "type": "object" + }, + "helm-values.cainjector.serviceAccount.annotations": { + "description": "Optional additional annotations to add to the cainjector's Service Account.", + "type": "object" + }, + "helm-values.cainjector.serviceAccount.automountServiceAccountToken": { + "default": true, + "description": "Automount API credentials for a Service Account.", + "type": "boolean" + }, + "helm-values.cainjector.serviceAccount.create": { + "default": true, + "description": "Specifies whether a service account should be created.", + "type": "boolean" + }, + "helm-values.cainjector.serviceAccount.labels": { + "description": "Optional additional labels to add to the cainjector's Service Account.", + "type": "object" + }, + "helm-values.cainjector.serviceAccount.name": { + "description": "The name of the service account to use.\nIf not set and create is true, a name is generated using the fullname template", + "type": "string" + }, + "helm-values.cainjector.serviceAnnotations": { + "description": "Optional additional annotations to add to the cainjector metrics Service.", + "type": "object" + }, + "helm-values.cainjector.serviceLabels": { + "default": {}, + "description": "Optional additional labels to add to the CA Injector metrics Service.", + "type": "object" + }, + "helm-values.cainjector.strategy": { + "default": {}, + "description": "Deployment update strategy for the cert-manager cainjector deployment. For more information, see the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy).\n\nFor example:\nstrategy:\n type: RollingUpdate\n rollingUpdate:\n maxSurge: 0\n maxUnavailable: 1", + "type": "object" + }, + "helm-values.cainjector.tolerations": { + "default": [], + "description": "A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core).\n\nFor example:\ntolerations:\n- key: foo.bar.com/role\n operator: Equal\n value: master\n effect: NoSchedule", + "items": {}, + "type": "array" + }, + "helm-values.cainjector.topologySpreadConstraints": { + "default": [], + "description": "A list of Kubernetes TopologySpreadConstraints, if required. For more information, see [Topology spread constraint v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#topologyspreadconstraint-v1-core).\n\nFor example:\ntopologySpreadConstraints:\n- maxSkew: 2\n topologyKey: topology.kubernetes.io/zone\n whenUnsatisfiable: ScheduleAnyway\n labelSelector:\n matchLabels:\n app.kubernetes.io/instance: cert-manager\n app.kubernetes.io/component: controller", + "items": {}, + "type": "array" + }, + "helm-values.cainjector.volumeMounts": { + "default": [], + "description": "Additional volume mounts to add to the cert-manager controller container.", + "items": {}, + "type": "array" + }, + "helm-values.cainjector.volumes": { + "default": [], + "description": "Additional volumes to add to the cert-manager controller pod.", + "items": {}, + "type": "array" + }, + "helm-values.clusterResourceNamespace": { + "default": "", + "description": "Override the namespace used to store DNS provider credentials etc. for ClusterIssuer resources. By default, the same namespace as cert-manager is deployed within is used. This namespace will not be automatically created by the Helm chart.", + "type": "string" + }, + "helm-values.config": { + "default": {}, + "description": "This property is used to configure options for the controller pod. This allows setting options that would usually be provided using flags.\n\nIf `apiVersion` and `kind` are unspecified they default to the current latest version (currently `controller.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself.\n\nFor example:\nconfig:\n apiVersion: controller.config.cert-manager.io/v1alpha1\n kind: ControllerConfiguration\n logging:\n verbosity: 2\n format: text\n leaderElectionConfig:\n namespace: kube-system\n kubernetesAPIQPS: 9000\n kubernetesAPIBurst: 9000\n numberOfConcurrentWorkers: 200\n featureGates:\n AdditionalCertificateOutputFormats: true\n DisallowInsecureCSRUsageDefinition: true\n ExperimentalCertificateSigningRequestControllers: true\n ExperimentalGatewayAPISupport: true\n LiteralCertificateSubject: true\n SecretsFilteredCaching: true\n ServerSideApply: true\n StableCertificateRequestName: true\n UseCertificateRequestBasicConstraints: true\n ValidateCAA: true\n # Configure the metrics server for TLS\n # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls\n metricsTLSConfig:\n dynamic:\n secretNamespace: \"cert-manager\"\n secretName: \"cert-manager-metrics-ca\"\n dnsNames:\n - cert-manager-metrics", + "type": "object" + }, + "helm-values.containerSecurityContext": { + "default": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + }, + "readOnlyRootFilesystem": true + }, + "description": "Container Security Context to be set on the controller component container. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/).", + "type": "object" + }, + "helm-values.crds": { + "additionalProperties": false, + "properties": { + "enabled": { + "$ref": "#/$defs/helm-values.crds.enabled" + }, + "keep": { + "$ref": "#/$defs/helm-values.crds.keep" + } + }, + "type": "object" + }, + "helm-values.crds.enabled": { + "default": false, + "description": "This option decides if the CRDs should be installed as part of the Helm installation.", + "type": "boolean" + }, + "helm-values.crds.keep": { + "default": true, + "description": "This option makes it so that the \"helm.sh/resource-policy\": keep annotation is added to the CRD. This will prevent Helm from uninstalling the CRD when the Helm release is uninstalled. WARNING: when the CRDs are removed, all cert-manager custom resources\n(Certificates, Issuers, ...) will be removed too by the garbage collector.", + "type": "boolean" + }, + "helm-values.creator": { + "default": "helm", + "description": "Field used by our release pipeline to produce the static manifests. The field defaults to \"helm\" but is set to \"static\" when we render the static YAML manifests.", + "type": "string" + }, + "helm-values.deploymentAnnotations": { + "description": "Optional additional annotations to add to the controller Deployment.", + "type": "object" + }, + "helm-values.disableAutoApproval": { + "default": false, + "description": "Option to disable cert-manager's build-in auto-approver. The auto-approver approves all CertificateRequests that reference issuers matching the 'approveSignerNames' option. This 'disableAutoApproval' option is useful when you want to make all approval decisions using a different approver (like approver-policy - https://github.com/cert-manager/approver-policy).", + "type": "boolean" + }, + "helm-values.dns01RecursiveNameservers": { + "default": "", + "description": "A comma-separated string with the host and port of the recursive nameservers cert-manager should query.", + "type": "string" + }, + "helm-values.dns01RecursiveNameserversOnly": { + "default": false, + "description": "Forces cert-manager to use only the recursive nameservers for verification. Enabling this option could cause the DNS01 self check to take longer owing to caching performed by the recursive nameservers.", + "type": "boolean" + }, + "helm-values.enableCertificateOwnerRef": { + "default": false, + "description": "When this flag is enabled, secrets will be automatically removed when the certificate resource is deleted.", + "type": "boolean" + }, + "helm-values.enableServiceLinks": { + "default": false, + "description": "enableServiceLinks indicates whether information about services should be injected into the pod's environment variables, matching the syntax of Docker links.", + "type": "boolean" + }, + "helm-values.enabled": { + "default": true, + "description": "Field that can be used as a condition when cert-manager is a dependency. This definition is only here as a placeholder such that it is included in the json schema. See https://helm.sh/docs/chart_best_practices/dependencies/#conditions-and-tags for more info.", + "type": "boolean" + }, + "helm-values.extraArgs": { + "default": [], + "description": "Additional command line flags to pass to cert-manager controller binary. To see all available flags run `docker run quay.io/jetstack/cert-manager-controller: --help`.\n\nUse this flag to enable or disable arbitrary controllers. For example, to disable the CertificateRequests approver.\n\nFor example:\nextraArgs:\n - --controllers=*,-certificaterequests-approver", + "items": {}, + "type": "array" + }, + "helm-values.extraEnv": { + "default": [], + "description": "Additional environment variables to pass to cert-manager controller binary.\nFor example:\nextraEnv:\n- name: SOME_VAR\n value: 'some value'", + "items": {}, + "type": "array" + }, + "helm-values.extraObjects": { + "default": [], + "description": "Create dynamic manifests via values.\n\nFor example:\nextraObjects:\n - |\n apiVersion: v1\n kind: ConfigMap\n metadata:\n name: '{{ template \"cert-manager.fullname\" . }}-extra-configmap'", + "items": {}, + "type": "array" + }, + "helm-values.featureGates": { + "default": "", + "description": "A comma-separated list of feature gates that should be enabled on the controller pod.", + "type": "string" + }, + "helm-values.fullnameOverride": { + "description": "Override the \"cert-manager.fullname\" value. This value is used as part of most of the names of the resources created by this Helm chart.", + "type": "string" + }, + "helm-values.global": { + "description": "Global values shared across all (sub)charts", + "properties": { + "commonLabels": { + "$ref": "#/$defs/helm-values.global.commonLabels" + }, + "imagePullSecrets": { + "$ref": "#/$defs/helm-values.global.imagePullSecrets" + }, + "leaderElection": { + "$ref": "#/$defs/helm-values.global.leaderElection" + }, + "logLevel": { + "$ref": "#/$defs/helm-values.global.logLevel" + }, + "podSecurityPolicy": { + "$ref": "#/$defs/helm-values.global.podSecurityPolicy" + }, + "priorityClassName": { + "$ref": "#/$defs/helm-values.global.priorityClassName" + }, + "rbac": { + "$ref": "#/$defs/helm-values.global.rbac" + }, + "revisionHistoryLimit": { + "$ref": "#/$defs/helm-values.global.revisionHistoryLimit" + } + }, + "type": "object" + }, + "helm-values.global.commonLabels": { + "default": {}, + "description": "Labels to apply to all resources.\nPlease note that this does not add labels to the resources created dynamically by the controllers. For these resources, you have to add the labels in the template in the cert-manager custom resource: For example, podTemplate/ ingressTemplate in ACMEChallengeSolverHTTP01Ingress. For more information, see the [cert-manager documentation](https://cert-manager.io/docs/reference/api-docs/#acme.cert-manager.io/v1.ACMEChallengeSolverHTTP01Ingress).\nFor example, secretTemplate in CertificateSpec\nFor more information, see the [cert-manager documentation](https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificateSpec).", + "type": "object" + }, + "helm-values.global.imagePullSecrets": { + "default": [], + "description": "Reference to one or more secrets to be used when pulling images. For more information, see [Pull an Image from a Private Registry](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/).\n\nFor example:\nimagePullSecrets:\n - name: \"image-pull-secret\"", + "items": {}, + "type": "array" + }, + "helm-values.global.leaderElection": { + "properties": { + "leaseDuration": { + "$ref": "#/$defs/helm-values.global.leaderElection.leaseDuration" + }, + "namespace": { + "$ref": "#/$defs/helm-values.global.leaderElection.namespace" + }, + "renewDeadline": { + "$ref": "#/$defs/helm-values.global.leaderElection.renewDeadline" + }, + "retryPeriod": { + "$ref": "#/$defs/helm-values.global.leaderElection.retryPeriod" + } + }, + "type": "object" + }, + "helm-values.global.leaderElection.leaseDuration": { + "description": "The duration that non-leader candidates will wait after observing a leadership renewal until attempting to acquire leadership of a led but unrenewed leader slot. This is effectively the maximum duration that a leader can be stopped before it is replaced by another candidate.", + "type": "string" + }, + "helm-values.global.leaderElection.namespace": { + "default": "kube-system", + "description": "Override the namespace used for the leader election lease.", + "type": "string" + }, + "helm-values.global.leaderElection.renewDeadline": { + "description": "The interval between attempts by the acting master to renew a leadership slot before it stops leading. This must be less than or equal to the lease duration.", + "type": "string" + }, + "helm-values.global.leaderElection.retryPeriod": { + "description": "The duration the clients should wait between attempting acquisition and renewal of a leadership.", + "type": "string" + }, + "helm-values.global.logLevel": { + "default": 2, + "description": "Set the verbosity of cert-manager. A range of 0 - 6, with 6 being the most verbose.", + "type": "number" + }, + "helm-values.global.podSecurityPolicy": { + "properties": { + "enabled": { + "$ref": "#/$defs/helm-values.global.podSecurityPolicy.enabled" + }, + "useAppArmor": { + "$ref": "#/$defs/helm-values.global.podSecurityPolicy.useAppArmor" + } + }, + "type": "object" + }, + "helm-values.global.podSecurityPolicy.enabled": { + "default": false, + "description": "Create PodSecurityPolicy for cert-manager.\n\nNote that PodSecurityPolicy was deprecated in Kubernetes 1.21 and removed in Kubernetes 1.25.", + "type": "boolean" + }, + "helm-values.global.podSecurityPolicy.useAppArmor": { + "default": true, + "description": "Configure the PodSecurityPolicy to use AppArmor.", + "type": "boolean" + }, + "helm-values.global.priorityClassName": { + "default": "", + "description": "The optional priority class to be used for the cert-manager pods.", + "type": "string" + }, + "helm-values.global.rbac": { + "properties": { + "aggregateClusterRoles": { + "$ref": "#/$defs/helm-values.global.rbac.aggregateClusterRoles" + }, + "create": { + "$ref": "#/$defs/helm-values.global.rbac.create" + } + }, + "type": "object" + }, + "helm-values.global.rbac.aggregateClusterRoles": { + "default": true, + "description": "Aggregate ClusterRoles to Kubernetes default user-facing roles. For more information, see [User-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles)", + "type": "boolean" + }, + "helm-values.global.rbac.create": { + "default": true, + "description": "Create required ClusterRoles and ClusterRoleBindings for cert-manager.", + "type": "boolean" + }, + "helm-values.global.revisionHistoryLimit": { + "description": "The number of old ReplicaSets to retain to allow rollback (if not set, the default Kubernetes value is set to 10).", + "type": "number" + }, + "helm-values.hostAliases": { + "default": [], + "description": "Optional hostAliases for cert-manager-controller pods. May be useful when performing ACME DNS-01 self checks.", + "items": {}, + "type": "array" + }, + "helm-values.http_proxy": { + "description": "Configures the HTTP_PROXY environment variable where a HTTP proxy is required.", + "type": "string" + }, + "helm-values.https_proxy": { + "description": "Configures the HTTPS_PROXY environment variable where a HTTP proxy is required.", + "type": "string" + }, + "helm-values.image": { + "additionalProperties": false, + "properties": { + "digest": { + "$ref": "#/$defs/helm-values.image.digest" + }, + "pullPolicy": { + "$ref": "#/$defs/helm-values.image.pullPolicy" + }, + "registry": { + "$ref": "#/$defs/helm-values.image.registry" + }, + "repository": { + "$ref": "#/$defs/helm-values.image.repository" + }, + "tag": { + "$ref": "#/$defs/helm-values.image.tag" + } + }, + "type": "object" + }, + "helm-values.image.digest": { + "description": "Setting a digest will override any tag.", + "type": "string" + }, + "helm-values.image.pullPolicy": { + "default": "IfNotPresent", + "description": "Kubernetes imagePullPolicy on Deployment.", + "type": "string" + }, + "helm-values.image.registry": { + "description": "The container registry to pull the manager image from.", + "type": "string" + }, + "helm-values.image.repository": { + "default": "quay.io/jetstack/cert-manager-controller", + "description": "The container image for the cert-manager controller.", + "type": "string" + }, + "helm-values.image.tag": { + "description": "Override the image tag to deploy by setting this variable. If no value is set, the chart's appVersion is used.", + "type": "string" + }, + "helm-values.ingressShim": { + "additionalProperties": false, + "properties": { + "defaultIssuerGroup": { + "$ref": "#/$defs/helm-values.ingressShim.defaultIssuerGroup" + }, + "defaultIssuerKind": { + "$ref": "#/$defs/helm-values.ingressShim.defaultIssuerKind" + }, + "defaultIssuerName": { + "$ref": "#/$defs/helm-values.ingressShim.defaultIssuerName" + } + }, + "type": "object" + }, + "helm-values.ingressShim.defaultIssuerGroup": { + "description": "Optional default issuer group to use for ingress resources.", + "type": "string" + }, + "helm-values.ingressShim.defaultIssuerKind": { + "description": "Optional default issuer kind to use for ingress resources.", + "type": "string" + }, + "helm-values.ingressShim.defaultIssuerName": { + "description": "Optional default issuer to use for ingress resources.", + "type": "string" + }, + "helm-values.installCRDs": { + "default": false, + "description": "This option is equivalent to setting crds.enabled=true and crds.keep=true. Deprecated: use crds.enabled and crds.keep instead.", + "type": "boolean" + }, + "helm-values.livenessProbe": { + "default": { + "enabled": true, + "failureThreshold": 8, + "initialDelaySeconds": 10, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 15 + }, + "description": "LivenessProbe settings for the controller container of the controller Pod.\n\nThis is enabled by default, in order to enable the clock-skew liveness probe that restarts the controller in case of a skew between the system clock and the monotonic clock. LivenessProbe durations and thresholds are based on those used for the Kubernetes controller-manager. For more information see the following on the\n[Kubernetes GitHub repository](https://github.com/kubernetes/kubernetes/blob/806b30170c61a38fedd54cc9ede4cd6275a1ad3b/cmd/kubeadm/app/util/staticpod/utils.go#L241-L245)", + "type": "object" + }, + "helm-values.maxConcurrentChallenges": { + "default": 60, + "description": "The maximum number of challenges that can be scheduled as 'processing' at once.", + "type": "number" + }, + "helm-values.nameOverride": { + "description": "Override the \"cert-manager.name\" value, which is used to annotate some of the resources that are created by this Chart (using \"app.kubernetes.io/name\"). NOTE: There are some inconsistencies in the Helm chart when it comes to these annotations (some resources use eg. \"cainjector.name\" which resolves to the value \"cainjector\").", + "type": "string" + }, + "helm-values.namespace": { + "default": "", + "description": "This namespace allows you to define where the services are installed into. If not set then they use the namespace of the release. This is helpful when installing cert manager as a chart dependency (sub chart).", + "type": "string" + }, + "helm-values.no_proxy": { + "description": "Configures the NO_PROXY environment variable where a HTTP proxy is required, but certain domains should be excluded.", + "type": "string" + }, + "helm-values.nodeSelector": { + "default": { + "kubernetes.io/os": "linux" + }, + "description": "The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with matching labels. For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/).\n\nThis default ensures that Pods are only scheduled to Linux nodes. It prevents Pods being scheduled to Windows nodes in a mixed OS cluster.", + "type": "object" + }, + "helm-values.podAnnotations": { + "description": "Optional additional annotations to add to the controller Pods.", + "type": "object" + }, + "helm-values.podDisruptionBudget": { + "additionalProperties": false, + "properties": { + "enabled": { + "$ref": "#/$defs/helm-values.podDisruptionBudget.enabled" + }, + "maxUnavailable": { + "$ref": "#/$defs/helm-values.podDisruptionBudget.maxUnavailable" + }, + "minAvailable": { + "$ref": "#/$defs/helm-values.podDisruptionBudget.minAvailable" + } + }, + "type": "object" + }, + "helm-values.podDisruptionBudget.enabled": { + "default": false, + "description": "Enable or disable the PodDisruptionBudget resource.\n\nThis prevents downtime during voluntary disruptions such as during a Node upgrade. For example, the PodDisruptionBudget will block `kubectl drain` if it is used on the Node where the only remaining cert-manager\nPod is currently running.", + "type": "boolean" + }, + "helm-values.podDisruptionBudget.maxUnavailable": { + "description": "This configures the maximum unavailable pods for disruptions. It can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%). it cannot be used if `minAvailable` is set." + }, + "helm-values.podDisruptionBudget.minAvailable": { + "description": "This configures the minimum available pods for disruptions. It can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%).\nIt cannot be used if `maxUnavailable` is set." + }, + "helm-values.podDnsConfig": { + "description": "Pod DNS configuration. The podDnsConfig field is optional and can work with any podDnsPolicy settings. However, when a Pod's dnsPolicy is set to \"None\", the dnsConfig field has to be specified. For more information, see [Pod's DNS Config](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-dns-config).", + "type": "object" + }, + "helm-values.podDnsPolicy": { + "description": "Pod DNS policy.\nFor more information, see [Pod's DNS Policy](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy).", + "type": "string" + }, + "helm-values.podLabels": { + "default": {}, + "description": "Optional additional labels to add to the controller Pods.", + "type": "object" + }, + "helm-values.prometheus": { + "additionalProperties": false, + "properties": { + "enabled": { + "$ref": "#/$defs/helm-values.prometheus.enabled" + }, + "podmonitor": { + "$ref": "#/$defs/helm-values.prometheus.podmonitor" + }, + "servicemonitor": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor" + } + }, + "type": "object" + }, + "helm-values.prometheus.enabled": { + "default": true, + "description": "Enable Prometheus monitoring for the cert-manager controller and webhook. If you use the Prometheus Operator, set prometheus.podmonitor.enabled or prometheus.servicemonitor.enabled, to create a PodMonitor or a\nServiceMonitor resource.\nOtherwise, 'prometheus.io' annotations are added to the cert-manager and cert-manager-webhook Deployments. Note that you can not enable both PodMonitor and ServiceMonitor as they are mutually exclusive. Enabling both will result in an error.", + "type": "boolean" + }, + "helm-values.prometheus.podmonitor": { + "additionalProperties": false, + "properties": { + "annotations": { + "$ref": "#/$defs/helm-values.prometheus.podmonitor.annotations" + }, + "enabled": { + "$ref": "#/$defs/helm-values.prometheus.podmonitor.enabled" + }, + "endpointAdditionalProperties": { + "$ref": "#/$defs/helm-values.prometheus.podmonitor.endpointAdditionalProperties" + }, + "honorLabels": { + "$ref": "#/$defs/helm-values.prometheus.podmonitor.honorLabels" + }, + "interval": { + "$ref": "#/$defs/helm-values.prometheus.podmonitor.interval" + }, + "labels": { + "$ref": "#/$defs/helm-values.prometheus.podmonitor.labels" + }, + "namespace": { + "$ref": "#/$defs/helm-values.prometheus.podmonitor.namespace" + }, + "path": { + "$ref": "#/$defs/helm-values.prometheus.podmonitor.path" + }, + "prometheusInstance": { + "$ref": "#/$defs/helm-values.prometheus.podmonitor.prometheusInstance" + }, + "scrapeTimeout": { + "$ref": "#/$defs/helm-values.prometheus.podmonitor.scrapeTimeout" + } + }, + "type": "object" + }, + "helm-values.prometheus.podmonitor.annotations": { + "default": {}, + "description": "Additional annotations to add to the PodMonitor.", + "type": "object" + }, + "helm-values.prometheus.podmonitor.enabled": { + "default": false, + "description": "Create a PodMonitor to add cert-manager to Prometheus.", + "type": "boolean" + }, + "helm-values.prometheus.podmonitor.endpointAdditionalProperties": { + "default": {}, + "description": "EndpointAdditionalProperties allows setting additional properties on the endpoint such as relabelings, metricRelabelings etc.\n\nFor example:\nendpointAdditionalProperties:\n relabelings:\n - action: replace\n sourceLabels:\n - __meta_kubernetes_pod_node_name\n targetLabel: instance\n # Configure the PodMonitor for TLS connections\n # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls\n scheme: https\n tlsConfig:\n serverName: cert-manager-metrics\n ca:\n secret:\n name: cert-manager-metrics-ca\n key: \"tls.crt\"", + "type": "object" + }, + "helm-values.prometheus.podmonitor.honorLabels": { + "default": false, + "description": "Keep labels from scraped data, overriding server-side labels.", + "type": "boolean" + }, + "helm-values.prometheus.podmonitor.interval": { + "default": "60s", + "description": "The interval to scrape metrics.", + "type": "string" + }, + "helm-values.prometheus.podmonitor.labels": { + "default": {}, + "description": "Additional labels to add to the PodMonitor.", + "type": "object" + }, + "helm-values.prometheus.podmonitor.namespace": { + "description": "The namespace that the pod monitor should live in, defaults to the cert-manager namespace.", + "type": "string" + }, + "helm-values.prometheus.podmonitor.path": { + "default": "/metrics", + "description": "The path to scrape for metrics.", + "type": "string" + }, + "helm-values.prometheus.podmonitor.prometheusInstance": { + "default": "default", + "description": "Specifies the `prometheus` label on the created PodMonitor. This is used when different Prometheus instances have label selectors matching different PodMonitors.", + "type": "string" + }, + "helm-values.prometheus.podmonitor.scrapeTimeout": { + "default": "30s", + "description": "The timeout before a metrics scrape fails.", + "type": "string" + }, + "helm-values.prometheus.servicemonitor": { + "additionalProperties": false, + "properties": { + "annotations": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor.annotations" + }, + "enabled": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor.enabled" + }, + "endpointAdditionalProperties": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor.endpointAdditionalProperties" + }, + "honorLabels": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor.honorLabels" + }, + "interval": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor.interval" + }, + "labels": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor.labels" + }, + "namespace": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor.namespace" + }, + "path": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor.path" + }, + "prometheusInstance": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor.prometheusInstance" + }, + "scrapeTimeout": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor.scrapeTimeout" + }, + "targetPort": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor.targetPort" + } + }, + "type": "object" + }, + "helm-values.prometheus.servicemonitor.annotations": { + "default": {}, + "description": "Additional annotations to add to the ServiceMonitor.", + "type": "object" + }, + "helm-values.prometheus.servicemonitor.enabled": { + "default": false, + "description": "Create a ServiceMonitor to add cert-manager to Prometheus.", + "type": "boolean" + }, + "helm-values.prometheus.servicemonitor.endpointAdditionalProperties": { + "default": {}, + "description": "EndpointAdditionalProperties allows setting additional properties on the endpoint such as relabelings, metricRelabelings etc.\n\nFor example:\nendpointAdditionalProperties:\n relabelings:\n - action: replace\n sourceLabels:\n - __meta_kubernetes_pod_node_name\n targetLabel: instance", + "type": "object" + }, + "helm-values.prometheus.servicemonitor.honorLabels": { + "default": false, + "description": "Keep labels from scraped data, overriding server-side labels.", + "type": "boolean" + }, + "helm-values.prometheus.servicemonitor.interval": { + "default": "60s", + "description": "The interval to scrape metrics.", + "type": "string" + }, + "helm-values.prometheus.servicemonitor.labels": { + "default": {}, + "description": "Additional labels to add to the ServiceMonitor.", + "type": "object" + }, + "helm-values.prometheus.servicemonitor.namespace": { + "description": "The namespace that the service monitor should live in, defaults to the cert-manager namespace.", + "type": "string" + }, + "helm-values.prometheus.servicemonitor.path": { + "default": "/metrics", + "description": "The path to scrape for metrics.", + "type": "string" + }, + "helm-values.prometheus.servicemonitor.prometheusInstance": { + "default": "default", + "description": "Specifies the `prometheus` label on the created ServiceMonitor. This is used when different Prometheus instances have label selectors matching different ServiceMonitors.", + "type": "string" + }, + "helm-values.prometheus.servicemonitor.scrapeTimeout": { + "default": "30s", + "description": "The timeout before a metrics scrape fails.", + "type": "string" + }, + "helm-values.prometheus.servicemonitor.targetPort": { + "default": 9402, + "description": "The target port to set on the ServiceMonitor. This must match the port that the cert-manager controller is listening on for metrics.", + "type": "number" + }, + "helm-values.replicaCount": { + "default": 1, + "description": "The number of replicas of the cert-manager controller to run.\n\nThe default is 1, but in production set this to 2 or 3 to provide high availability.\n\nIf `replicas > 1`, consider setting `podDisruptionBudget.enabled=true`.\n\nNote that cert-manager uses leader election to ensure that there can only be a single instance active at a time.", + "type": "number" + }, + "helm-values.resources": { + "default": {}, + "description": "Resources to provide to the cert-manager controller pod.\n\nFor example:\nrequests:\n cpu: 10m\n memory: 32Mi\nFor more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/).", + "type": "object" + }, + "helm-values.securityContext": { + "default": { + "runAsNonRoot": true, + "seccompProfile": { + "type": "RuntimeDefault" + } + }, + "description": "Pod Security Context.\nFor more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/).", + "type": "object" + }, + "helm-values.serviceAccount": { + "additionalProperties": false, + "properties": { + "annotations": { + "$ref": "#/$defs/helm-values.serviceAccount.annotations" + }, + "automountServiceAccountToken": { + "$ref": "#/$defs/helm-values.serviceAccount.automountServiceAccountToken" + }, + "create": { + "$ref": "#/$defs/helm-values.serviceAccount.create" + }, + "labels": { + "$ref": "#/$defs/helm-values.serviceAccount.labels" + }, + "name": { + "$ref": "#/$defs/helm-values.serviceAccount.name" + } + }, + "type": "object" + }, + "helm-values.serviceAccount.annotations": { + "description": "Optional additional annotations to add to the controller's Service Account.", + "type": "object" + }, + "helm-values.serviceAccount.automountServiceAccountToken": { + "default": true, + "description": "Automount API credentials for a Service Account.", + "type": "boolean" + }, + "helm-values.serviceAccount.create": { + "default": true, + "description": "Specifies whether a service account should be created.", + "type": "boolean" + }, + "helm-values.serviceAccount.labels": { + "description": "Optional additional labels to add to the controller's Service Account.", + "type": "object" + }, + "helm-values.serviceAccount.name": { + "description": "The name of the service account to use.\nIf not set and create is true, a name is generated using the fullname template.", + "type": "string" + }, + "helm-values.serviceAnnotations": { + "description": "Optional annotations to add to the controller Service.", + "type": "object" + }, + "helm-values.serviceIPFamilies": { + "description": "Optionally set the IP families for the controller Service that should be supported, in the order in which they should be applied to ClusterIP. Can be IPv4 and/or IPv6.", + "items": {}, + "type": "array" + }, + "helm-values.serviceIPFamilyPolicy": { + "description": "Optionally set the IP family policy for the controller Service to configure dual-stack; see [Configure dual-stack](https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services).", + "type": "string" + }, + "helm-values.serviceLabels": { + "description": "Optional additional labels to add to the controller Service.", + "type": "object" + }, + "helm-values.startupapicheck": { + "additionalProperties": false, + "properties": { + "affinity": { + "$ref": "#/$defs/helm-values.startupapicheck.affinity" + }, + "automountServiceAccountToken": { + "$ref": "#/$defs/helm-values.startupapicheck.automountServiceAccountToken" + }, + "backoffLimit": { + "$ref": "#/$defs/helm-values.startupapicheck.backoffLimit" + }, + "containerSecurityContext": { + "$ref": "#/$defs/helm-values.startupapicheck.containerSecurityContext" + }, + "enableServiceLinks": { + "$ref": "#/$defs/helm-values.startupapicheck.enableServiceLinks" + }, + "enabled": { + "$ref": "#/$defs/helm-values.startupapicheck.enabled" + }, + "extraArgs": { + "$ref": "#/$defs/helm-values.startupapicheck.extraArgs" + }, + "extraEnv": { + "$ref": "#/$defs/helm-values.startupapicheck.extraEnv" + }, + "image": { + "$ref": "#/$defs/helm-values.startupapicheck.image" + }, + "jobAnnotations": { + "$ref": "#/$defs/helm-values.startupapicheck.jobAnnotations" + }, + "nodeSelector": { + "$ref": "#/$defs/helm-values.startupapicheck.nodeSelector" + }, + "podAnnotations": { + "$ref": "#/$defs/helm-values.startupapicheck.podAnnotations" + }, + "podLabels": { + "$ref": "#/$defs/helm-values.startupapicheck.podLabels" + }, + "rbac": { + "$ref": "#/$defs/helm-values.startupapicheck.rbac" + }, + "resources": { + "$ref": "#/$defs/helm-values.startupapicheck.resources" + }, + "securityContext": { + "$ref": "#/$defs/helm-values.startupapicheck.securityContext" + }, + "serviceAccount": { + "$ref": "#/$defs/helm-values.startupapicheck.serviceAccount" + }, + "timeout": { + "$ref": "#/$defs/helm-values.startupapicheck.timeout" + }, + "tolerations": { + "$ref": "#/$defs/helm-values.startupapicheck.tolerations" + }, + "volumeMounts": { + "$ref": "#/$defs/helm-values.startupapicheck.volumeMounts" + }, + "volumes": { + "$ref": "#/$defs/helm-values.startupapicheck.volumes" + } + }, + "type": "object" + }, + "helm-values.startupapicheck.affinity": { + "default": {}, + "description": "A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core).\nFor example:\naffinity:\n nodeAffinity:\n requiredDuringSchedulingIgnoredDuringExecution:\n nodeSelectorTerms:\n - matchExpressions:\n - key: foo.bar.com/role\n operator: In\n values:\n - master", + "type": "object" + }, + "helm-values.startupapicheck.automountServiceAccountToken": { + "description": "Automounting API credentials for a particular pod.", + "type": "boolean" + }, + "helm-values.startupapicheck.backoffLimit": { + "default": 4, + "description": "Job backoffLimit", + "type": "number" + }, + "helm-values.startupapicheck.containerSecurityContext": { + "default": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + }, + "readOnlyRootFilesystem": true + }, + "description": "Container Security Context to be set on the controller component container. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/).", + "type": "object" + }, + "helm-values.startupapicheck.enableServiceLinks": { + "default": false, + "description": "enableServiceLinks indicates whether information about services should be injected into pod's environment variables, matching the syntax of Docker links.", + "type": "boolean" + }, + "helm-values.startupapicheck.enabled": { + "default": true, + "description": "Enables the startup api check.", + "type": "boolean" + }, + "helm-values.startupapicheck.extraArgs": { + "default": [ + "-v" + ], + "description": "Additional command line flags to pass to startupapicheck binary. To see all available flags run `docker run quay.io/jetstack/cert-manager-startupapicheck: --help`.\n\nVerbose logging is enabled by default so that if startupapicheck fails, you can know what exactly caused the failure. Verbose logs include details of the webhook URL, IP address and TCP connect errors for example.", + "items": {}, + "type": "array" + }, + "helm-values.startupapicheck.extraEnv": { + "default": [], + "description": "Additional environment variables to pass to cert-manager startupapicheck binary.\nFor example:\nextraEnv:\n- name: SOME_VAR\n value: 'some value'", + "items": {}, + "type": "array" + }, + "helm-values.startupapicheck.image": { + "additionalProperties": false, + "properties": { + "digest": { + "$ref": "#/$defs/helm-values.startupapicheck.image.digest" + }, + "pullPolicy": { + "$ref": "#/$defs/helm-values.startupapicheck.image.pullPolicy" + }, + "registry": { + "$ref": "#/$defs/helm-values.startupapicheck.image.registry" + }, + "repository": { + "$ref": "#/$defs/helm-values.startupapicheck.image.repository" + }, + "tag": { + "$ref": "#/$defs/helm-values.startupapicheck.image.tag" + } + }, + "type": "object" + }, + "helm-values.startupapicheck.image.digest": { + "description": "Setting a digest will override any tag.", + "type": "string" + }, + "helm-values.startupapicheck.image.pullPolicy": { + "default": "IfNotPresent", + "description": "Kubernetes imagePullPolicy on Deployment.", + "type": "string" + }, + "helm-values.startupapicheck.image.registry": { + "description": "The container registry to pull the startupapicheck image from.", + "type": "string" + }, + "helm-values.startupapicheck.image.repository": { + "default": "quay.io/jetstack/cert-manager-startupapicheck", + "description": "The container image for the cert-manager startupapicheck.", + "type": "string" + }, + "helm-values.startupapicheck.image.tag": { + "description": "Override the image tag to deploy by setting this variable. If no value is set, the chart's appVersion is used.", + "type": "string" + }, + "helm-values.startupapicheck.jobAnnotations": { + "default": { + "helm.sh/hook": "post-install", + "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded", + "helm.sh/hook-weight": "1" + }, + "description": "Optional additional annotations to add to the startupapicheck Job.", + "type": "object" + }, + "helm-values.startupapicheck.nodeSelector": { + "default": { + "kubernetes.io/os": "linux" + }, + "description": "The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with matching labels. For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/).\n\nThis default ensures that Pods are only scheduled to Linux nodes. It prevents Pods being scheduled to Windows nodes in a mixed OS cluster.", + "type": "object" + }, + "helm-values.startupapicheck.podAnnotations": { + "description": "Optional additional annotations to add to the startupapicheck Pods.", + "type": "object" + }, + "helm-values.startupapicheck.podLabels": { + "default": {}, + "description": "Optional additional labels to add to the startupapicheck Pods.", + "type": "object" + }, + "helm-values.startupapicheck.rbac": { + "additionalProperties": false, + "properties": { + "annotations": { + "$ref": "#/$defs/helm-values.startupapicheck.rbac.annotations" + } + }, + "type": "object" + }, + "helm-values.startupapicheck.rbac.annotations": { + "default": { + "helm.sh/hook": "post-install", + "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded", + "helm.sh/hook-weight": "-5" + }, + "description": "annotations for the startup API Check job RBAC and PSP resources.", + "type": "object" + }, + "helm-values.startupapicheck.resources": { + "default": {}, + "description": "Resources to provide to the cert-manager controller pod.\n\nFor example:\nrequests:\n cpu: 10m\n memory: 32Mi\nFor more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/).", + "type": "object" + }, + "helm-values.startupapicheck.securityContext": { + "default": { + "runAsNonRoot": true, + "seccompProfile": { + "type": "RuntimeDefault" + } + }, + "description": "Pod Security Context to be set on the startupapicheck component Pod. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/).", + "type": "object" + }, + "helm-values.startupapicheck.serviceAccount": { + "additionalProperties": false, + "properties": { + "annotations": { + "$ref": "#/$defs/helm-values.startupapicheck.serviceAccount.annotations" + }, + "automountServiceAccountToken": { + "$ref": "#/$defs/helm-values.startupapicheck.serviceAccount.automountServiceAccountToken" + }, + "create": { + "$ref": "#/$defs/helm-values.startupapicheck.serviceAccount.create" + }, + "labels": { + "$ref": "#/$defs/helm-values.startupapicheck.serviceAccount.labels" + }, + "name": { + "$ref": "#/$defs/helm-values.startupapicheck.serviceAccount.name" + } + }, + "type": "object" + }, + "helm-values.startupapicheck.serviceAccount.annotations": { + "default": { + "helm.sh/hook": "post-install", + "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded", + "helm.sh/hook-weight": "-5" + }, + "description": "Optional additional annotations to add to the Job's Service Account.", + "type": "object" + }, + "helm-values.startupapicheck.serviceAccount.automountServiceAccountToken": { + "default": true, + "description": "Automount API credentials for a Service Account.", + "type": "boolean" + }, + "helm-values.startupapicheck.serviceAccount.create": { + "default": true, + "description": "Specifies whether a service account should be created.", + "type": "boolean" + }, + "helm-values.startupapicheck.serviceAccount.labels": { + "description": "Optional additional labels to add to the startupapicheck's Service Account.", + "type": "object" + }, + "helm-values.startupapicheck.serviceAccount.name": { + "description": "The name of the service account to use.\nIf not set and create is true, a name is generated using the fullname template.", + "type": "string" + }, + "helm-values.startupapicheck.timeout": { + "default": "1m", + "description": "Timeout for 'kubectl check api' command.", + "type": "string" + }, + "helm-values.startupapicheck.tolerations": { + "default": [], + "description": "A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core).\n\nFor example:\ntolerations:\n- key: foo.bar.com/role\n operator: Equal\n value: master\n effect: NoSchedule", + "items": {}, + "type": "array" + }, + "helm-values.startupapicheck.volumeMounts": { + "default": [], + "description": "Additional volume mounts to add to the cert-manager controller container.", + "items": {}, + "type": "array" + }, + "helm-values.startupapicheck.volumes": { + "default": [], + "description": "Additional volumes to add to the cert-manager controller pod.", + "items": {}, + "type": "array" + }, + "helm-values.strategy": { + "default": {}, + "description": "Deployment update strategy for the cert-manager controller deployment. For more information, see the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy).\n\nFor example:\nstrategy:\n type: RollingUpdate\n rollingUpdate:\n maxSurge: 0\n maxUnavailable: 1", + "type": "object" + }, + "helm-values.tolerations": { + "default": [], + "description": "A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core).\n\nFor example:\ntolerations:\n- key: foo.bar.com/role\n operator: Equal\n value: master\n effect: NoSchedule", + "items": {}, + "type": "array" + }, + "helm-values.topologySpreadConstraints": { + "default": [], + "description": "A list of Kubernetes TopologySpreadConstraints, if required. For more information, see [Topology spread constraint v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#topologyspreadconstraint-v1-core\n\nFor example:\ntopologySpreadConstraints:\n- maxSkew: 2\n topologyKey: topology.kubernetes.io/zone\n whenUnsatisfiable: ScheduleAnyway\n labelSelector:\n matchLabels:\n app.kubernetes.io/instance: cert-manager\n app.kubernetes.io/component: controller", + "items": {}, + "type": "array" + }, + "helm-values.volumeMounts": { + "default": [], + "description": "Additional volume mounts to add to the cert-manager controller container.", + "items": {}, + "type": "array" + }, + "helm-values.volumes": { + "default": [], + "description": "Additional volumes to add to the cert-manager controller pod.", + "items": {}, + "type": "array" + }, + "helm-values.webhook": { + "additionalProperties": false, + "properties": { + "affinity": { + "$ref": "#/$defs/helm-values.webhook.affinity" + }, + "automountServiceAccountToken": { + "$ref": "#/$defs/helm-values.webhook.automountServiceAccountToken" + }, + "config": { + "$ref": "#/$defs/helm-values.webhook.config" + }, + "containerSecurityContext": { + "$ref": "#/$defs/helm-values.webhook.containerSecurityContext" + }, + "deploymentAnnotations": { + "$ref": "#/$defs/helm-values.webhook.deploymentAnnotations" + }, + "enableServiceLinks": { + "$ref": "#/$defs/helm-values.webhook.enableServiceLinks" + }, + "extraArgs": { + "$ref": "#/$defs/helm-values.webhook.extraArgs" + }, + "extraEnv": { + "$ref": "#/$defs/helm-values.webhook.extraEnv" + }, + "featureGates": { + "$ref": "#/$defs/helm-values.webhook.featureGates" + }, + "hostNetwork": { + "$ref": "#/$defs/helm-values.webhook.hostNetwork" + }, + "image": { + "$ref": "#/$defs/helm-values.webhook.image" + }, + "livenessProbe": { + "$ref": "#/$defs/helm-values.webhook.livenessProbe" + }, + "loadBalancerIP": { + "$ref": "#/$defs/helm-values.webhook.loadBalancerIP" + }, + "mutatingWebhookConfiguration": { + "$ref": "#/$defs/helm-values.webhook.mutatingWebhookConfiguration" + }, + "mutatingWebhookConfigurationAnnotations": { + "$ref": "#/$defs/helm-values.webhook.mutatingWebhookConfigurationAnnotations" + }, + "networkPolicy": { + "$ref": "#/$defs/helm-values.webhook.networkPolicy" + }, + "nodeSelector": { + "$ref": "#/$defs/helm-values.webhook.nodeSelector" + }, + "podAnnotations": { + "$ref": "#/$defs/helm-values.webhook.podAnnotations" + }, + "podDisruptionBudget": { + "$ref": "#/$defs/helm-values.webhook.podDisruptionBudget" + }, + "podLabels": { + "$ref": "#/$defs/helm-values.webhook.podLabels" + }, + "readinessProbe": { + "$ref": "#/$defs/helm-values.webhook.readinessProbe" + }, + "replicaCount": { + "$ref": "#/$defs/helm-values.webhook.replicaCount" + }, + "resources": { + "$ref": "#/$defs/helm-values.webhook.resources" + }, + "securePort": { + "$ref": "#/$defs/helm-values.webhook.securePort" + }, + "securityContext": { + "$ref": "#/$defs/helm-values.webhook.securityContext" + }, + "serviceAccount": { + "$ref": "#/$defs/helm-values.webhook.serviceAccount" + }, + "serviceAnnotations": { + "$ref": "#/$defs/helm-values.webhook.serviceAnnotations" + }, + "serviceIPFamilies": { + "$ref": "#/$defs/helm-values.webhook.serviceIPFamilies" + }, + "serviceIPFamilyPolicy": { + "$ref": "#/$defs/helm-values.webhook.serviceIPFamilyPolicy" + }, + "serviceLabels": { + "$ref": "#/$defs/helm-values.webhook.serviceLabels" + }, + "serviceType": { + "$ref": "#/$defs/helm-values.webhook.serviceType" + }, + "strategy": { + "$ref": "#/$defs/helm-values.webhook.strategy" + }, + "timeoutSeconds": { + "$ref": "#/$defs/helm-values.webhook.timeoutSeconds" + }, + "tolerations": { + "$ref": "#/$defs/helm-values.webhook.tolerations" + }, + "topologySpreadConstraints": { + "$ref": "#/$defs/helm-values.webhook.topologySpreadConstraints" + }, + "url": { + "$ref": "#/$defs/helm-values.webhook.url" + }, + "validatingWebhookConfiguration": { + "$ref": "#/$defs/helm-values.webhook.validatingWebhookConfiguration" + }, + "validatingWebhookConfigurationAnnotations": { + "$ref": "#/$defs/helm-values.webhook.validatingWebhookConfigurationAnnotations" + }, + "volumeMounts": { + "$ref": "#/$defs/helm-values.webhook.volumeMounts" + }, + "volumes": { + "$ref": "#/$defs/helm-values.webhook.volumes" + } + }, + "type": "object" + }, + "helm-values.webhook.affinity": { + "default": {}, + "description": "A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core).\n\nFor example:\naffinity:\n nodeAffinity:\n requiredDuringSchedulingIgnoredDuringExecution:\n nodeSelectorTerms:\n - matchExpressions:\n - key: foo.bar.com/role\n operator: In\n values:\n - master", + "type": "object" + }, + "helm-values.webhook.automountServiceAccountToken": { + "description": "Automounting API credentials for a particular pod.", + "type": "boolean" + }, + "helm-values.webhook.config": { + "default": {}, + "description": "This is used to configure options for the webhook pod. This allows setting options that would usually be provided using flags.\n\nIf `apiVersion` and `kind` are unspecified they default to the current latest version (currently `webhook.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself.\n\nFor example:\napiVersion: webhook.config.cert-manager.io/v1alpha1\nkind: WebhookConfiguration\n# The port that the webhook listens on for requests.\n# In GKE private clusters, by default Kubernetes apiservers are allowed to\n# talk to the cluster nodes only on 443 and 10250. Configuring\n# securePort: 10250 therefore will work out-of-the-box without needing to add firewall\n# rules or requiring NET_BIND_SERVICE capabilities to bind port numbers < 1000.\n# This should be uncommented and set as a default by the chart once\n# the apiVersion of WebhookConfiguration graduates beyond v1alpha1.\nsecurePort: 10250\n# Configure the metrics server for TLS\n# See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls\nmetricsTLSConfig:\n dynamic:\n secretNamespace: \"cert-manager\"\n secretName: \"cert-manager-metrics-ca\"\n dnsNames:\n - cert-manager-metrics", + "type": "object" + }, + "helm-values.webhook.containerSecurityContext": { + "default": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + }, + "readOnlyRootFilesystem": true + }, + "description": "Container Security Context to be set on the webhook component container. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/).", + "type": "object" + }, + "helm-values.webhook.deploymentAnnotations": { + "description": "Optional additional annotations to add to the webhook Deployment.", + "type": "object" + }, + "helm-values.webhook.enableServiceLinks": { + "default": false, + "description": "enableServiceLinks indicates whether information about services should be injected into the pod's environment variables, matching the syntax of Docker links.", + "type": "boolean" + }, + "helm-values.webhook.extraArgs": { + "default": [], + "description": "Additional command line flags to pass to cert-manager webhook binary. To see all available flags run `docker run quay.io/jetstack/cert-manager-webhook: --help`.", + "items": {}, + "type": "array" + }, + "helm-values.webhook.extraEnv": { + "default": [], + "description": "Additional environment variables to pass to cert-manager webhook binary.\nFor example:\nextraEnv:\n- name: SOME_VAR\n value: 'some value'", + "items": {}, + "type": "array" + }, + "helm-values.webhook.featureGates": { + "default": "", + "description": "Comma separated list of feature gates that should be enabled on the webhook pod.", + "type": "string" + }, + "helm-values.webhook.hostNetwork": { + "default": false, + "description": "Specifies if the webhook should be started in hostNetwork mode.\n\nRequired for use in some managed kubernetes clusters (such as AWS EKS) with custom. CNI (such as calico), because control-plane managed by AWS cannot communicate with pods' IP CIDR and admission webhooks are not working\n\nSince the default port for the webhook conflicts with kubelet on the host network, `webhook.securePort` should be changed to an available port if running in hostNetwork mode.", + "type": "boolean" + }, + "helm-values.webhook.image": { + "additionalProperties": false, + "properties": { + "digest": { + "$ref": "#/$defs/helm-values.webhook.image.digest" + }, + "pullPolicy": { + "$ref": "#/$defs/helm-values.webhook.image.pullPolicy" + }, + "registry": { + "$ref": "#/$defs/helm-values.webhook.image.registry" + }, + "repository": { + "$ref": "#/$defs/helm-values.webhook.image.repository" + }, + "tag": { + "$ref": "#/$defs/helm-values.webhook.image.tag" + } + }, + "type": "object" + }, + "helm-values.webhook.image.digest": { + "description": "Setting a digest will override any tag", + "type": "string" + }, + "helm-values.webhook.image.pullPolicy": { + "default": "IfNotPresent", + "description": "Kubernetes imagePullPolicy on Deployment.", + "type": "string" + }, + "helm-values.webhook.image.registry": { + "description": "The container registry to pull the webhook image from.", + "type": "string" + }, + "helm-values.webhook.image.repository": { + "default": "quay.io/jetstack/cert-manager-webhook", + "description": "The container image for the cert-manager webhook", + "type": "string" + }, + "helm-values.webhook.image.tag": { + "description": "Override the image tag to deploy by setting this variable. If no value is set, the chart's appVersion will be used.", + "type": "string" + }, + "helm-values.webhook.livenessProbe": { + "default": { + "failureThreshold": 3, + "initialDelaySeconds": 60, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "description": "Liveness probe values.\nFor more information, see [Container probes](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes).", + "type": "object" + }, + "helm-values.webhook.loadBalancerIP": { + "description": "Specify the load balancer IP for the created service.", + "type": "string" + }, + "helm-values.webhook.mutatingWebhookConfiguration": { + "additionalProperties": false, + "properties": { + "namespaceSelector": { + "$ref": "#/$defs/helm-values.webhook.mutatingWebhookConfiguration.namespaceSelector" + } + }, + "type": "object" + }, + "helm-values.webhook.mutatingWebhookConfiguration.namespaceSelector": { + "default": {}, + "description": "Configure spec.namespaceSelector for mutating webhooks.", + "type": "object" + }, + "helm-values.webhook.mutatingWebhookConfigurationAnnotations": { + "description": "Optional additional annotations to add to the webhook MutatingWebhookConfiguration.", + "type": "object" + }, + "helm-values.webhook.networkPolicy": { + "additionalProperties": false, + "properties": { + "egress": { + "$ref": "#/$defs/helm-values.webhook.networkPolicy.egress" + }, + "enabled": { + "$ref": "#/$defs/helm-values.webhook.networkPolicy.enabled" + }, + "ingress": { + "$ref": "#/$defs/helm-values.webhook.networkPolicy.ingress" + } + }, + "type": "object" + }, + "helm-values.webhook.networkPolicy.egress": { + "default": [ + { + "ports": [ + { + "port": 80, + "protocol": "TCP" + }, + { + "port": 443, + "protocol": "TCP" + }, + { + "port": 53, + "protocol": "TCP" + }, + { + "port": 53, + "protocol": "UDP" + }, + { + "port": 6443, + "protocol": "TCP" + } + ], + "to": [ + { + "ipBlock": { + "cidr": "0.0.0.0/0" + } + } + ] + } + ], + "description": "Egress rule for the webhook network policy. By default, it allows all outbound traffic to ports 80 and 443, as well as DNS ports.", + "items": {}, + "type": "array" + }, + "helm-values.webhook.networkPolicy.enabled": { + "default": false, + "description": "Create network policies for the webhooks.", + "type": "boolean" + }, + "helm-values.webhook.networkPolicy.ingress": { + "default": [ + { + "from": [ + { + "ipBlock": { + "cidr": "0.0.0.0/0" + } + } + ] + } + ], + "description": "Ingress rule for the webhook network policy. By default, it allows all inbound traffic.", + "items": {}, + "type": "array" + }, + "helm-values.webhook.nodeSelector": { + "default": { + "kubernetes.io/os": "linux" + }, + "description": "The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with matching labels. For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/).\n\nThis default ensures that Pods are only scheduled to Linux nodes. It prevents Pods being scheduled to Windows nodes in a mixed OS cluster.", + "type": "object" + }, + "helm-values.webhook.podAnnotations": { + "description": "Optional additional annotations to add to the webhook Pods.", + "type": "object" + }, + "helm-values.webhook.podDisruptionBudget": { + "additionalProperties": false, + "properties": { + "enabled": { + "$ref": "#/$defs/helm-values.webhook.podDisruptionBudget.enabled" + }, + "maxUnavailable": { + "$ref": "#/$defs/helm-values.webhook.podDisruptionBudget.maxUnavailable" + }, + "minAvailable": { + "$ref": "#/$defs/helm-values.webhook.podDisruptionBudget.minAvailable" + } + }, + "type": "object" + }, + "helm-values.webhook.podDisruptionBudget.enabled": { + "default": false, + "description": "Enable or disable the PodDisruptionBudget resource.\n\nThis prevents downtime during voluntary disruptions such as during a Node upgrade. For example, the PodDisruptionBudget will block `kubectl drain` if it is used on the Node where the only remaining cert-manager\nPod is currently running.", + "type": "boolean" + }, + "helm-values.webhook.podDisruptionBudget.maxUnavailable": { + "description": "This property configures the maximum unavailable pods for disruptions. Can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%).\nIt cannot be used if `minAvailable` is set." + }, + "helm-values.webhook.podDisruptionBudget.minAvailable": { + "description": "This property configures the minimum available pods for disruptions. Can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%).\nIt cannot be used if `maxUnavailable` is set." + }, + "helm-values.webhook.podLabels": { + "default": {}, + "description": "Optional additional labels to add to the Webhook Pods.", + "type": "object" + }, + "helm-values.webhook.readinessProbe": { + "default": { + "failureThreshold": 3, + "initialDelaySeconds": 5, + "periodSeconds": 5, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "description": "Readiness probe values.\nFor more information, see [Container probes](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes).", + "type": "object" + }, + "helm-values.webhook.replicaCount": { + "default": 1, + "description": "Number of replicas of the cert-manager webhook to run.\n\nThe default is 1, but in production set this to 2 or 3 to provide high availability.\n\nIf `replicas > 1`, consider setting `webhook.podDisruptionBudget.enabled=true`.", + "type": "number" + }, + "helm-values.webhook.resources": { + "default": {}, + "description": "Resources to provide to the cert-manager webhook pod.\n\nFor example:\nrequests:\n cpu: 10m\n memory: 32Mi\nFor more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/).", + "type": "object" + }, + "helm-values.webhook.securePort": { + "default": 10250, + "description": "The port that the webhook listens on for requests. In GKE private clusters, by default Kubernetes apiservers are allowed to talk to the cluster nodes only on 443 and 10250. Configuring securePort: 10250, therefore will work out-of-the-box without needing to add firewall rules or requiring NET_BIND_SERVICE capabilities to bind port numbers <1000.", + "type": "number" + }, + "helm-values.webhook.securityContext": { + "default": { + "runAsNonRoot": true, + "seccompProfile": { + "type": "RuntimeDefault" + } + }, + "description": "Pod Security Context to be set on the webhook component Pod. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/).", + "type": "object" + }, + "helm-values.webhook.serviceAccount": { + "additionalProperties": false, + "properties": { + "annotations": { + "$ref": "#/$defs/helm-values.webhook.serviceAccount.annotations" + }, + "automountServiceAccountToken": { + "$ref": "#/$defs/helm-values.webhook.serviceAccount.automountServiceAccountToken" + }, + "create": { + "$ref": "#/$defs/helm-values.webhook.serviceAccount.create" + }, + "labels": { + "$ref": "#/$defs/helm-values.webhook.serviceAccount.labels" + }, + "name": { + "$ref": "#/$defs/helm-values.webhook.serviceAccount.name" + } + }, + "type": "object" + }, + "helm-values.webhook.serviceAccount.annotations": { + "description": "Optional additional annotations to add to the webhook's Service Account.", + "type": "object" + }, + "helm-values.webhook.serviceAccount.automountServiceAccountToken": { + "default": true, + "description": "Automount API credentials for a Service Account.", + "type": "boolean" + }, + "helm-values.webhook.serviceAccount.create": { + "default": true, + "description": "Specifies whether a service account should be created.", + "type": "boolean" + }, + "helm-values.webhook.serviceAccount.labels": { + "description": "Optional additional labels to add to the webhook's Service Account.", + "type": "object" + }, + "helm-values.webhook.serviceAccount.name": { + "description": "The name of the service account to use.\nIf not set and create is true, a name is generated using the fullname template.", + "type": "string" + }, + "helm-values.webhook.serviceAnnotations": { + "description": "Optional additional annotations to add to the webhook Service.", + "type": "object" + }, + "helm-values.webhook.serviceIPFamilies": { + "default": [], + "description": "Optionally set the IP families for the controller Service that should be supported, in the order in which they should be applied to ClusterIP. Can be IPv4 and/or IPv6.", + "items": {}, + "type": "array" + }, + "helm-values.webhook.serviceIPFamilyPolicy": { + "default": "", + "description": "Optionally set the IP family policy for the controller Service to configure dual-stack; see [Configure dual-stack](https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services).", + "type": "string" + }, + "helm-values.webhook.serviceLabels": { + "default": {}, + "description": "Optional additional labels to add to the Webhook Service.", + "type": "object" + }, + "helm-values.webhook.serviceType": { + "default": "ClusterIP", + "description": "Specifies how the service should be handled. Useful if you want to expose the webhook outside of the cluster. In some cases, the control plane cannot reach internal services.", + "type": "string" + }, + "helm-values.webhook.strategy": { + "default": {}, + "description": "The update strategy for the cert-manager webhook deployment. For more information, see the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy)\n\nFor example:\nstrategy:\n type: RollingUpdate\n rollingUpdate:\n maxSurge: 0\n maxUnavailable: 1", + "type": "object" + }, + "helm-values.webhook.timeoutSeconds": { + "default": 30, + "description": "The number of seconds the API server should wait for the webhook to respond before treating the call as a failure. The value must be between 1 and 30 seconds. For more information, see\n[Validating webhook configuration v1](https://kubernetes.io/docs/reference/kubernetes-api/extend-resources/validating-webhook-configuration-v1/).\n\nThe default is set to the maximum value of 30 seconds as users sometimes report that the connection between the K8S API server and the cert-manager webhook server times out. If *this* timeout is reached, the error message will be \"context deadline exceeded\", which doesn't help the user diagnose what phase of the HTTPS connection timed out. For example, it could be during DNS resolution, TCP connection, TLS negotiation, HTTP negotiation, or slow HTTP response from the webhook server. By setting this timeout to its maximum value the underlying timeout error message has more chance of being returned to the end user.", + "type": "number" + }, + "helm-values.webhook.tolerations": { + "default": [], + "description": "A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core).\n\nFor example:\ntolerations:\n- key: foo.bar.com/role\n operator: Equal\n value: master\n effect: NoSchedule", + "items": {}, + "type": "array" + }, + "helm-values.webhook.topologySpreadConstraints": { + "default": [], + "description": "A list of Kubernetes TopologySpreadConstraints, if required. For more information, see [Topology spread constraint v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#topologyspreadconstraint-v1-core).\n\nFor example:\ntopologySpreadConstraints:\n- maxSkew: 2\n topologyKey: topology.kubernetes.io/zone\n whenUnsatisfiable: ScheduleAnyway\n labelSelector:\n matchLabels:\n app.kubernetes.io/instance: cert-manager\n app.kubernetes.io/component: controller", + "items": {}, + "type": "array" + }, + "helm-values.webhook.url": { + "default": {}, + "description": "Overrides the mutating webhook and validating webhook so they reach the webhook service using the `url` field instead of a service.", + "type": "object" + }, + "helm-values.webhook.validatingWebhookConfiguration": { + "additionalProperties": false, + "properties": { + "namespaceSelector": { + "$ref": "#/$defs/helm-values.webhook.validatingWebhookConfiguration.namespaceSelector" + } + }, + "type": "object" + }, + "helm-values.webhook.validatingWebhookConfiguration.namespaceSelector": { + "default": { + "matchExpressions": [ + { + "key": "cert-manager.io/disable-validation", + "operator": "NotIn", + "values": [ + "true" + ] + } + ] + }, + "description": "Configure spec.namespaceSelector for validating webhooks.", + "type": "object" + }, + "helm-values.webhook.validatingWebhookConfigurationAnnotations": { + "description": "Optional additional annotations to add to the webhook ValidatingWebhookConfiguration.", + "type": "object" + }, + "helm-values.webhook.volumeMounts": { + "default": [], + "description": "Additional volume mounts to add to the cert-manager controller container.", + "items": {}, + "type": "array" + }, + "helm-values.webhook.volumes": { + "default": [], + "description": "Additional volumes to add to the cert-manager controller pod.", + "items": {}, + "type": "array" + } + }, + "$ref": "#/$defs/helm-values", + "$schema": "http://json-schema.org/draft-07/schema#" +} diff --git a/backing-services/cert-manager/values.yaml b/backing-services/cert-manager/values.yaml new file mode 100644 index 0000000..7a1c295 --- /dev/null +++ b/backing-services/cert-manager/values.yaml @@ -0,0 +1,1455 @@ +# +docs:section=Global + +# Default values for cert-manager. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +global: + # Reference to one or more secrets to be used when pulling images. + # For more information, see [Pull an Image from a Private Registry](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/). + # + # For example: + # imagePullSecrets: + # - name: "image-pull-secret" + imagePullSecrets: [] + + # Labels to apply to all resources. + # Please note that this does not add labels to the resources created dynamically by the controllers. + # For these resources, you have to add the labels in the template in the cert-manager custom resource: + # For example, podTemplate/ ingressTemplate in ACMEChallengeSolverHTTP01Ingress + # For more information, see the [cert-manager documentation](https://cert-manager.io/docs/reference/api-docs/#acme.cert-manager.io/v1.ACMEChallengeSolverHTTP01Ingress). + # For example, secretTemplate in CertificateSpec + # For more information, see the [cert-manager documentation](https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificateSpec). + commonLabels: {} + + # The number of old ReplicaSets to retain to allow rollback (if not set, the default Kubernetes value is set to 10). + # +docs:property + # revisionHistoryLimit: 1 + + # The optional priority class to be used for the cert-manager pods. + priorityClassName: "" + + rbac: + # Create required ClusterRoles and ClusterRoleBindings for cert-manager. + create: true + # Aggregate ClusterRoles to Kubernetes default user-facing roles. For more information, see [User-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) + aggregateClusterRoles: true + + podSecurityPolicy: + # Create PodSecurityPolicy for cert-manager. + # + # Note that PodSecurityPolicy was deprecated in Kubernetes 1.21 and removed in Kubernetes 1.25. + enabled: false + # Configure the PodSecurityPolicy to use AppArmor. + useAppArmor: true + + # Set the verbosity of cert-manager. A range of 0 - 6, with 6 being the most verbose. + logLevel: 2 + + leaderElection: + # Override the namespace used for the leader election lease. + namespace: "kube-system" + + # The duration that non-leader candidates will wait after observing a + # leadership renewal until attempting to acquire leadership of a led but + # unrenewed leader slot. This is effectively the maximum duration that a + # leader can be stopped before it is replaced by another candidate. + # +docs:property + # leaseDuration: 60s + + # The interval between attempts by the acting master to renew a leadership + # slot before it stops leading. This must be less than or equal to the + # lease duration. + # +docs:property + # renewDeadline: 40s + + # The duration the clients should wait between attempting acquisition and + # renewal of a leadership. + # +docs:property + # retryPeriod: 15s + +# This option is equivalent to setting crds.enabled=true and crds.keep=true. +# Deprecated: use crds.enabled and crds.keep instead. +installCRDs: false + +crds: + # This option decides if the CRDs should be installed + # as part of the Helm installation. + enabled: false + + # This option makes it so that the "helm.sh/resource-policy": keep + # annotation is added to the CRD. This will prevent Helm from uninstalling + # the CRD when the Helm release is uninstalled. + # WARNING: when the CRDs are removed, all cert-manager custom resources + # (Certificates, Issuers, ...) will be removed too by the garbage collector. + keep: true + +# +docs:section=Controller + +# The number of replicas of the cert-manager controller to run. +# +# The default is 1, but in production set this to 2 or 3 to provide high +# availability. +# +# If `replicas > 1`, consider setting `podDisruptionBudget.enabled=true`. +# +# Note that cert-manager uses leader election to ensure that there can +# only be a single instance active at a time. +replicaCount: 1 + +# Deployment update strategy for the cert-manager controller deployment. +# For more information, see the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy). +# +# For example: +# strategy: +# type: RollingUpdate +# rollingUpdate: +# maxSurge: 0 +# maxUnavailable: 1 +strategy: {} + +podDisruptionBudget: + # Enable or disable the PodDisruptionBudget resource. + # + # This prevents downtime during voluntary disruptions such as during a Node upgrade. + # For example, the PodDisruptionBudget will block `kubectl drain` + # if it is used on the Node where the only remaining cert-manager + # Pod is currently running. + enabled: false + + # This configures the minimum available pods for disruptions. It can either be set to + # an integer (e.g. 1) or a percentage value (e.g. 25%). + # It cannot be used if `maxUnavailable` is set. + # +docs:property + # +docs:type=unknown + # minAvailable: 1 + + # This configures the maximum unavailable pods for disruptions. It can either be set to + # an integer (e.g. 1) or a percentage value (e.g. 25%). + # it cannot be used if `minAvailable` is set. + # +docs:property + # +docs:type=unknown + # maxUnavailable: 1 + +# A comma-separated list of feature gates that should be enabled on the +# controller pod. +featureGates: "" + +# The maximum number of challenges that can be scheduled as 'processing' at once. +maxConcurrentChallenges: 60 + +image: + # The container registry to pull the manager image from. + # +docs:property + # registry: quay.io + + # The container image for the cert-manager controller. + # +docs:property + repository: quay.io/jetstack/cert-manager-controller + + # Override the image tag to deploy by setting this variable. + # If no value is set, the chart's appVersion is used. + # +docs:property + # tag: vX.Y.Z + + # Setting a digest will override any tag. + # +docs:property + # digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 + + # Kubernetes imagePullPolicy on Deployment. + pullPolicy: IfNotPresent + +# Override the namespace used to store DNS provider credentials etc. for ClusterIssuer +# resources. By default, the same namespace as cert-manager is deployed within is +# used. This namespace will not be automatically created by the Helm chart. +clusterResourceNamespace: "" + +# This namespace allows you to define where the services are installed into. +# If not set then they use the namespace of the release. +# This is helpful when installing cert manager as a chart dependency (sub chart). +namespace: "" + +# Override the "cert-manager.fullname" value. This value is used as part of +# most of the names of the resources created by this Helm chart. +# +docs:property +# fullnameOverride: "my-cert-manager" + +# Override the "cert-manager.name" value, which is used to annotate some of +# the resources that are created by this Chart (using "app.kubernetes.io/name"). +# NOTE: There are some inconsistencies in the Helm chart when it comes to +# these annotations (some resources use eg. "cainjector.name" which resolves +# to the value "cainjector"). +# +docs:property +# nameOverride: "my-cert-manager" + +serviceAccount: + # Specifies whether a service account should be created. + create: true + + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template. + # +docs:property + # name: "" + + # Optional additional annotations to add to the controller's Service Account. + # +docs:property + # annotations: {} + + # Optional additional labels to add to the controller's Service Account. + # +docs:property + # labels: {} + + # Automount API credentials for a Service Account. + automountServiceAccountToken: true + +# Automounting API credentials for a particular pod. +# +docs:property +# automountServiceAccountToken: true + +# When this flag is enabled, secrets will be automatically removed when the certificate resource is deleted. +enableCertificateOwnerRef: false + +# This property is used to configure options for the controller pod. +# This allows setting options that would usually be provided using flags. +# +# If `apiVersion` and `kind` are unspecified they default to the current latest +# version (currently `controller.config.cert-manager.io/v1alpha1`). You can pin +# the version by specifying the `apiVersion` yourself. +# +# For example: +# config: +# apiVersion: controller.config.cert-manager.io/v1alpha1 +# kind: ControllerConfiguration +# logging: +# verbosity: 2 +# format: text +# leaderElectionConfig: +# namespace: kube-system +# kubernetesAPIQPS: 9000 +# kubernetesAPIBurst: 9000 +# numberOfConcurrentWorkers: 200 +# featureGates: +# AdditionalCertificateOutputFormats: true +# DisallowInsecureCSRUsageDefinition: true +# ExperimentalCertificateSigningRequestControllers: true +# ExperimentalGatewayAPISupport: true +# LiteralCertificateSubject: true +# SecretsFilteredCaching: true +# ServerSideApply: true +# StableCertificateRequestName: true +# UseCertificateRequestBasicConstraints: true +# ValidateCAA: true +# # Configure the metrics server for TLS +# # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls +# metricsTLSConfig: +# dynamic: +# secretNamespace: "cert-manager" +# secretName: "cert-manager-metrics-ca" +# dnsNames: +# - cert-manager-metrics +config: {} + +# Setting Nameservers for DNS01 Self Check. +# For more information, see the [cert-manager documentation](https://cert-manager.io/docs/configuration/acme/dns01/#setting-nameservers-for-dns01-self-check). + +# A comma-separated string with the host and port of the recursive nameservers cert-manager should query. +dns01RecursiveNameservers: "" + +# Forces cert-manager to use only the recursive nameservers for verification. +# Enabling this option could cause the DNS01 self check to take longer owing to caching performed by the recursive nameservers. +dns01RecursiveNameserversOnly: false + +# Option to disable cert-manager's build-in auto-approver. The auto-approver +# approves all CertificateRequests that reference issuers matching the 'approveSignerNames' +# option. This 'disableAutoApproval' option is useful when you want to make all approval decisions +# using a different approver (like approver-policy - https://github.com/cert-manager/approver-policy). +disableAutoApproval: false + +# List of signer names that cert-manager will approve by default. CertificateRequests +# referencing these signer names will be auto-approved by cert-manager. Defaults to just +# approving the cert-manager.io Issuer and ClusterIssuer issuers. When set to an empty +# array, ALL issuers will be auto-approved by cert-manager. To disable the auto-approval, +# because eg. you are using approver-policy, you can enable 'disableAutoApproval'. +# ref: https://cert-manager.io/docs/concepts/certificaterequest/#approval +# +docs:property +approveSignerNames: +- issuers.cert-manager.io/* +- clusterissuers.cert-manager.io/* + +# Additional command line flags to pass to cert-manager controller binary. +# To see all available flags run `docker run quay.io/jetstack/cert-manager-controller: --help`. +# +# Use this flag to enable or disable arbitrary controllers. For example, to disable the CertificateRequests approver. +# +# For example: +# extraArgs: +# - --controllers=*,-certificaterequests-approver +extraArgs: [] + +# Additional environment variables to pass to cert-manager controller binary. +# For example: +# extraEnv: +# - name: SOME_VAR +# value: 'some value' +extraEnv: [] + +# Resources to provide to the cert-manager controller pod. +# +# For example: +# requests: +# cpu: 10m +# memory: 32Mi +# +# For more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). +resources: {} + +# Pod Security Context. +# For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). +# +docs:property +securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + +# Container Security Context to be set on the controller component container. +# For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). +# +docs:property +containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + +# Additional volumes to add to the cert-manager controller pod. +volumes: [] + +# Additional volume mounts to add to the cert-manager controller container. +volumeMounts: [] + +# Optional additional annotations to add to the controller Deployment. +# +docs:property +# deploymentAnnotations: {} + +# Optional additional annotations to add to the controller Pods. +# +docs:property +# podAnnotations: {} + +# Optional additional labels to add to the controller Pods. +podLabels: {} + +# Optional annotations to add to the controller Service. +# +docs:property +# serviceAnnotations: {} + +# Optional additional labels to add to the controller Service. +# +docs:property +# serviceLabels: {} + +# Optionally set the IP family policy for the controller Service to configure dual-stack; see [Configure dual-stack](https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services). +# +docs:property +# serviceIPFamilyPolicy: "" + +# Optionally set the IP families for the controller Service that should be supported, in the order in which they should be applied to ClusterIP. Can be IPv4 and/or IPv6. +# +docs:property +# serviceIPFamilies: [] + +# Optional DNS settings. These are useful if you have a public and private DNS zone for +# the same domain on Route 53. The following is an example of ensuring +# cert-manager can access an ingress or DNS TXT records at all times. +# Note that this requires Kubernetes 1.10 or `CustomPodDNS` feature gate enabled for +# the cluster to work. + +# Pod DNS policy. +# For more information, see [Pod's DNS Policy](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). +# +docs:property +# podDnsPolicy: "None" + +# Pod DNS configuration. The podDnsConfig field is optional and can work with any podDnsPolicy +# settings. However, when a Pod's dnsPolicy is set to "None", the dnsConfig field has to be specified. +# For more information, see [Pod's DNS Config](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-dns-config). +# +docs:property +# podDnsConfig: +# nameservers: +# - "1.1.1.1" +# - "8.8.8.8" + +# Optional hostAliases for cert-manager-controller pods. May be useful when performing ACME DNS-01 self checks. +hostAliases: [] +# - ip: 127.0.0.1 +# hostnames: +# - foo.local +# - bar.local +# - ip: 10.1.2.3 +# hostnames: +# - foo.remote +# - bar.remote + +# The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with +# matching labels. +# For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). +# +# This default ensures that Pods are only scheduled to Linux nodes. +# It prevents Pods being scheduled to Windows nodes in a mixed OS cluster. +# +docs:property +nodeSelector: + kubernetes.io/os: linux + +# +docs:ignore +ingressShim: {} + + # Optional default issuer to use for ingress resources. + # +docs:property=ingressShim.defaultIssuerName + # defaultIssuerName: "" + + # Optional default issuer kind to use for ingress resources. + # +docs:property=ingressShim.defaultIssuerKind + # defaultIssuerKind: "" + + # Optional default issuer group to use for ingress resources. + # +docs:property=ingressShim.defaultIssuerGroup + # defaultIssuerGroup: "" + +# Use these variables to configure the HTTP_PROXY environment variables. + +# Configures the HTTP_PROXY environment variable where a HTTP proxy is required. +# +docs:property +# http_proxy: "http://proxy:8080" + +# Configures the HTTPS_PROXY environment variable where a HTTP proxy is required. +# +docs:property +# https_proxy: "https://proxy:8080" + +# Configures the NO_PROXY environment variable where a HTTP proxy is required, +# but certain domains should be excluded. +# +docs:property +# no_proxy: 127.0.0.1,localhost + + +# A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core). +# +# For example: +# affinity: +# nodeAffinity: +# requiredDuringSchedulingIgnoredDuringExecution: +# nodeSelectorTerms: +# - matchExpressions: +# - key: foo.bar.com/role +# operator: In +# values: +# - master +affinity: {} + +# A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core). +# +# For example: +# tolerations: +# - key: foo.bar.com/role +# operator: Equal +# value: master +# effect: NoSchedule +tolerations: [] + +# A list of Kubernetes TopologySpreadConstraints, if required. For more information, see [Topology spread constraint v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#topologyspreadconstraint-v1-core +# +# For example: +# topologySpreadConstraints: +# - maxSkew: 2 +# topologyKey: topology.kubernetes.io/zone +# whenUnsatisfiable: ScheduleAnyway +# labelSelector: +# matchLabels: +# app.kubernetes.io/instance: cert-manager +# app.kubernetes.io/component: controller +topologySpreadConstraints: [] + +# LivenessProbe settings for the controller container of the controller Pod. +# +# This is enabled by default, in order to enable the clock-skew liveness probe that +# restarts the controller in case of a skew between the system clock and the monotonic clock. +# LivenessProbe durations and thresholds are based on those used for the Kubernetes +# controller-manager. For more information see the following on the +# [Kubernetes GitHub repository](https://github.com/kubernetes/kubernetes/blob/806b30170c61a38fedd54cc9ede4cd6275a1ad3b/cmd/kubeadm/app/util/staticpod/utils.go#L241-L245) +# +docs:property +livenessProbe: + enabled: true + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 15 + successThreshold: 1 + failureThreshold: 8 + +# enableServiceLinks indicates whether information about services should be +# injected into the pod's environment variables, matching the syntax of Docker +# links. +enableServiceLinks: false + +# +docs:section=Prometheus + +prometheus: + # Enable Prometheus monitoring for the cert-manager controller and webhook. + # If you use the Prometheus Operator, set prometheus.podmonitor.enabled or + # prometheus.servicemonitor.enabled, to create a PodMonitor or a + # ServiceMonitor resource. + # Otherwise, 'prometheus.io' annotations are added to the cert-manager and + # cert-manager-webhook Deployments. + # Note that you can not enable both PodMonitor and ServiceMonitor as they are + # mutually exclusive. Enabling both will result in an error. + enabled: true + + servicemonitor: + # Create a ServiceMonitor to add cert-manager to Prometheus. + enabled: false + + # The namespace that the service monitor should live in, defaults + # to the cert-manager namespace. + # +docs:property + # namespace: cert-manager + + # Specifies the `prometheus` label on the created ServiceMonitor. This is + # used when different Prometheus instances have label selectors matching + # different ServiceMonitors. + prometheusInstance: default + + # The target port to set on the ServiceMonitor. This must match the port that the + # cert-manager controller is listening on for metrics. + targetPort: 9402 + + # The path to scrape for metrics. + path: /metrics + + # The interval to scrape metrics. + interval: 60s + + # The timeout before a metrics scrape fails. + scrapeTimeout: 30s + + # Additional labels to add to the ServiceMonitor. + labels: {} + + # Additional annotations to add to the ServiceMonitor. + annotations: {} + + # Keep labels from scraped data, overriding server-side labels. + honorLabels: false + + # EndpointAdditionalProperties allows setting additional properties on the + # endpoint such as relabelings, metricRelabelings etc. + # + # For example: + # endpointAdditionalProperties: + # relabelings: + # - action: replace + # sourceLabels: + # - __meta_kubernetes_pod_node_name + # targetLabel: instance + # + # +docs:property + endpointAdditionalProperties: {} + + # Note that you can not enable both PodMonitor and ServiceMonitor as they are mutually exclusive. Enabling both will result in an error. + podmonitor: + # Create a PodMonitor to add cert-manager to Prometheus. + enabled: false + + # The namespace that the pod monitor should live in, defaults + # to the cert-manager namespace. + # +docs:property + # namespace: cert-manager + + # Specifies the `prometheus` label on the created PodMonitor. This is + # used when different Prometheus instances have label selectors matching + # different PodMonitors. + prometheusInstance: default + + # The path to scrape for metrics. + path: /metrics + + # The interval to scrape metrics. + interval: 60s + + # The timeout before a metrics scrape fails. + scrapeTimeout: 30s + + # Additional labels to add to the PodMonitor. + labels: {} + + # Additional annotations to add to the PodMonitor. + annotations: {} + + # Keep labels from scraped data, overriding server-side labels. + honorLabels: false + + # EndpointAdditionalProperties allows setting additional properties on the + # endpoint such as relabelings, metricRelabelings etc. + # + # For example: + # endpointAdditionalProperties: + # relabelings: + # - action: replace + # sourceLabels: + # - __meta_kubernetes_pod_node_name + # targetLabel: instance + # # Configure the PodMonitor for TLS connections + # # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls + # scheme: https + # tlsConfig: + # serverName: cert-manager-metrics + # ca: + # secret: + # name: cert-manager-metrics-ca + # key: "tls.crt" + # + # +docs:property + endpointAdditionalProperties: {} + +# +docs:section=Webhook + +webhook: + # Number of replicas of the cert-manager webhook to run. + # + # The default is 1, but in production set this to 2 or 3 to provide high + # availability. + # + # If `replicas > 1`, consider setting `webhook.podDisruptionBudget.enabled=true`. + replicaCount: 1 + + # The number of seconds the API server should wait for the webhook to respond before treating the call as a failure. + # The value must be between 1 and 30 seconds. For more information, see + # [Validating webhook configuration v1](https://kubernetes.io/docs/reference/kubernetes-api/extend-resources/validating-webhook-configuration-v1/). + # + # The default is set to the maximum value of 30 seconds as + # users sometimes report that the connection between the K8S API server and + # the cert-manager webhook server times out. + # If *this* timeout is reached, the error message will be "context deadline exceeded", + # which doesn't help the user diagnose what phase of the HTTPS connection timed out. + # For example, it could be during DNS resolution, TCP connection, TLS + # negotiation, HTTP negotiation, or slow HTTP response from the webhook + # server. + # By setting this timeout to its maximum value the underlying timeout error + # message has more chance of being returned to the end user. + timeoutSeconds: 30 + + # This is used to configure options for the webhook pod. + # This allows setting options that would usually be provided using flags. + # + # If `apiVersion` and `kind` are unspecified they default to the current latest + # version (currently `webhook.config.cert-manager.io/v1alpha1`). You can pin + # the version by specifying the `apiVersion` yourself. + # + # For example: + # apiVersion: webhook.config.cert-manager.io/v1alpha1 + # kind: WebhookConfiguration + # # The port that the webhook listens on for requests. + # # In GKE private clusters, by default Kubernetes apiservers are allowed to + # # talk to the cluster nodes only on 443 and 10250. Configuring + # # securePort: 10250 therefore will work out-of-the-box without needing to add firewall + # # rules or requiring NET_BIND_SERVICE capabilities to bind port numbers < 1000. + # # This should be uncommented and set as a default by the chart once + # # the apiVersion of WebhookConfiguration graduates beyond v1alpha1. + # securePort: 10250 + # # Configure the metrics server for TLS + # # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls + # metricsTLSConfig: + # dynamic: + # secretNamespace: "cert-manager" + # secretName: "cert-manager-metrics-ca" + # dnsNames: + # - cert-manager-metrics + config: {} + + # The update strategy for the cert-manager webhook deployment. + # For more information, see the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy) + # + # For example: + # strategy: + # type: RollingUpdate + # rollingUpdate: + # maxSurge: 0 + # maxUnavailable: 1 + strategy: {} + + # Pod Security Context to be set on the webhook component Pod. + # For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + # +docs:property + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + + # Container Security Context to be set on the webhook component container. + # For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + # +docs:property + containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + + podDisruptionBudget: + # Enable or disable the PodDisruptionBudget resource. + # + # This prevents downtime during voluntary disruptions such as during a Node upgrade. + # For example, the PodDisruptionBudget will block `kubectl drain` + # if it is used on the Node where the only remaining cert-manager + # Pod is currently running. + enabled: false + + # This property configures the minimum available pods for disruptions. Can either be set to + # an integer (e.g. 1) or a percentage value (e.g. 25%). + # It cannot be used if `maxUnavailable` is set. + # +docs:property + # +docs:type=unknown + # minAvailable: 1 + + # This property configures the maximum unavailable pods for disruptions. Can either be set to + # an integer (e.g. 1) or a percentage value (e.g. 25%). + # It cannot be used if `minAvailable` is set. + # +docs:property + # +docs:type=unknown + # maxUnavailable: 1 + + # Optional additional annotations to add to the webhook Deployment. + # +docs:property + # deploymentAnnotations: {} + + # Optional additional annotations to add to the webhook Pods. + # +docs:property + # podAnnotations: {} + + # Optional additional annotations to add to the webhook Service. + # +docs:property + # serviceAnnotations: {} + + # Optional additional annotations to add to the webhook MutatingWebhookConfiguration. + # +docs:property + # mutatingWebhookConfigurationAnnotations: {} + + # Optional additional annotations to add to the webhook ValidatingWebhookConfiguration. + # +docs:property + # validatingWebhookConfigurationAnnotations: {} + + validatingWebhookConfiguration: + # Configure spec.namespaceSelector for validating webhooks. + # +docs:property + namespaceSelector: + matchExpressions: + - key: "cert-manager.io/disable-validation" + operator: "NotIn" + values: + - "true" + + mutatingWebhookConfiguration: + # Configure spec.namespaceSelector for mutating webhooks. + # +docs:property + namespaceSelector: {} + # matchLabels: + # key: value + # matchExpressions: + # - key: kubernetes.io/metadata.name + # operator: NotIn + # values: + # - kube-system + + + # Additional command line flags to pass to cert-manager webhook binary. + # To see all available flags run `docker run quay.io/jetstack/cert-manager-webhook: --help`. + extraArgs: [] + # Path to a file containing a WebhookConfiguration object used to configure the webhook. + # - --config= + + # Additional environment variables to pass to cert-manager webhook binary. + # For example: + # extraEnv: + # - name: SOME_VAR + # value: 'some value' + extraEnv: [] + + # Comma separated list of feature gates that should be enabled on the + # webhook pod. + featureGates: "" + + # Resources to provide to the cert-manager webhook pod. + # + # For example: + # requests: + # cpu: 10m + # memory: 32Mi + # + # For more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). + resources: {} + + # Liveness probe values. + # For more information, see [Container probes](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes). + # + # +docs:property + livenessProbe: + failureThreshold: 3 + initialDelaySeconds: 60 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + + # Readiness probe values. + # For more information, see [Container probes](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes). + # + # +docs:property + readinessProbe: + failureThreshold: 3 + initialDelaySeconds: 5 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + + # The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with + # matching labels. + # For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). + # + # This default ensures that Pods are only scheduled to Linux nodes. + # It prevents Pods being scheduled to Windows nodes in a mixed OS cluster. + # +docs:property + nodeSelector: + kubernetes.io/os: linux + + # A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core). + # + # For example: + # affinity: + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: foo.bar.com/role + # operator: In + # values: + # - master + affinity: {} + + # A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core). + # + # For example: + # tolerations: + # - key: foo.bar.com/role + # operator: Equal + # value: master + # effect: NoSchedule + tolerations: [] + + # A list of Kubernetes TopologySpreadConstraints, if required. For more information, see [Topology spread constraint v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#topologyspreadconstraint-v1-core). + # + # For example: + # topologySpreadConstraints: + # - maxSkew: 2 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: ScheduleAnyway + # labelSelector: + # matchLabels: + # app.kubernetes.io/instance: cert-manager + # app.kubernetes.io/component: controller + topologySpreadConstraints: [] + + # Optional additional labels to add to the Webhook Pods. + podLabels: {} + + # Optional additional labels to add to the Webhook Service. + serviceLabels: {} + + # Optionally set the IP family policy for the controller Service to configure dual-stack; see [Configure dual-stack](https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services). + serviceIPFamilyPolicy: "" + + # Optionally set the IP families for the controller Service that should be supported, in the order in which they should be applied to ClusterIP. Can be IPv4 and/or IPv6. + serviceIPFamilies: [] + + image: + # The container registry to pull the webhook image from. + # +docs:property + # registry: quay.io + + # The container image for the cert-manager webhook + # +docs:property + repository: quay.io/jetstack/cert-manager-webhook + + # Override the image tag to deploy by setting this variable. + # If no value is set, the chart's appVersion will be used. + # +docs:property + # tag: vX.Y.Z + + # Setting a digest will override any tag + # +docs:property + # digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 + + # Kubernetes imagePullPolicy on Deployment. + pullPolicy: IfNotPresent + + serviceAccount: + # Specifies whether a service account should be created. + create: true + + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template. + # +docs:property + # name: "" + + # Optional additional annotations to add to the webhook's Service Account. + # +docs:property + # annotations: {} + + # Optional additional labels to add to the webhook's Service Account. + # +docs:property + # labels: {} + + # Automount API credentials for a Service Account. + automountServiceAccountToken: true + + # Automounting API credentials for a particular pod. + # +docs:property + # automountServiceAccountToken: true + + # The port that the webhook listens on for requests. + # In GKE private clusters, by default Kubernetes apiservers are allowed to + # talk to the cluster nodes only on 443 and 10250. Configuring + # securePort: 10250, therefore will work out-of-the-box without needing to add firewall + # rules or requiring NET_BIND_SERVICE capabilities to bind port numbers <1000. + securePort: 10250 + + # Specifies if the webhook should be started in hostNetwork mode. + # + # Required for use in some managed kubernetes clusters (such as AWS EKS) with custom + # CNI (such as calico), because control-plane managed by AWS cannot communicate + # with pods' IP CIDR and admission webhooks are not working + # + # Since the default port for the webhook conflicts with kubelet on the host + # network, `webhook.securePort` should be changed to an available port if + # running in hostNetwork mode. + hostNetwork: false + + # Specifies how the service should be handled. Useful if you want to expose the + # webhook outside of the cluster. In some cases, the control plane cannot + # reach internal services. + serviceType: ClusterIP + + # Specify the load balancer IP for the created service. + # +docs:property + # loadBalancerIP: "10.10.10.10" + + # Overrides the mutating webhook and validating webhook so they reach the webhook + # service using the `url` field instead of a service. + url: {} + # host: + + # Enables default network policies for webhooks. + networkPolicy: + # Create network policies for the webhooks. + enabled: false + + # Ingress rule for the webhook network policy. By default, it allows all + # inbound traffic. + # +docs:property + ingress: + - from: + - ipBlock: + cidr: 0.0.0.0/0 + + # Egress rule for the webhook network policy. By default, it allows all + # outbound traffic to ports 80 and 443, as well as DNS ports. + # +docs:property + egress: + - ports: + - port: 80 + protocol: TCP + - port: 443 + protocol: TCP + - port: 53 + protocol: TCP + - port: 53 + protocol: UDP + # On OpenShift and OKD, the Kubernetes API server listens on. + # port 6443. + - port: 6443 + protocol: TCP + to: + - ipBlock: + cidr: 0.0.0.0/0 + + # Additional volumes to add to the cert-manager controller pod. + volumes: [] + + # Additional volume mounts to add to the cert-manager controller container. + volumeMounts: [] + + # enableServiceLinks indicates whether information about services should be + # injected into the pod's environment variables, matching the syntax of Docker + # links. + enableServiceLinks: false + +# +docs:section=CA Injector + +cainjector: + # Create the CA Injector deployment + enabled: true + + # The number of replicas of the cert-manager cainjector to run. + # + # The default is 1, but in production set this to 2 or 3 to provide high + # availability. + # + # If `replicas > 1`, consider setting `cainjector.podDisruptionBudget.enabled=true`. + # + # Note that cert-manager uses leader election to ensure that there can + # only be a single instance active at a time. + replicaCount: 1 + + # This is used to configure options for the cainjector pod. + # It allows setting options that are usually provided via flags. + # + # If `apiVersion` and `kind` are unspecified they default to the current latest + # version (currently `cainjector.config.cert-manager.io/v1alpha1`). You can pin + # the version by specifying the `apiVersion` yourself. + # + # For example: + # apiVersion: cainjector.config.cert-manager.io/v1alpha1 + # kind: CAInjectorConfiguration + # logging: + # verbosity: 2 + # format: text + # leaderElectionConfig: + # namespace: kube-system + # # Configure the metrics server for TLS + # # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls + # metricsTLSConfig: + # dynamic: + # secretNamespace: "cert-manager" + # secretName: "cert-manager-metrics-ca" + # dnsNames: + # - cert-manager-metrics + config: {} + + # Deployment update strategy for the cert-manager cainjector deployment. + # For more information, see the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy). + # + # For example: + # strategy: + # type: RollingUpdate + # rollingUpdate: + # maxSurge: 0 + # maxUnavailable: 1 + strategy: {} + + # Pod Security Context to be set on the cainjector component Pod + # For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + # +docs:property + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + + # Container Security Context to be set on the cainjector component container + # For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + # +docs:property + containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + + podDisruptionBudget: + # Enable or disable the PodDisruptionBudget resource. + # + # This prevents downtime during voluntary disruptions such as during a Node upgrade. + # For example, the PodDisruptionBudget will block `kubectl drain` + # if it is used on the Node where the only remaining cert-manager + # Pod is currently running. + enabled: false + + # `minAvailable` configures the minimum available pods for disruptions. It can either be set to + # an integer (e.g. 1) or a percentage value (e.g. 25%). + # Cannot be used if `maxUnavailable` is set. + # +docs:property + # +docs:type=unknown + # minAvailable: 1 + + # `maxUnavailable` configures the maximum unavailable pods for disruptions. It can either be set to + # an integer (e.g. 1) or a percentage value (e.g. 25%). + # Cannot be used if `minAvailable` is set. + # +docs:property + # +docs:type=unknown + # maxUnavailable: 1 + + # Optional additional annotations to add to the cainjector Deployment. + # +docs:property + # deploymentAnnotations: {} + + # Optional additional annotations to add to the cainjector Pods. + # +docs:property + # podAnnotations: {} + + # Optional additional annotations to add to the cainjector metrics Service. + # +docs:property + # serviceAnnotations: {} + + # Additional command line flags to pass to cert-manager cainjector binary. + # To see all available flags run `docker run quay.io/jetstack/cert-manager-cainjector: --help`. + extraArgs: [] + # Enable profiling for cainjector. + # - --enable-profiling=true + + # Additional environment variables to pass to cert-manager cainjector binary. + # For example: + # extraEnv: + # - name: SOME_VAR + # value: 'some value' + extraEnv: [] + + # Comma separated list of feature gates that should be enabled on the + # cainjector pod. + featureGates: "" + + # Resources to provide to the cert-manager cainjector pod. + # + # For example: + # requests: + # cpu: 10m + # memory: 32Mi + # + # For more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). + resources: {} + + + # The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with + # matching labels. + # For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). + # + # This default ensures that Pods are only scheduled to Linux nodes. + # It prevents Pods being scheduled to Windows nodes in a mixed OS cluster. + # +docs:property + nodeSelector: + kubernetes.io/os: linux + + # A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core). + # + # For example: + # affinity: + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: foo.bar.com/role + # operator: In + # values: + # - master + affinity: {} + + # A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core). + # + # For example: + # tolerations: + # - key: foo.bar.com/role + # operator: Equal + # value: master + # effect: NoSchedule + tolerations: [] + + # A list of Kubernetes TopologySpreadConstraints, if required. For more information, see [Topology spread constraint v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#topologyspreadconstraint-v1-core). + # + # For example: + # topologySpreadConstraints: + # - maxSkew: 2 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: ScheduleAnyway + # labelSelector: + # matchLabels: + # app.kubernetes.io/instance: cert-manager + # app.kubernetes.io/component: controller + topologySpreadConstraints: [] + + # Optional additional labels to add to the CA Injector Pods. + podLabels: {} + + # Optional additional labels to add to the CA Injector metrics Service. + serviceLabels: {} + + image: + # The container registry to pull the cainjector image from. + # +docs:property + # registry: quay.io + + # The container image for the cert-manager cainjector + # +docs:property + repository: quay.io/jetstack/cert-manager-cainjector + + # Override the image tag to deploy by setting this variable. + # If no value is set, the chart's appVersion will be used. + # +docs:property + # tag: vX.Y.Z + + # Setting a digest will override any tag. + # +docs:property + # digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 + + # Kubernetes imagePullPolicy on Deployment. + pullPolicy: IfNotPresent + + serviceAccount: + # Specifies whether a service account should be created. + create: true + + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + # +docs:property + # name: "" + + # Optional additional annotations to add to the cainjector's Service Account. + # +docs:property + # annotations: {} + + # Optional additional labels to add to the cainjector's Service Account. + # +docs:property + # labels: {} + + # Automount API credentials for a Service Account. + automountServiceAccountToken: true + + # Automounting API credentials for a particular pod. + # +docs:property + # automountServiceAccountToken: true + + # Additional volumes to add to the cert-manager controller pod. + volumes: [] + + # Additional volume mounts to add to the cert-manager controller container. + volumeMounts: [] + + # enableServiceLinks indicates whether information about services should be + # injected into the pod's environment variables, matching the syntax of Docker + # links. + enableServiceLinks: false + +# +docs:section=ACME Solver + +acmesolver: + image: + # The container registry to pull the acmesolver image from. + # +docs:property + # registry: quay.io + + # The container image for the cert-manager acmesolver. + # +docs:property + repository: quay.io/jetstack/cert-manager-acmesolver + + # Override the image tag to deploy by setting this variable. + # If no value is set, the chart's appVersion is used. + # +docs:property + # tag: vX.Y.Z + + # Setting a digest will override any tag. + # +docs:property + # digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 + + # Kubernetes imagePullPolicy on Deployment. + pullPolicy: IfNotPresent + +# +docs:section=Startup API Check +# This startupapicheck is a Helm post-install hook that waits for the webhook +# endpoints to become available. +# The check is implemented using a Kubernetes Job - if you are injecting mesh +# sidecar proxies into cert-manager pods, ensure that they +# are not injected into this Job's pod. Otherwise, the installation may time out +# owing to the Job never being completed because the sidecar proxy does not exit. +# For more information, see [this note](https://github.com/cert-manager/cert-manager/pull/4414). + +startupapicheck: + # Enables the startup api check. + enabled: true + + # Pod Security Context to be set on the startupapicheck component Pod. + # For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + # +docs:property + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + + # Container Security Context to be set on the controller component container. + # For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + # +docs:property + containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + + # Timeout for 'kubectl check api' command. + timeout: 1m + + # Job backoffLimit + backoffLimit: 4 + + # Optional additional annotations to add to the startupapicheck Job. + # +docs:property + jobAnnotations: + helm.sh/hook: post-install + helm.sh/hook-weight: "1" + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded + + # Optional additional annotations to add to the startupapicheck Pods. + # +docs:property + # podAnnotations: {} + + # Additional command line flags to pass to startupapicheck binary. + # To see all available flags run `docker run quay.io/jetstack/cert-manager-startupapicheck: --help`. + # + # Verbose logging is enabled by default so that if startupapicheck fails, you + # can know what exactly caused the failure. Verbose logs include details of + # the webhook URL, IP address and TCP connect errors for example. + # +docs:property + extraArgs: + - -v + + # Additional environment variables to pass to cert-manager startupapicheck binary. + # For example: + # extraEnv: + # - name: SOME_VAR + # value: 'some value' + extraEnv: [] + + # Resources to provide to the cert-manager controller pod. + # + # For example: + # requests: + # cpu: 10m + # memory: 32Mi + # + # For more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). + resources: {} + + + # The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with + # matching labels. + # For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). + # + # This default ensures that Pods are only scheduled to Linux nodes. + # It prevents Pods being scheduled to Windows nodes in a mixed OS cluster. + # +docs:property + nodeSelector: + kubernetes.io/os: linux + + # A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core). + # For example: + # affinity: + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: foo.bar.com/role + # operator: In + # values: + # - master + affinity: {} + + # A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core). + # + # For example: + # tolerations: + # - key: foo.bar.com/role + # operator: Equal + # value: master + # effect: NoSchedule + tolerations: [] + + # Optional additional labels to add to the startupapicheck Pods. + podLabels: {} + + image: + # The container registry to pull the startupapicheck image from. + # +docs:property + # registry: quay.io + + # The container image for the cert-manager startupapicheck. + # +docs:property + repository: quay.io/jetstack/cert-manager-startupapicheck + + # Override the image tag to deploy by setting this variable. + # If no value is set, the chart's appVersion is used. + # +docs:property + # tag: vX.Y.Z + + # Setting a digest will override any tag. + # +docs:property + # digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 + + # Kubernetes imagePullPolicy on Deployment. + pullPolicy: IfNotPresent + + rbac: + # annotations for the startup API Check job RBAC and PSP resources. + # +docs:property + annotations: + helm.sh/hook: post-install + helm.sh/hook-weight: "-5" + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded + + # Automounting API credentials for a particular pod. + # +docs:property + # automountServiceAccountToken: true + + serviceAccount: + # Specifies whether a service account should be created. + create: true + + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template. + # +docs:property + # name: "" + + # Optional additional annotations to add to the Job's Service Account. + # +docs:property + annotations: + helm.sh/hook: post-install + helm.sh/hook-weight: "-5" + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded + + # Automount API credentials for a Service Account. + # +docs:property + automountServiceAccountToken: true + + # Optional additional labels to add to the startupapicheck's Service Account. + # +docs:property + # labels: {} + + # Additional volumes to add to the cert-manager controller pod. + volumes: [] + + # Additional volume mounts to add to the cert-manager controller container. + volumeMounts: [] + + # enableServiceLinks indicates whether information about services should be + # injected into pod's environment variables, matching the syntax of Docker + # links. + enableServiceLinks: false + +# Create dynamic manifests via values. +# +# For example: +# extraObjects: +# - | +# apiVersion: v1 +# kind: ConfigMap +# metadata: +# name: '{{ template "cert-manager.fullname" . }}-extra-configmap' +extraObjects: [] + +# Field used by our release pipeline to produce the static manifests. +# The field defaults to "helm" but is set to "static" when we render +# the static YAML manifests. +# +docs:hidden +creator: "helm" + +# Field that can be used as a condition when cert-manager is a dependency. +# This definition is only here as a placeholder such that it is included in +# the json schema. +# See https://helm.sh/docs/chart_best_practices/dependencies/#conditions-and-tags +# for more info. +# +docs:hidden +enabled: true diff --git a/backing-services/docker-registry/.circleci/config.yml b/backing-services/docker-registry/.circleci/config.yml new file mode 100644 index 0000000..6e4b6a7 --- /dev/null +++ b/backing-services/docker-registry/.circleci/config.yml @@ -0,0 +1,15 @@ +version: 2.1 +jobs: + lint: + docker: + - image: twuni/helm:3.4.1 + steps: + - checkout + - run: + command: helm lint --strict + name: lint +workflows: + version: 2 + default: + jobs: + - lint diff --git a/backing-services/docker-registry/.github/workflows/pr_diff.yaml b/backing-services/docker-registry/.github/workflows/pr_diff.yaml new file mode 100644 index 0000000..52f6a42 --- /dev/null +++ b/backing-services/docker-registry/.github/workflows/pr_diff.yaml @@ -0,0 +1,58 @@ +name: PR Diff for Helm chart + +on: + pull_request_target: + +permissions: + pull-requests: write + +jobs: + diff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: azure/setup-helm@v3 + - name: Run diff + id: diff + run: | + OPTIONS=( + --namespace meta-namespace + --set serviceAccount.create=true + --set priorityClassName=high + --set podAnnotations.test=annotation + --set extraEnvVars[0].name=TEST_NAME + --set extraEnvVars[0].value=TEST_VALUE + --set extraVolumes[0].name=test + --set extraVolumes[0].emptyDir.medium=Memory + --set extraVolumeMounts[0].name=test + --set extraVolumeMounts[0].mountPath=/test + --set secrets.htpasswd=abc + --set tlsSecretName=abc + --set garbageCollect.enabled=true + --set namespace=target-namespace + --set proxy.enabled=true + --set storage=s3 + --set secrets.s3.secretKey=abc + --set secrets.s3.accessKey=def + --set s3.region=us-42 + --set s3.bucket=abc + --set s3.encrypt=abc + ) + helm template --debug ${OPTIONS[@]} --output-dir before https://github.com/twuni/docker-registry.helm/archive/refs/heads/main.tar.gz + helm template --debug ${OPTIONS[@]} --output-dir after . + # https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings + echo 'HELM_DIFF<> $GITHUB_ENV + echo "$(diff -ur before after)" >> $GITHUB_ENV + echo 'EOF' >> $GITHUB_ENV + - uses: marocchino/sticky-pull-request-comment@39c5b5dc7717447d0cba270cd115037d32d28443 + with: + message: | + Running a `helm template` smoketest on commit ${{ github.ref }} results in the following diff against `${{ github.base_ref }}`: + +
diff

+ + ```diff + ${{ env.HELM_DIFF }} + ``` + +

diff --git a/backing-services/docker-registry/.helmignore b/backing-services/docker-registry/.helmignore new file mode 100644 index 0000000..f0c1319 --- /dev/null +++ b/backing-services/docker-registry/.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/backing-services/docker-registry/Chart.yaml b/backing-services/docker-registry/Chart.yaml new file mode 100644 index 0000000..e0ef927 --- /dev/null +++ b/backing-services/docker-registry/Chart.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +appVersion: 2.8.1 +description: A Helm chart for Docker Registry +home: https://hub.docker.com/_/registry/ +icon: https://helm.twun.io/docker-registry.png +maintainers: +- email: devin@canterberry.cc + name: Devin Canterberry + url: https://canterberry.cc/ +name: docker-registry +sources: +- https://github.com/docker/distribution-library-image +version: 2.2.3 diff --git a/backing-services/docker-registry/LICENSE b/backing-services/docker-registry/LICENSE new file mode 100644 index 0000000..393b7a3 --- /dev/null +++ b/backing-services/docker-registry/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright The Helm Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/backing-services/docker-registry/README.md b/backing-services/docker-registry/README.md new file mode 100644 index 0000000..ef4ee90 --- /dev/null +++ b/backing-services/docker-registry/README.md @@ -0,0 +1,127 @@ +# Docker Registry Helm Chart + +This directory contains a Kubernetes chart to deploy a private Docker Registry. + +## Prerequisites Details + +* PV support on underlying infrastructure (if persistence is required) + +## Chart Details + +This chart will do the following: + +* Implement a Docker registry deployment + +## Installing the Chart + +First, add the repo: + +```console +$ helm repo add twuni https://helm.twun.io +``` + +To install the chart, use the following: + +```console +$ helm install twuni/docker-registry +``` + +## Configuration + +The following table lists the configurable parameters of the docker-registry chart and +their default values. + +| Parameter | Description | Default | +|:----------------------------|:-------------------------------------------------------------------------------------------|:----------------| +| `image.pullPolicy` | Container pull policy | `IfNotPresent` | +| `image.repository` | Container image to use | `registry` | +| `image.tag` | Container image tag to deploy | `2.8.1` | +| `imagePullSecrets` | Specify image pull secrets | `nil` (does not add image pull secrets to deployed pods) | +| `persistence.accessMode` | Access mode to use for PVC | `ReadWriteOnce` | +| `persistence.enabled` | Whether to use a PVC for the Docker storage | `false` | +| `persistence.deleteEnabled` | Enable the deletion of image blobs and manifests by digest | `nil` | +| `persistence.size` | Amount of space to claim for PVC | `10Gi` | +| `persistence.storageClass` | Storage Class to use for PVC | `-` | +| `persistence.existingClaim` | Name of an existing PVC to use for config | `nil` | +| `serviceAccount.create` | Create ServiceAccount | `false` | +| `serviceAccount.name` | ServiceAccount name | `nil` | +| `serviceAccount.annotations` | Annotations to add to the ServiceAccount | `{}` | +| `deployment.annotations` | Annotations to add to the Deployment | `{}` | +| `service.port` | TCP port on which the service is exposed | `5000` | +| `service.type` | service type | `ClusterIP` | +| `service.clusterIP` | if `service.type` is `ClusterIP` and this is non-empty, sets the cluster IP of the service | `nil` | +| `service.nodePort` | if `service.type` is `NodePort` and this is non-empty, sets the node port of the service | `nil` | +| `service.loadBalancerIP` | if `service.type` is `LoadBalancer` and this is non-empty, sets the loadBalancerIP of the service | `nil` | +| `service.loadBalancerSourceRanges`| if `service.type` is `LoadBalancer` and this is non-empty, sets the loadBalancerSourceRanges of the service | `nil` | +| `service.sessionAffinity` | service session affinity | `nil` | +| `service.sessionAffinityConfig` | service session affinity config | `nil` | +| `replicaCount` | k8s replicas | `1` | +| `updateStrategy` | update strategy for deployment | `{}` | +| `podAnnotations` | Annotations for pod | `{}` | +| `podLabels` | Labels for pod | `{}` | +| `podDisruptionBudget` | Pod disruption budget | `{}` | +| `resources.limits.cpu` | Container requested CPU | `nil` | +| `resources.limits.memory` | Container requested memory | `nil` | +| `autoscaling.enabled` | Enable autoscaling using HorizontalPodAutoscaler | `false` | +| `autoscaling.minReplicas` | Minimal number of replicas | `1` | +| `autoscaling.maxReplicas` | Maximal number of replicas | `2` | +| `autoscaling.targetCPUUtilizationPercentage` | Target average utilization of CPU on Pods | `60` | +| `autoscaling.targetMemoryUtilizationPercentage` | (Kubernetes ≥1.23) Target average utilization of Memory on Pods | `60` | +| `autoscaling.behavior` | (Kubernetes ≥1.23) Configurable scaling behavior | `{}` | +| `priorityClassName ` | priorityClassName | `""` | +| `storage` | Storage system to use | `filesystem` | +| `tlsSecretName` | Name of secret for TLS certs | `nil` | +| `secrets.htpasswd` | Htpasswd authentication | `nil` | +| `secrets.s3.accessKey` | Access Key for S3 configuration | `nil` | +| `secrets.s3.secretKey` | Secret Key for S3 configuration | `nil` | +| `secrets.s3.secretRef` | The ref for an external secret containing the accessKey and secretKey keys | `""` | +| `secrets.swift.username` | Username for Swift configuration | `nil` | +| `secrets.swift.password` | Password for Swift configuration | `nil` | +| `secrets.haSharedSecret` | Shared secret for Registry | `nil` | +| `configData` | Configuration hash for docker | `nil` | +| `s3.region` | S3 region | `nil` | +| `s3.regionEndpoint` | S3 region endpoint | `nil` | +| `s3.bucket` | S3 bucket name | `nil` | +| `s3.rootdirectory` | S3 prefix that is applied to allow you to segment data | `nil` | +| `s3.encrypt` | Store images in encrypted format | `nil` | +| `s3.secure` | Use HTTPS | `nil` | +| `swift.authurl` | Swift authurl | `nil` | +| `swift.container` | Swift container | `nil` | +| `proxy.enabled` | If true, registry will function as a proxy/mirror | `false` | +| `proxy.remoteurl` | Remote registry URL to proxy requests to | `https://registry-1.docker.io` | +| `proxy.username` | Remote registry login username | `nil` | +| `proxy.password` | Remote registry login password | `nil` | +| `proxy.secretRef` | The ref for an external secret containing the proxyUsername and proxyPassword keys | `""` | +| `namespace` | specify a namespace to install the chart to - defaults to `.Release.Namespace` | `{{ .Release.Namespace }}` | +| `nodeSelector` | node labels for pod assignment | `{}` | +| `affinity` | affinity settings | `{}` | +| `tolerations` | pod tolerations | `[]` | +| `ingress.enabled` | If true, Ingress will be created | `false` | +| `ingress.annotations` | Ingress annotations | `{}` | +| `ingress.labels` | Ingress labels | `{}` | +| `ingress.path` | Ingress service path | `/` | +| `ingress.hosts` | Ingress hostnames | `[]` | +| `ingress.tls` | Ingress TLS configuration (YAML) | `[]` | +| `ingress.className` | Ingress controller class name | `nginx` | +| `metrics.enabled` | Enable metrics on Service | `false` | +| `metrics.port` | TCP port on which the service metrics is exposed | `5001` | +| `metrics.serviceMonitor.annotations` | Prometheus Operator ServiceMonitor annotations | `{}` | +| `metrics.serviceMonitor.enable` | If true, Prometheus Operator ServiceMonitor will be created | `false` | +| `metrics.serviceMonitor.labels` | Prometheus Operator ServiceMonitor labels | `{}` | +| `metrics.prometheusRule.annotations` | Prometheus Operator PrometheusRule annotations | `{}` | +| `metrics.prometheusRule.enable` | If true, Prometheus Operator prometheusRule will be created | `false` | +| `metrics.prometheusRule.labels` | Prometheus Operator prometheusRule labels | `{}` | +| `metrics.prometheusRule.rules` | PrometheusRule defining alerting rules for a Prometheus instance | `{}` | +| `extraVolumeMounts` | Additional volumeMounts to the registry container | `[]` | +| `extraVolumes` | Additional volumes to the pod | `[]` | +| `extraEnvVars` | Additional environment variables to the pod | `[]` | +| `initContainers` | Init containers to be created in the pod | `[]` | +| `garbageCollect.enabled` | If true, will deploy garbage-collector cronjob | `false` | +| `garbageCollect.deleteUntagged` | If true, garbage-collector will delete manifests that are not currently referenced via tag | `true` | | +| `garbageCollect.schedule` | CronTab schedule, please use standard crontab format | `0 1 * * *` | | + +Specify each parameter using the `--set key=value[,key=value]` argument to +`helm install`. + +To generate htpasswd file, run this docker command: +`docker run --entrypoint htpasswd registry:2 -Bbn user password > ./htpasswd`. diff --git a/backing-services/docker-registry/templates/NOTES.txt b/backing-services/docker-registry/templates/NOTES.txt new file mode 100644 index 0000000..4a9152b --- /dev/null +++ b/backing-services/docker-registry/templates/NOTES.txt @@ -0,0 +1,19 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range .Values.ingress.hosts }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ . }}{{ $.Values.ingress.path }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "docker-registry.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 "docker-registry.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "docker-registry.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 "docker-registry.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl -n {{ .Release.Namespace }} port-forward $POD_NAME 8080:5000 +{{- end }} diff --git a/backing-services/docker-registry/templates/_helpers.tpl b/backing-services/docker-registry/templates/_helpers.tpl new file mode 100644 index 0000000..d9d7531 --- /dev/null +++ b/backing-services/docker-registry/templates/_helpers.tpl @@ -0,0 +1,209 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "docker-registry.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 "docker-registry.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 -}} + +{{- define "docker-registry.envs" -}} +- name: REGISTRY_HTTP_SECRET + valueFrom: + secretKeyRef: + name: {{ template "docker-registry.fullname" . }}-secret + key: haSharedSecret + +{{- if .Values.secrets.htpasswd }} +- name: REGISTRY_AUTH + value: "htpasswd" +- name: REGISTRY_AUTH_HTPASSWD_REALM + value: "Registry Realm" +- name: REGISTRY_AUTH_HTPASSWD_PATH + value: "/auth/htpasswd" +{{- end }} + +{{- if .Values.tlsSecretName }} +- name: REGISTRY_HTTP_TLS_CERTIFICATE + value: /etc/ssl/docker/tls.crt +- name: REGISTRY_HTTP_TLS_KEY + value: /etc/ssl/docker/tls.key +{{- end -}} + +{{- if eq .Values.storage "filesystem" }} +- name: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY + value: "/var/lib/registry" +{{- else if eq .Values.storage "azure" }} +- name: REGISTRY_STORAGE_AZURE_ACCOUNTNAME + valueFrom: + secretKeyRef: + name: {{ template "docker-registry.fullname" . }}-secret + key: azureAccountName +- name: REGISTRY_STORAGE_AZURE_ACCOUNTKEY + valueFrom: + secretKeyRef: + name: {{ template "docker-registry.fullname" . }}-secret + key: azureAccountKey +- name: REGISTRY_STORAGE_AZURE_CONTAINER + valueFrom: + secretKeyRef: + name: {{ template "docker-registry.fullname" . }}-secret + key: azureContainer +{{- else if eq .Values.storage "s3" }} +- name: REGISTRY_STORAGE_S3_REGION + value: {{ required ".Values.s3.region is required" .Values.s3.region }} +- name: REGISTRY_STORAGE_S3_BUCKET + value: {{ required ".Values.s3.bucket is required" .Values.s3.bucket }} +{{- if or (and .Values.secrets.s3.secretKey .Values.secrets.s3.accessKey) .Values.secrets.s3.secretRef }} +- name: REGISTRY_STORAGE_S3_ACCESSKEY + valueFrom: + secretKeyRef: + name: {{ if .Values.secrets.s3.secretRef }}{{ .Values.secrets.s3.secretRef }}{{ else }}{{ template "docker-registry.fullname" . }}-secret{{ end }} + key: s3AccessKey +- name: REGISTRY_STORAGE_S3_SECRETKEY + valueFrom: + secretKeyRef: + name: {{ if .Values.secrets.s3.secretRef }}{{ .Values.secrets.s3.secretRef }}{{ else }}{{ template "docker-registry.fullname" . }}-secret{{ end }} + key: s3SecretKey +{{- end -}} + +{{- if .Values.s3.regionEndpoint }} +- name: REGISTRY_STORAGE_S3_REGIONENDPOINT + value: {{ .Values.s3.regionEndpoint }} +{{- end -}} + +{{- if .Values.s3.rootdirectory }} +- name: REGISTRY_STORAGE_S3_ROOTDIRECTORY + value: {{ .Values.s3.rootdirectory | quote }} +{{- end -}} + +{{- if .Values.s3.encrypt }} +- name: REGISTRY_STORAGE_S3_ENCRYPT + value: {{ .Values.s3.encrypt | quote }} +{{- end -}} + +{{- if .Values.s3.secure }} +- name: REGISTRY_STORAGE_S3_SECURE + value: {{ .Values.s3.secure | quote }} +{{- end -}} + +{{- else if eq .Values.storage "swift" }} +- name: REGISTRY_STORAGE_SWIFT_AUTHURL + value: {{ required ".Values.swift.authurl is required" .Values.swift.authurl }} +- name: REGISTRY_STORAGE_SWIFT_USERNAME + valueFrom: + secretKeyRef: + name: {{ template "docker-registry.fullname" . }}-secret + key: swiftUsername +- name: REGISTRY_STORAGE_SWIFT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "docker-registry.fullname" . }}-secret + key: swiftPassword +- name: REGISTRY_STORAGE_SWIFT_CONTAINER + value: {{ required ".Values.swift.container is required" .Values.swift.container }} +{{- end -}} + +{{- if .Values.proxy.enabled }} +- name: REGISTRY_PROXY_REMOTEURL + value: {{ required ".Values.proxy.remoteurl is required" .Values.proxy.remoteurl }} +- name: REGISTRY_PROXY_USERNAME + valueFrom: + secretKeyRef: + name: {{ if .Values.proxy.secretRef }}{{ .Values.proxy.secretRef }}{{ else }}{{ template "docker-registry.fullname" . }}-secret{{ end }} + key: proxyUsername +- name: REGISTRY_PROXY_PASSWORD + valueFrom: + secretKeyRef: + name: {{ if .Values.proxy.secretRef }}{{ .Values.proxy.secretRef }}{{ else }}{{ template "docker-registry.fullname" . }}-secret{{ end }} + key: proxyPassword +{{- end -}} + +{{- if .Values.persistence.deleteEnabled }} +- name: REGISTRY_STORAGE_DELETE_ENABLED + value: "true" +{{- end -}} + +{{- with .Values.extraEnvVars }} +{{ toYaml . }} +{{- end -}} + +{{- end -}} + +{{- define "docker-registry.volumeMounts" -}} +- name: "{{ template "docker-registry.fullname" . }}-config" + mountPath: "/etc/docker/registry" + +{{- if .Values.secrets.htpasswd }} +- name: auth + mountPath: /auth + readOnly: true +{{- end }} + +{{- if eq .Values.storage "filesystem" }} +- name: data + mountPath: /var/lib/registry/ +{{- end }} + +{{- if .Values.tlsSecretName }} +- mountPath: /etc/ssl/docker + name: tls-cert + readOnly: true +{{- end }} + +{{- with .Values.extraVolumeMounts }} +{{ toYaml . }} +{{- end }} + +{{- end -}} + +{{- define "docker-registry.volumes" -}} +- name: {{ template "docker-registry.fullname" . }}-config + configMap: + name: {{ template "docker-registry.fullname" . }}-config + +{{- if .Values.secrets.htpasswd }} +- name: auth + secret: + secretName: {{ template "docker-registry.fullname" . }}-secret + items: + - key: htpasswd + path: htpasswd +{{- end }} + +{{- if eq .Values.storage "filesystem" }} +- name: data + {{- if .Values.persistence.enabled }} + persistentVolumeClaim: + claimName: {{ if .Values.persistence.existingClaim }}{{ .Values.persistence.existingClaim }}{{- else }}{{ template "docker-registry.fullname" . }}{{- end }} + {{- else }} + emptyDir: {} + {{- end -}} +{{- end }} + +{{- if .Values.tlsSecretName }} +- name: tls-cert + secret: + secretName: {{ .Values.tlsSecretName }} +{{- end }} + +{{- with .Values.extraVolumes }} +{{ toYaml . }} +{{- end }} +{{- end -}} diff --git a/backing-services/docker-registry/templates/configmap.yaml b/backing-services/docker-registry/templates/configmap.yaml new file mode 100644 index 0000000..0f046ea --- /dev/null +++ b/backing-services/docker-registry/templates/configmap.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "docker-registry.fullname" . }}-config + namespace: {{ .Values.namespace | default .Release.Namespace }} + labels: + app: {{ template "docker-registry.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} +data: + config.yml: |- +{{ toYaml .Values.configData | indent 4 }} diff --git a/backing-services/docker-registry/templates/cronjob.yaml b/backing-services/docker-registry/templates/cronjob.yaml new file mode 100644 index 0000000..80b18d5 --- /dev/null +++ b/backing-services/docker-registry/templates/cronjob.yaml @@ -0,0 +1,68 @@ +{{- if .Values.garbageCollect.enabled }} +apiVersion: batch/v1 +kind: CronJob +metadata: + name: {{ template "docker-registry.fullname" . }}-garbage-collector + namespace: {{ .Values.namespace | default .Release.Namespace }} + labels: + app: {{ template "docker-registry.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + schedule: {{ .Values.garbageCollect.schedule | quote }} + jobTemplate: + metadata: + labels: + app: {{ template "docker-registry.name" . }} + release: {{ .Release.Name }} + {{- with .Values.podLabels }} + {{ toYaml . | nindent 8 }} + {{- end }} + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} + {{- if .Values.podAnnotations }} + {{ toYaml .Values.podAnnotations | nindent 8 }} + {{- end }} + spec: + template: + spec: + {{- if or (eq .Values.serviceAccount.create true) (ne .Values.serviceAccount.name "") }} + serviceAccountName: {{ .Values.serviceAccount.name | default (include "docker-registry.fullname" .) }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 12 }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: "{{ .Values.priorityClassName }}" + {{- end }} + {{- if .Values.securityContext.enabled }} + securityContext: {{ omit .Values.securityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - /bin/registry + - garbage-collect + - --delete-untagged={{ .Values.garbageCollect.deleteUntagged }} + - /etc/docker/registry/config.yml + env: {{ include "docker-registry.envs" . | nindent 16 }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{ omit .Values.containerSecurityContext "enabled" | toYaml | nindent 16 }} + {{- end }} + volumeMounts: {{ include "docker-registry.volumeMounts" . | nindent 16 }} + restartPolicy: OnFailure + {{- if .Values.nodeSelector }} + nodeSelector: {{ toYaml .Values.nodeSelector | nindent 12 }} + {{- end }} + {{- if .Values.affinity }} + affinity: {{ toYaml .Values.affinity | nindent 12 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: {{ toYaml .Values.tolerations | nindent 12 }} + {{- end }} + volumes: {{ include "docker-registry.volumes" . | nindent 12 }} +{{- end }} diff --git a/backing-services/docker-registry/templates/deployment.yaml b/backing-services/docker-registry/templates/deployment.yaml new file mode 100644 index 0000000..dff79cb --- /dev/null +++ b/backing-services/docker-registry/templates/deployment.yaml @@ -0,0 +1,100 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "docker-registry.fullname" . }} + namespace: {{ .Values.namespace | default .Release.Namespace }} + labels: + app: {{ template "docker-registry.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- if .Values.deployment.annotations }} + annotations: +{{ toYaml .Values.deployment.annotations | indent 4 }} +{{- end }} +spec: + selector: + matchLabels: + app: {{ template "docker-registry.name" . }} + release: {{ .Release.Name }} + replicas: {{ .Values.replicaCount }} + {{- if .Values.updateStrategy }} + strategy: {{ toYaml .Values.updateStrategy | nindent 4 }} + {{- end }} + minReadySeconds: 5 + template: + metadata: + labels: + app: {{ template "docker-registry.name" . }} + release: {{ .Release.Name }} + {{- with .Values.podLabels }} + {{ toYaml . | nindent 8 }} + {{- end }} + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} + {{- if .Values.podAnnotations }} + {{ toYaml .Values.podAnnotations | nindent 8 }} + {{- end }} + spec: + {{- if or (eq .Values.serviceAccount.create true) (ne .Values.serviceAccount.name "") }} + serviceAccountName: {{ .Values.serviceAccount.name | default (include "docker-registry.fullname" .) }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 8 }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: "{{ .Values.priorityClassName }}" + {{- end }} + {{- if .Values.securityContext.enabled }} + securityContext: {{ omit .Values.securityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{- with .Values.initContainers }} + initContainers: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - /bin/registry + - serve + - /etc/docker/registry/config.yml + ports: + - containerPort: 5000 + {{- if .Values.metrics.enabled }} + - containerPort: {{ (split ":" .Values.configData.http.debug.addr)._1 }} + name: http-metrics + protocol: TCP + {{- end }} + livenessProbe: + httpGet: + {{- if .Values.tlsSecretName }} + scheme: HTTPS + {{- end }} + path: / + port: 5000 + readinessProbe: + httpGet: + {{- if .Values.tlsSecretName }} + scheme: HTTPS + {{- end }} + path: / + port: 5000 + resources: {{ toYaml .Values.resources | nindent 12 }} + env: {{ include "docker-registry.envs" . | nindent 12 }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{ omit .Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + volumeMounts: {{ include "docker-registry.volumeMounts" . | nindent 12 }} + {{- if .Values.nodeSelector }} + nodeSelector: {{ toYaml .Values.nodeSelector | nindent 8 }} + {{- end }} + {{- if .Values.affinity }} + affinity: {{ toYaml .Values.affinity | nindent 8 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: {{ toYaml .Values.tolerations | nindent 8 }} + {{- end }} + volumes: {{ include "docker-registry.volumes" . | nindent 8 }} diff --git a/backing-services/docker-registry/templates/hpa.yaml b/backing-services/docker-registry/templates/hpa.yaml new file mode 100644 index 0000000..0e29c95 --- /dev/null +++ b/backing-services/docker-registry/templates/hpa.yaml @@ -0,0 +1,42 @@ +{{- if .Values.autoscaling.enabled }} +{{- $apiVersions := .Capabilities.APIVersions -}} +{{- if $apiVersions.Has "autoscaling/v2" }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ template "docker-registry.fullname" . }} + labels: + app: {{ template "docker-registry.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ template "docker-registry.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: +{{- with .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ . }} +{{- end }} +{{- with .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ . }} +{{- end }} +{{- with .Values.autoscaling.behavior }} + behavior: + {{- toYaml . | nindent 4 }} +{{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/docker-registry/templates/hpaV1.yaml b/backing-services/docker-registry/templates/hpaV1.yaml new file mode 100644 index 0000000..3dccb7f --- /dev/null +++ b/backing-services/docker-registry/templates/hpaV1.yaml @@ -0,0 +1,22 @@ +{{- if .Values.autoscaling.enabled }} +{{- $apiVersions := .Capabilities.APIVersions -}} +{{- if not ($apiVersions.Has "autoscaling/v2") }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ template "docker-registry.fullname" . }} + labels: + app: {{ template "docker-registry.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ template "docker-registry.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + targetCPUUtilizationPercentage: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} +{{- end }} +{{- end }} diff --git a/backing-services/docker-registry/templates/ingress.yaml b/backing-services/docker-registry/templates/ingress.yaml new file mode 100644 index 0000000..cb90c2f --- /dev/null +++ b/backing-services/docker-registry/templates/ingress.yaml @@ -0,0 +1,50 @@ +{{- if .Values.ingress.enabled -}} +{{- $apiVersions := .Capabilities.APIVersions -}} +{{- $serviceName := include "docker-registry.fullname" . -}} +{{- $servicePort := .Values.service.port -}} +{{- $path := .Values.ingress.path -}} +apiVersion: {{- if $apiVersions.Has "networking.k8s.io/v1" }} networking.k8s.io/v1 {{- else }} networking.k8s.io/v1beta1 {{- end }} +kind: Ingress +metadata: + name: {{ template "docker-registry.fullname" . }} + namespace: {{ .Values.namespace | default .Release.Namespace }} + labels: + app: {{ template "docker-registry.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- if .Values.ingress.labels }} +{{ toYaml .Values.ingress.labels | indent 4 }} +{{- end }} + annotations: + {{- range $key, $value := .Values.ingress.annotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} +spec: +{{- if $apiVersions.Has "networking.k8s.io/v1" }} + ingressClassName: {{ .Values.ingress.className }} +{{- end }} + rules: + {{- range $host := .Values.ingress.hosts }} + - host: {{ $host }} + http: + paths: + - path: {{ $path }} +{{- if $apiVersions.Has "networking.k8s.io/v1" }} + pathType: Prefix + backend: + service: + name: {{ $serviceName }} + port: + number: {{ $servicePort }} +{{- else }} + backend: + serviceName: {{ $serviceName }} + servicePort: {{ $servicePort }} +{{- end }} + {{- end -}} + {{- if .Values.ingress.tls }} + tls: +{{ toYaml .Values.ingress.tls | indent 4 }} + {{- end -}} +{{- end -}} diff --git a/backing-services/docker-registry/templates/poddisruptionbudget.yaml b/backing-services/docker-registry/templates/poddisruptionbudget.yaml new file mode 100644 index 0000000..5a551d3 --- /dev/null +++ b/backing-services/docker-registry/templates/poddisruptionbudget.yaml @@ -0,0 +1,22 @@ +{{- if .Values.podDisruptionBudget -}} +{{- if .Capabilities.APIVersions.Has "policy/v1" -}} +apiVersion: policy/v1 +{{- else}} +apiVersion: policy/v1beta1 +{{- end }} +kind: PodDisruptionBudget +metadata: + name: {{ template "docker-registry.fullname" . }} + namespace: {{ .Values.namespace | default .Release.Namespace }} + labels: + app: {{ template "docker-registry.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + selector: + matchLabels: + app: {{ template "docker-registry.name" . }} + release: {{ .Release.Name }} +{{ toYaml .Values.podDisruptionBudget | indent 2 }} +{{- end -}} diff --git a/backing-services/docker-registry/templates/prometheusrules.yaml b/backing-services/docker-registry/templates/prometheusrules.yaml new file mode 100644 index 0000000..bc58d9d --- /dev/null +++ b/backing-services/docker-registry/templates/prometheusrules.yaml @@ -0,0 +1,17 @@ +{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled -}} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ template "docker-registry.fullname" . }} + labels: + app.kubernetes.io/component: controller + {{- if .Values.metrics.prometheusRule.labels }} + {{- toYaml .Values.metrics.prometheusRule.labels | nindent 4 }} + {{- end }} +spec: +{{- if .Values.metrics.prometheusRule.rules }} + groups: + - name: {{ template "docker-registry.fullname" . }} + rules: {{- toYaml .Values.metrics.prometheusRule.rules | nindent 4 }} +{{- end }} +{{- end }} diff --git a/backing-services/docker-registry/templates/pvc.yaml b/backing-services/docker-registry/templates/pvc.yaml new file mode 100644 index 0000000..dea0539 --- /dev/null +++ b/backing-services/docker-registry/templates/pvc.yaml @@ -0,0 +1,27 @@ +{{- if .Values.persistence.enabled }} +{{- if not .Values.persistence.existingClaim -}} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ template "docker-registry.fullname" . }} + namespace: {{ .Values.namespace | default .Release.Namespace }} + labels: + app: {{ template "docker-registry.fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" +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 }} +{{- end -}} diff --git a/backing-services/docker-registry/templates/secret.yaml b/backing-services/docker-registry/templates/secret.yaml new file mode 100644 index 0000000..6265dc8 --- /dev/null +++ b/backing-services/docker-registry/templates/secret.yaml @@ -0,0 +1,40 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "docker-registry.fullname" . }}-secret + namespace: {{ .Values.namespace | default .Release.Namespace }} + labels: + app: {{ template "docker-registry.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} +type: Opaque +data: + {{- if .Values.secrets.htpasswd }} + htpasswd: {{ .Values.secrets.htpasswd | b64enc }} + {{- end }} + {{- if .Values.secrets.haSharedSecret }} + haSharedSecret: {{ .Values.secrets.haSharedSecret | b64enc | quote }} + {{- else }} + haSharedSecret: {{ randAlphaNum 16 | b64enc | quote }} + {{- end }} + + {{- if eq .Values.storage "azure" }} + {{- if and .Values.secrets.azure.accountName .Values.secrets.azure.accountKey .Values.secrets.azure.container }} + azureAccountName: {{ .Values.secrets.azure.accountName | b64enc | quote }} + azureAccountKey: {{ .Values.secrets.azure.accountKey | b64enc | quote }} + azureContainer: {{ .Values.secrets.azure.container | b64enc | quote }} + {{- end }} + {{- else if eq .Values.storage "s3" }} + {{- if and .Values.secrets.s3.secretKey .Values.secrets.s3.accessKey }} + s3AccessKey: {{ .Values.secrets.s3.accessKey | b64enc | quote }} + s3SecretKey: {{ .Values.secrets.s3.secretKey | b64enc | quote }} + {{- end }} + {{- else if eq .Values.storage "swift" }} + {{- if and .Values.secrets.swift.username .Values.secrets.swift.password }} + swiftUsername: {{ .Values.secrets.swift.username | b64enc | quote }} + swiftPassword: {{ .Values.secrets.swift.password | b64enc | quote }} + {{- end }} + {{- end }} + proxyUsername: {{ .Values.proxy.username | default "" | b64enc | quote }} + proxyPassword: {{ .Values.proxy.password | default "" | b64enc | quote }} diff --git a/backing-services/docker-registry/templates/service.yaml b/backing-services/docker-registry/templates/service.yaml new file mode 100644 index 0000000..cc9c5d8 --- /dev/null +++ b/backing-services/docker-registry/templates/service.yaml @@ -0,0 +1,49 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "docker-registry.fullname" . }} + namespace: {{ .Values.namespace | default .Release.Namespace }} + labels: + app: {{ template "docker-registry.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- if .Values.service.annotations }} + annotations: +{{ toYaml .Values.service.annotations | indent 4 }} +{{- end }} +spec: + type: {{ .Values.service.type }} +{{- if (and (eq .Values.service.type "ClusterIP") (not (empty .Values.service.clusterIP))) }} + clusterIP: {{ .Values.service.clusterIP }} +{{- end }} +{{- if (and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerIP))) }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} +{{- end }} +{{- if (and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerSourceRanges))) }} + loadBalancerSourceRanges: {{ .Values.service.loadBalancerSourceRanges }} +{{- end }} +{{- if .Values.service.sessionAffinity }} + sessionAffinity: {{ .Values.service.sessionAffinity }} + {{- if .Values.service.sessionAffinityConfig }} + sessionAffinityConfig: + {{ toYaml .Values.service.sessionAffinityConfig | nindent 4 }} + {{- end -}} +{{- end }} + ports: + - port: {{ .Values.service.port }} + protocol: TCP + name: {{ if .Values.tlsSecretName }}https{{ else }}http{{ end }}-{{ .Values.service.port }} + targetPort: 5000 +{{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nodePort))) }} + nodePort: {{ .Values.service.nodePort }} +{{- end }} +{{- if .Values.metrics.enabled }} + - port: {{ .Values.metrics.port }} + protocol: TCP + name: http-metrics + targetPort: {{ (split ":" .Values.configData.http.debug.addr)._1 }} +{{- end }} + selector: + app: {{ template "docker-registry.name" . }} + release: {{ .Release.Name }} diff --git a/backing-services/docker-registry/templates/serviceaccount.yaml b/backing-services/docker-registry/templates/serviceaccount.yaml new file mode 100644 index 0000000..6cef434 --- /dev/null +++ b/backing-services/docker-registry/templates/serviceaccount.yaml @@ -0,0 +1,20 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app: {{ template "docker-registry.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + namespace: {{ .Values.namespace | default .Release.Namespace }} +{{- if .Values.serviceAccount.name }} + name: {{ .Values.serviceAccount.name }} +{{- else }} + name: {{ include "docker-registry.fullname" . }} +{{- end }} +{{- if .Values.serviceAccount.annotations }} + annotations: +{{ toYaml .Values.serviceAccount.annotations | indent 4 }} +{{- end }} +{{- end -}} diff --git a/backing-services/docker-registry/templates/servicemonitor.yaml b/backing-services/docker-registry/templates/servicemonitor.yaml new file mode 100644 index 0000000..ece2160 --- /dev/null +++ b/backing-services/docker-registry/templates/servicemonitor.yaml @@ -0,0 +1,21 @@ +{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled -}} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "docker-registry.fullname" . }}-servicemonitor + labels: + app: {{ template "docker-registry.name" . }}-metrics + release: {{ .Release.Name }} +{{- if .Values.metrics.serviceMonitor.labels }} +{{ toYaml .Values.metrics.serviceMonitor.labels | indent 4 }} +{{- end }} +spec: + selector: + matchLabels: + app: {{ template "docker-registry.name" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + endpoints: + - port: http-metrics + interval: 15s +{{- end }} diff --git a/backing-services/docker-registry/values-afta.yaml b/backing-services/docker-registry/values-afta.yaml new file mode 100644 index 0000000..463e835 --- /dev/null +++ b/backing-services/docker-registry/values-afta.yaml @@ -0,0 +1,231 @@ +# Default values for docker-registry. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +replicaCount: 1 + +updateStrategy: {} + # type: RollingUpdate + # rollingUpdate: + # maxSurge: 1 + # maxUnavailable: 0 + +podAnnotations: {} +podLabels: {} + +serviceAccount: + create: false + name: "" + annotations: {} + +image: + repository: registry + tag: 2.8.1 + pullPolicy: IfNotPresent +# imagePullSecrets: + # - name: docker +deployment: {} + # annotations: +service: + name: registry + type: NodePort + # sessionAffinity: None + # sessionAffinityConfig: {} + # clusterIP: + port: 5000 + nodePort: 30500 + # loadBalancerIP: + # loadBalancerSourceRanges: + annotations: {} + # foo.io/bar: "true" +ingress: + enabled: false + className: nginx + path: / + # Used to create an Ingress record. + hosts: + - chart-example.local + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + labels: {} + tls: + # Secrets must be manually created in the namespace. + # - secretName: chart-example-tls + # hosts: + # - chart-example.local +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi +persistence: + accessMode: 'ReadWriteOnce' + enabled: false + size: 5Gi + # storageClass: '-' + +# set the type of filesystem to use: filesystem, s3 +storage: filesystem + +# Set this to name of secret for tls certs +# tlsSecretName: registry.docker.example.com +secrets: + haSharedSecret: "" + htpasswd: "" +# Secrets for Azure +# azure: +# accountName: "" +# accountKey: "" +# container: "" +# Secrets for S3 access and secret keys +# Use a secretRef with keys (accessKey, secretKey) for secrets stored outside the chart +# s3: +# secretRef: "" +# accessKey: "" +# secretKey: "" +# Secrets for Swift username and password +# swift: +# username: "" +# password: "" + +# Options for s3 storage type: +# s3: +# region: us-east-1 +# regionEndpoint: s3.us-east-1.amazonaws.com +# bucket: my-bucket +# rootdirectory: /object/prefix +# encrypt: false +# secure: true + +# Options for swift storage type: +# swift: +# authurl: http://swift.example.com/ +# container: my-container + +# https://docs.docker.com/registry/recipes/mirror/ +proxy: + enabled: false + remoteurl: https://registry-1.docker.io + username: "" + password: "" + # the ref for a secret stored outside of this chart + # Keys: proxyUsername, proxyPassword + secretRef: "" + +metrics: + enabled: false + port: 5001 + # Create a prometheus-operator servicemonitor + serviceMonitor: + enabled: false + labels: {} + # prometheus-operator PrometheusRule defining alerting rules for a Prometheus instance + prometheusRule: + enabled: false + labels: {} + rules: {} + +configData: + version: 0.1 + log: + fields: + service: registry + storage: + cache: + blobdescriptor: inmemory + http: + addr: :5000 + headers: + X-Content-Type-Options: [nosniff] + debug: + addr: :5001 + prometheus: + enabled: false + path: /metrics + health: + storagedriver: + enabled: true + interval: 10s + threshold: 3 + +containerSecurityContext: + enabled: false + +securityContext: + enabled: true + runAsUser: 1000 + fsGroup: 1000 + +priorityClassName: "" + +podDisruptionBudget: {} + # maxUnavailable: 1 + # minAvailable: 2 + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 2 + targetCPUUtilizationPercentage: 60 + targetMemoryUtilizationPercentage: 60 # available only on Kubernetes ≥1.23 [required "autoscaling/v2"] + behavior: {} # available only on Kubernetes ≥1.23 [required "autoscaling/v2"] +# scaleDown: +# stabilizationWindowSeconds: 300 +# policies: +# - type: Percent +# value: 100 +# periodSeconds: 15 +# scaleUp: +# stabilizationWindowSeconds: 0 +# policies: +# - type: Percent +# value: 100 +# periodSeconds: 15 +# - type: Pods +# value: 4 +# periodSeconds: 15 +# selectPolicy: Max + +nodeSelector: {} + +affinity: {} + +tolerations: [] + +extraVolumeMounts: [] +## Additional volumeMounts to the registry container. +# - mountPath: /secret-data +# name: cloudfront-pem-secret +# readOnly: true + +extraVolumes: [] +## Additional volumes to the pod. +# - name: cloudfront-pem-secret +# secret: +# secretName: cloudfront-credentials +# items: +# - key: cloudfront.pem +# path: cloudfront.pem +# mode: 511 + +extraEnvVars: [] +## Additional ENV variables to set +# - name: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY +# value: "/var/lib/example" + +initContainers: [] +## Init containers to add to the Deployment +# - name: init +# image: busybox +# command: [] + +garbageCollect: + enabled: false + deleteUntagged: true + schedule: "0 1 * * *" diff --git a/backing-services/docker-registry/values.yaml b/backing-services/docker-registry/values.yaml new file mode 100644 index 0000000..4c000e3 --- /dev/null +++ b/backing-services/docker-registry/values.yaml @@ -0,0 +1,231 @@ +# Default values for docker-registry. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +replicaCount: 1 + +updateStrategy: {} + # type: RollingUpdate + # rollingUpdate: + # maxSurge: 1 + # maxUnavailable: 0 + +podAnnotations: {} +podLabels: {} + +serviceAccount: + create: false + name: "" + annotations: {} + +image: + repository: registry + tag: 2.8.1 + pullPolicy: IfNotPresent +# imagePullSecrets: + # - name: docker +deployment: {} + # annotations: +service: + name: registry + type: ClusterIP + # sessionAffinity: None + # sessionAffinityConfig: {} + # clusterIP: + port: 5000 + # nodePort: + # loadBalancerIP: + # loadBalancerSourceRanges: + annotations: {} + # foo.io/bar: "true" +ingress: + enabled: false + className: nginx + path: / + # Used to create an Ingress record. + hosts: + - chart-example.local + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + labels: {} + tls: + # Secrets must be manually created in the namespace. + # - secretName: chart-example-tls + # hosts: + # - chart-example.local +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi +persistence: + accessMode: 'ReadWriteOnce' + enabled: false + size: 10Gi + # storageClass: '-' + +# set the type of filesystem to use: filesystem, s3 +storage: filesystem + +# Set this to name of secret for tls certs +# tlsSecretName: registry.docker.example.com +secrets: + haSharedSecret: "" + htpasswd: "" +# Secrets for Azure +# azure: +# accountName: "" +# accountKey: "" +# container: "" +# Secrets for S3 access and secret keys +# Use a secretRef with keys (accessKey, secretKey) for secrets stored outside the chart +# s3: +# secretRef: "" +# accessKey: "" +# secretKey: "" +# Secrets for Swift username and password +# swift: +# username: "" +# password: "" + +# Options for s3 storage type: +# s3: +# region: us-east-1 +# regionEndpoint: s3.us-east-1.amazonaws.com +# bucket: my-bucket +# rootdirectory: /object/prefix +# encrypt: false +# secure: true + +# Options for swift storage type: +# swift: +# authurl: http://swift.example.com/ +# container: my-container + +# https://docs.docker.com/registry/recipes/mirror/ +proxy: + enabled: false + remoteurl: https://registry-1.docker.io + username: "" + password: "" + # the ref for a secret stored outside of this chart + # Keys: proxyUsername, proxyPassword + secretRef: "" + +metrics: + enabled: false + port: 5001 + # Create a prometheus-operator servicemonitor + serviceMonitor: + enabled: false + labels: {} + # prometheus-operator PrometheusRule defining alerting rules for a Prometheus instance + prometheusRule: + enabled: false + labels: {} + rules: {} + +configData: + version: 0.1 + log: + fields: + service: registry + storage: + cache: + blobdescriptor: inmemory + http: + addr: :5000 + headers: + X-Content-Type-Options: [nosniff] + debug: + addr: :5001 + prometheus: + enabled: false + path: /metrics + health: + storagedriver: + enabled: true + interval: 10s + threshold: 3 + +containerSecurityContext: + enabled: false + +securityContext: + enabled: true + runAsUser: 1000 + fsGroup: 1000 + +priorityClassName: "" + +podDisruptionBudget: {} + # maxUnavailable: 1 + # minAvailable: 2 + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 2 + targetCPUUtilizationPercentage: 60 + targetMemoryUtilizationPercentage: 60 # available only on Kubernetes ≥1.23 [required "autoscaling/v2"] + behavior: {} # available only on Kubernetes ≥1.23 [required "autoscaling/v2"] +# scaleDown: +# stabilizationWindowSeconds: 300 +# policies: +# - type: Percent +# value: 100 +# periodSeconds: 15 +# scaleUp: +# stabilizationWindowSeconds: 0 +# policies: +# - type: Percent +# value: 100 +# periodSeconds: 15 +# - type: Pods +# value: 4 +# periodSeconds: 15 +# selectPolicy: Max + +nodeSelector: {} + +affinity: {} + +tolerations: [] + +extraVolumeMounts: [] +## Additional volumeMounts to the registry container. +# - mountPath: /secret-data +# name: cloudfront-pem-secret +# readOnly: true + +extraVolumes: [] +## Additional volumes to the pod. +# - name: cloudfront-pem-secret +# secret: +# secretName: cloudfront-credentials +# items: +# - key: cloudfront.pem +# path: cloudfront.pem +# mode: 511 + +extraEnvVars: [] +## Additional ENV variables to set +# - name: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY +# value: "/var/lib/example" + +initContainers: [] +## Init containers to add to the Deployment +# - name: init +# image: busybox +# command: [] + +garbageCollect: + enabled: false + deleteUntagged: true + schedule: "0 1 * * *" diff --git a/backing-services/elasticsearch/.helmignore b/backing-services/elasticsearch/.helmignore new file mode 100644 index 0000000..e12c0b4 --- /dev/null +++ b/backing-services/elasticsearch/.helmignore @@ -0,0 +1,2 @@ +tests/ +.pytest_cache/ diff --git a/backing-services/elasticsearch/Chart.yaml b/backing-services/elasticsearch/Chart.yaml new file mode 100644 index 0000000..df17757 --- /dev/null +++ b/backing-services/elasticsearch/Chart.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +appVersion: 8.5.1 +description: Official Elastic helm chart for Elasticsearch +home: https://github.com/elastic/helm-charts +icon: https://helm.elastic.co/icons/elasticsearch.png +maintainers: +- email: helm-charts@elastic.co + name: Elastic +name: elasticsearch +sources: +- https://github.com/elastic/elasticsearch +version: 8.5.1 diff --git a/backing-services/elasticsearch/Makefile b/backing-services/elasticsearch/Makefile new file mode 100644 index 0000000..22218a1 --- /dev/null +++ b/backing-services/elasticsearch/Makefile @@ -0,0 +1 @@ +include ../helpers/common.mk diff --git a/backing-services/elasticsearch/README.md b/backing-services/elasticsearch/README.md new file mode 100644 index 0000000..a4948bd --- /dev/null +++ b/backing-services/elasticsearch/README.md @@ -0,0 +1,490 @@ +# Elasticsearch Helm Chart + +[![Build Status](https://img.shields.io/jenkins/s/https/devops-ci.elastic.co/job/elastic+helm-charts+main.svg)](https://devops-ci.elastic.co/job/elastic+helm-charts+main/) [![Artifact HUB](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/elastic)](https://artifacthub.io/packages/search?repo=elastic) + +This Helm chart is a lightweight way to configure and run our official +[Elasticsearch Docker image][]. + +> **Warning** +> When it comes to running the Elastic on Kubernetes infrastructure, we +> recommend [Elastic Cloud on Kubernetes][] (ECK) as the best way to run and manage +> the Elastic Stack. +> +> ECK offers many operational benefits for both our basic-tier and our +> enterprise-tier customers, such as spinning up cluster nodes that were lost on +> failed infrastructure, seamless upgrades, rolling cluster changes, and much +> much more. +> +> With the release of the Elastic Stack Helm charts for Elastic version 8.5.1, +> we are handing over the ongoing maintenance of our Elastic Stack Helm charts +> to the community and contributors. This repository will finally be archived +> after 6 months time. Elastic Stacks deployed on Kubernetes through Helm charts +> will still be fully supported under EOL limitations. +> +> Since we want to provide an even better experience for our customers by +> running the Elastic Stack on Kubernetes, we will continue maintaining the +> Helm charts applicable to ECK Custom Resources. These charts can be found in +> the [ECK repository][eck-charts]. +> +> Helm charts will currently be maintained for ECK Enterprise-tier customers, +> however, we encourage the community to engage with the existing Helm charts +> for the Elastic Stack and continue supporting their ongoing maintenance. +> +> See for more details. + + + + + +- [Requirements](#requirements) +- [Installing](#installing) + - [Install a released version using the Helm repository](#install-a-released-version-using-the-helm-repository) + - [Install a development version using the main branch](#install-a-development-version-using-the-main-branch) +- [Upgrading](#upgrading) +- [Usage notes](#usage-notes) +- [Configuration](#configuration) +- [FAQ](#faq) + - [How to deploy this chart on a specific K8S distribution?](#how-to-deploy-this-chart-on-a-specific-k8s-distribution) + - [How to deploy dedicated nodes types?](#how-to-deploy-dedicated-nodes-types) + - [Coordinating nodes](#coordinating-nodes) + - [Clustering and Node Discovery](#clustering-and-node-discovery) + - [How to deploy clusters with security (authentication and TLS) enabled?](#how-to-deploy-clusters-with-security-authentication-and-tls-enabled) + - [How to migrate from helm/charts stable chart?](#how-to-migrate-from-helmcharts-stable-chart) + - [How to install plugins?](#how-to-install-plugins) + - [How to use the keystore?](#how-to-use-the-keystore) + - [Basic example](#basic-example) + - [Multiple keys](#multiple-keys) + - [Custom paths and keys](#custom-paths-and-keys) + - [How to enable snapshotting?](#how-to-enable-snapshotting) + - [How to configure templates post-deployment?](#how-to-configure-templates-post-deployment) +- [Contributing](#contributing) + + + + + + +## Requirements + +* Minimum cluster requirements include the following to run this chart with +default settings. All of these settings are configurable. + * Three Kubernetes nodes to respect the default "hard" affinity settings + * 1GB of RAM for the JVM heap + +See [supported configurations][] for more details. + + +## Installing + +### Install a released version using the Helm repository + +* Add the Elastic Helm charts repo: +`helm repo add elastic https://helm.elastic.co` + +* Install it: `helm install elasticsearch elastic/elasticsearch` + +### Install a development version using the main branch + +* Clone the git repo: `git clone git@github.com:elastic/helm-charts.git` + +* Install it: `helm install elasticsearch ./helm-charts/elasticsearch --set imageTag=8.5.1` + +## Upgrading + +Please always check [CHANGELOG.md][] and [BREAKING_CHANGES.md][] before +upgrading to a new chart version. + + +## Usage notes + +* This repo includes several [examples][] of configurations that can be used +as a reference. They are also used in the automated testing of this chart. +* Automated testing of this chart is currently only run against GKE (Google +Kubernetes Engine). +* The chart deploys a StatefulSet and by default will do an automated rolling +update of your cluster. It does this by waiting for the cluster health to become +green after each instance is updated. If you prefer to update manually you can +set `OnDelete` [updateStrategy][]. +* It is important to verify that the JVM heap size in `esJavaOpts` and to set +the CPU/Memory `resources` to something suitable for your cluster. +* To simplify chart and maintenance each set of node groups is deployed as a +separate Helm release. Take a look at the [multi][] example to get an idea for +how this works. Without doing this it isn't possible to resize persistent +volumes in a StatefulSet. By setting it up this way it makes it possible to add +more nodes with a new storage size then drain the old ones. It also solves the +problem of allowing the user to determine which node groups to update first when +doing upgrades or changes. +* We have designed this chart to be very un-opinionated about how to configure +Elasticsearch. It exposes ways to set environment variables and mount secrets +inside of the container. Doing this makes it much easier for this chart to +support multiple versions with minimal changes. + + +## Configuration + +| Parameter | Description | Default | +|------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------| +| `antiAffinityTopologyKey` | The [anti-affinity][] topology key. By default this will prevent multiple Elasticsearch nodes from running on the same Kubernetes node | `kubernetes.io/hostname` | +| `antiAffinity` | Setting this to hard enforces the [anti-affinity][] rules. If it is set to soft it will be done "best effort". Other values will be ignored | `hard` | +| `clusterHealthCheckParams` | The [Elasticsearch cluster health status params][] that will be used by readiness [probe][] command | `wait_for_status=green&timeout=1s` | +| `clusterName` | This will be used as the Elasticsearch [cluster.name][] and should be unique per cluster in the namespace | `elasticsearch` | +| `createCert` | This will automatically create the SSL certificates | `true` | +| `enableServiceLinks` | Set to false to disabling service links, which can cause slow pod startup times when there are many services in the current namespace. | `true` | +| `envFrom` | Templatable string to be passed to the [environment from variables][] which will be appended to the `envFrom:` definition for the container | `[]` | +| `esConfig` | Allows you to add any config files in `/usr/share/elasticsearch/config/` such as `elasticsearch.yml` and `log4j2.properties`. See [values.yaml][] for an example of the formatting | `{}` | +| `esJavaOpts` | [Java options][] for Elasticsearch. This is where you could configure the [jvm heap size][] | `""` | +| `esJvmOptions` | [Java options][] for Elasticsearch. Override the default JVM options by adding custom options files . See [values.yaml][] for an example of the formatting | `{}` | +| `esMajorVersion` | Deprecated. Instead, use the version of the chart corresponding to your ES minor version. Used to set major version specific configuration. If you are using a custom image and not running the default Elasticsearch version you will need to set this to the version you are running (e.g. `esMajorVersion: 6`) | `""` | +| `extraContainers` | Templatable string of additional `containers` to be passed to the `tpl` function | `""` | +| `extraEnvs` | Extra [environment variables][] which will be appended to the `env:` definition for the container | `[]` | +| `extraInitContainers` | Templatable string of additional `initContainers` to be passed to the `tpl` function | `""` | +| `extraVolumeMounts` | Templatable string of additional `volumeMounts` to be passed to the `tpl` function | `""` | +| `extraVolumes` | Templatable string of additional `volumes` to be passed to the `tpl` function | `""` | +| `fullnameOverride` | Overrides the `clusterName` and `nodeGroup` when used in the naming of resources. This should only be used when using a single `nodeGroup`, otherwise you will have name conflicts | `""` | +| `healthNameOverride` | Overrides `test-elasticsearch-health` pod name | `""` | +| `hostAliases` | Configurable [hostAliases][] | `[]` | +| `httpPort` | The http port that Kubernetes will use for the healthchecks and the service. If you change this you will also need to set [http.port][] in `extraEnvs` | `9200` | +| `imagePullPolicy` | The Kubernetes [imagePullPolicy][] value | `IfNotPresent` | +| `imagePullSecrets` | Configuration for [imagePullSecrets][] so that you can use a private registry for your image | `[]` | +| `imageTag` | The Elasticsearch Docker image tag | `8.5.1` | +| `image` | The Elasticsearch Docker image | `docker.elastic.co/elasticsearch/elasticsearch` | +| `ingress` | Configurable [ingress][] to expose the Elasticsearch service. See [values.yaml][] for an example | see [values.yaml][] | +| `initResources` | Allows you to set the [resources][] for the `initContainer` in the StatefulSet | `{}` | +| `keystore` | Allows you map Kubernetes secrets into the keystore. See the [config example][] and [how to use the keystore][] | `[]` | +| `labels` | Configurable [labels][] applied to all Elasticsearch pods | `{}` | +| `lifecycle` | Allows you to add [lifecycle hooks][]. See [values.yaml][] for an example of the formatting | `{}` | +| `masterService` | The service name used to connect to the masters. You only need to set this if your master `nodeGroup` is set to something other than `master`. See [Clustering and Node Discovery][] for more information | `""` | +| `maxUnavailable` | The [maxUnavailable][] value for the pod disruption budget. By default this will prevent Kubernetes from having more than 1 unhealthy pod in the node group | `1` | +| `minimumMasterNodes` | The value for [discovery.zen.minimum_master_nodes][]. Should be set to `(master_eligible_nodes / 2) + 1`. Ignored in Elasticsearch versions >= 7 | `2` | +| `nameOverride` | Overrides the `clusterName` when used in the naming of resources | `""` | +| `networkHost` | Value for the [network.host Elasticsearch setting][] | `0.0.0.0` | +| `networkPolicy` | The [NetworkPolicy](https://kubernetes.io/docs/concepts/services-networking/network-policies/) to set. See [`values.yaml`](./values.yaml) for an example | `{http.enabled: false,transport.enabled: false}` | +| `nodeAffinity` | Value for the [node affinity settings][] | `{}` | +| `nodeGroup` | This is the name that will be used for each group of nodes in the cluster. The name will be `clusterName-nodeGroup-X` , `nameOverride-nodeGroup-X` if a `nameOverride` is specified, and `fullnameOverride-X` if a `fullnameOverride` is specified | `master` | +| `nodeSelector` | Configurable [nodeSelector][] so that you can target specific nodes for your Elasticsearch cluster | `{}` | +| `persistence` | Enables a persistent volume for Elasticsearch data. Can be disabled for nodes that only have [roles][] which don't require persistent data | see [values.yaml][] | +| `podAnnotations` | Configurable [annotations][] applied to all Elasticsearch pods | `{}` | +| `podManagementPolicy` | By default Kubernetes [deploys StatefulSets serially][]. This deploys them in parallel so that they can discover each other | `Parallel` | +| `podSecurityContext` | Allows you to set the [securityContext][] for the pod | see [values.yaml][] | +| `podSecurityPolicy` | Configuration for create a pod security policy with minimal permissions to run this Helm chart with `create: true`. Also can be used to reference an external pod security policy with `name: "externalPodSecurityPolicy"` | see [values.yaml][] | +| `priorityClassName` | The name of the [PriorityClass][]. No default is supplied as the PriorityClass must be created first | `""` | +| `protocol` | The protocol that will be used for the readiness [probe][]. Change this to `https` if you have `xpack.security.http.ssl.enabled` set | `http` | +| `rbac` | Configuration for creating a role, role binding and ServiceAccount as part of this Helm chart with `create: true`. Also can be used to reference an external ServiceAccount with `serviceAccountName: "externalServiceAccountName"`, or automount the service account token | see [values.yaml][] | +| `readinessProbe` | Configuration fields for the readiness [probe][] | see [values.yaml][] | +| `replicas` | Kubernetes replica count for the StatefulSet (i.e. how many pods) | `3` | +| `resources` | Allows you to set the [resources][] for the StatefulSet | see [values.yaml][] | +| `roles` | A list with the specific [roles][] for the `nodeGroup` | see [values.yaml][] | +| `schedulerName` | Name of the [alternate scheduler][] | `""` | +| `secret.enabled` | Enable Secret creation for Elasticsearch credentials | `true` | +| `secret.password` | Initial password for the elastic user | `""` (generated randomly) | +| `secretMounts` | Allows you easily mount a secret as a file inside the StatefulSet. Useful for mounting certificates and other secrets. See [values.yaml][] for an example | `[]` | +| `securityContext` | Allows you to set the [securityContext][] for the container | see [values.yaml][] | +| `service.annotations` | [LoadBalancer annotations][] that Kubernetes will use for the service. This will configure load balancer if `service.type` is `LoadBalancer` | `{}` | +| `service.enabled` | Enable non-headless service | `true` | +| `service.externalTrafficPolicy` | Some cloud providers allow you to specify the [LoadBalancer externalTrafficPolicy][]. Kubernetes will use this to preserve the client source IP. This will configure load balancer if `service.type` is `LoadBalancer` | `""` | +| `service.httpPortName` | The name of the http port within the service | `http` | +| `service.labelsHeadless` | Labels to be added to headless service | `{}` | +| `service.labels` | Labels to be added to non-headless service | `{}` | +| `service.loadBalancerIP` | Some cloud providers allow you to specify the [loadBalancer][] IP. If the `loadBalancerIP` field is not specified, the IP is dynamically assigned. If you specify a `loadBalancerIP` but your cloud provider does not support the feature, it is ignored. | `""` | +| `service.loadBalancerSourceRanges` | The IP ranges that are allowed to access | `[]` | +| `service.nodePort` | Custom [nodePort][] port that can be set if you are using `service.type: nodePort` | `""` | +| `service.transportPortName` | The name of the transport port within the service | `transport` | +| `service.publishNotReadyAddresses` | Consider that all endpoints are considered "ready" even if the Pods themselves are not | `false` | +| `service.type` | Elasticsearch [Service Types][] | `ClusterIP` | +| `sysctlInitContainer` | Allows you to disable the `sysctlInitContainer` if you are setting [sysctl vm.max_map_count][] with another method | `enabled: true` | +| `sysctlVmMaxMapCount` | Sets the [sysctl vm.max_map_count][] needed for Elasticsearch | `262144` | +| `terminationGracePeriod` | The [terminationGracePeriod][] in seconds used when trying to stop the pod | `120` | +| `tests.enabled` | Enable creating test related resources when running `helm template` or `helm test` | `true` | +| `tolerations` | Configurable [tolerations][] | `[]` | +| `transportPort` | The transport port that Kubernetes will use for the service. If you change this you will also need to set [transport port configuration][] in `extraEnvs` | `9300` | +| `updateStrategy` | The [updateStrategy][] for the StatefulSet. By default Kubernetes will wait for the cluster to be green after upgrading each pod. Setting this to `OnDelete` will allow you to manually delete each pod during upgrades | `RollingUpdate` | +| `volumeClaimTemplate` | Configuration for the [volumeClaimTemplate for StatefulSets][]. You will want to adjust the storage (default `30Gi` ) and the `storageClassName` if you are using a different storage class | see [values.yaml][] | + + +## FAQ + +### How to deploy this chart on a specific K8S distribution? + +This chart is designed to run on production scale Kubernetes clusters with +multiple nodes, lots of memory and persistent storage. For that reason it can be +a bit tricky to run them against local Kubernetes environments such as +[Minikube][]. + +This chart is highly tested with [GKE][], but some K8S distribution also +requires specific configurations. + +We provide examples of configuration for the following K8S providers: + +- [Docker for Mac][] +- [KIND][] +- [Minikube][] +- [MicroK8S][] +- [OpenShift][] + +### How to deploy dedicated nodes types? + +All the Elasticsearch pods deployed share the same configuration. If you need to +deploy dedicated [nodes types][] (for example dedicated master and data nodes), +you can deploy multiple releases of this chart with different configurations +while they share the same `clusterName` value. + +For each Helm release, the nodes types can then be defined using `roles` value. + +An example of Elasticsearch cluster using 2 different Helm releases for master, +data and coordinating nodes can be found in [examples/multi][]. + +#### Coordinating nodes + +Every node is implicitly a coordinating node. This means that a node that has an +explicit empty list of roles will only act as a coordinating node. + +When deploying coordinating-only node with Elasticsearch chart, it is required +to define the empty list of roles in both `roles` value and `node.roles` +settings: + +```yaml +roles: [] + +esConfig: + elasticsearch.yml: | + node.roles: [] +``` + +More details in [#1186 (comment)][] + +#### Clustering and Node Discovery + +This chart facilitates Elasticsearch node discovery and services by creating two +`Service` definitions in Kubernetes, one with the name `$clusterName-$nodeGroup` +and another named `$clusterName-$nodeGroup-headless`. +Only `Ready` pods are a part of the `$clusterName-$nodeGroup` service, while all +pods ( `Ready` or not) are a part of `$clusterName-$nodeGroup-headless`. + +If your group of master nodes has the default `nodeGroup: master` then you can +just add new groups of nodes with a different `nodeGroup` and they will +automatically discover the correct master. If your master nodes have a different +`nodeGroup` name then you will need to set `masterService` to +`$clusterName-$masterNodeGroup`. + +The chart value for `masterService` is used to populate +`discovery.zen.ping.unicast.hosts` , which Elasticsearch nodes will use to +contact master nodes and form a cluster. +Therefore, to add a group of nodes to an existing cluster, setting +`masterService` to the desired `Service` name of the related cluster is +sufficient. + +### How to deploy clusters with security (authentication and TLS) enabled? + +This Helm chart can generate a [Kubernetes Secret][] or use an existing one to +setup Elastic credentials. + +This Helm chart can use existing [Kubernetes Secret][] to setup Elastic +certificates for example. These secrets should be created outside of this chart +and accessed using [environment variables][] and volumes. + +This chart is setting TLS and creating a certificate by default, but you can also provide your own certs as a K8S secret. An example of configuration for providing existing certificates can be found in [examples/security][]. + +### How to migrate from helm/charts stable chart? + +If you currently have a cluster deployed with the [helm/charts stable][] chart +you can follow the [migration guide][]. + +### How to install plugins? + +The recommended way to install plugins into our Docker images is to create a +[custom Docker image][]. + +The Dockerfile would look something like: + +``` +ARG elasticsearch_version +FROM docker.elastic.co/elasticsearch/elasticsearch:${elasticsearch_version} + +RUN bin/elasticsearch-plugin install --batch repository-gcs +``` + +And then updating the `image` in values to point to your custom image. + +There are a couple reasons we recommend this. + +1. Tying the availability of Elasticsearch to the download service to install +plugins is not a great idea or something that we recommend. Especially in +Kubernetes where it is normal and expected for a container to be moved to +another host at random times. +2. Mutating the state of a running Docker image (by installing plugins) goes +against best practices of containers and immutable infrastructure. + +### How to use the keystore? + +#### Basic example + +Create the secret, the key name needs to be the keystore key path. In this +example we will create a secret from a file and from a literal string. + +``` +kubectl create secret generic encryption-key --from-file=xpack.watcher.encryption_key=./watcher_encryption_key +kubectl create secret generic slack-hook --from-literal=xpack.notification.slack.account.monitoring.secure_url='https://hooks.slack.com/services/asdasdasd/asdasdas/asdasd' +``` + +To add these secrets to the keystore: + +``` +keystore: + - secretName: encryption-key + - secretName: slack-hook +``` + +#### Multiple keys + +All keys in the secret will be added to the keystore. To create the previous +example in one secret you could also do: + +``` +kubectl create secret generic keystore-secrets --from-file=xpack.watcher.encryption_key=./watcher_encryption_key --from-literal=xpack.notification.slack.account.monitoring.secure_url='https://hooks.slack.com/services/asdasdasd/asdasdas/asdasd' +``` + +``` +keystore: + - secretName: keystore-secrets +``` + +#### Custom paths and keys + +If you are using these secrets for other applications (besides the Elasticsearch +keystore) then it is also possible to specify the keystore path and which keys +you want to add. Everything specified under each `keystore` item will be passed +through to the `volumeMounts` section for mounting the [secret][]. In this +example we will only add the `slack_hook` key from a secret that also has other +keys. Our secret looks like this: + +``` +kubectl create secret generic slack-secrets --from-literal=slack_channel='#general' --from-literal=slack_hook='https://hooks.slack.com/services/asdasdasd/asdasdas/asdasd' +``` + +We only want to add the `slack_hook` key to the keystore at path +`xpack.notification.slack.account.monitoring.secure_url`: + +``` +keystore: + - secretName: slack-secrets + items: + - key: slack_hook + path: xpack.notification.slack.account.monitoring.secure_url +``` + +You can also take a look at the [config example][] which is used as part of the +automated testing pipeline. + +### How to enable snapshotting? + +1. Install your [snapshot plugin][] into a custom Docker image following the +[how to install plugins guide][]. +2. Add any required secrets or credentials into an Elasticsearch keystore +following the [how to use the keystore][] guide. +3. Configure the [snapshot repository][] as you normally would. +4. To automate snapshots you can use [Snapshot Lifecycle Management][] or a tool +like [curator][]. + +### How to configure templates post-deployment? + +You can use `postStart` [lifecycle hooks][] to run code triggered after a +container is created. + +Here is an example of `postStart` hook to configure templates: + +```yaml +lifecycle: + postStart: + exec: + command: + - bash + - -c + - | + #!/bin/bash + # Add a template to adjust number of shards/replicas + TEMPLATE_NAME=my_template + INDEX_PATTERN="logstash-*" + SHARD_COUNT=8 + REPLICA_COUNT=1 + ES_URL=http://localhost:9200 + while [[ "$(curl -s -o /dev/null -w '%{http_code}\n' $ES_URL)" != "200" ]]; do sleep 1; done + curl -XPUT "$ES_URL/_template/$TEMPLATE_NAME" -H 'Content-Type: application/json' -d'{"index_patterns":['\""$INDEX_PATTERN"\"'],"settings":{"number_of_shards":'$SHARD_COUNT',"number_of_replicas":'$REPLICA_COUNT'}}' +``` + + +## Contributing + +Please check [CONTRIBUTING.md][] before any contribution or for any questions +about our development and testing process. + +[#1186 (comment)]: https://github.com/elastic/helm-charts/pull/1186#discussion_r631166442 +[alternate scheduler]: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/#specify-schedulers-for-pods +[annotations]: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +[anti-affinity]: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +[BREAKING_CHANGES.md]: https://github.com/elastic/helm-charts/blob/main/BREAKING_CHANGES.md +[CHANGELOG.md]: https://github.com/elastic/helm-charts/blob/main/CHANGELOG.md +[cluster.name]: https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster.name.html +[clustering and node discovery]: https://github.com/elastic/helm-charts/blob/main/elasticsearch/README.md#clustering-and-node-discovery +[config example]: https://github.com/elastic/helm-charts/blob/main/elasticsearch/examples/config/values.yaml +[CONTRIBUTING.md]: https://github.com/elastic/helm-charts/blob/main/CONTRIBUTING.md +[curator]: https://www.elastic.co/guide/en/elasticsearch/client/curator/current/snapshot.html +[custom docker image]: https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html#_c_customized_image +[deploys statefulsets serially]: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#pod-management-policies +[discovery.zen.minimum_master_nodes]: https://www.elastic.co/guide/en/elasticsearch/reference/current/discovery-settings.html#minimum_master_nodes +[docker for mac]: https://github.com/elastic/helm-charts/tree/main/elasticsearch/examples/docker-for-mac +[eck-charts]: https://github.com/elastic/cloud-on-k8s/tree/master/deploy +[elastic cloud on kubernetes]: https://github.com/elastic/cloud-on-k8s +[elasticsearch cluster health status params]: https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-health.html#request-params +[elasticsearch docker image]: https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html +[environment from variables]: https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#configure-all-key-value-pairs-in-a-configmap-as-container-environment-variables +[environment variables]: https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/#using-environment-variables-inside-of-your-config +[examples]: https://github.com/elastic/helm-charts/tree/main/elasticsearch/examples/ +[examples/multi]: https://github.com/elastic/helm-charts/tree/main/elasticsearch/examples/multi +[examples/security]: https://github.com/elastic/helm-charts/tree/main/elasticsearch/examples/security +[gke]: https://cloud.google.com/kubernetes-engine +[helm]: https://helm.sh +[helm/charts stable]: https://github.com/helm/charts/tree/master/stable/elasticsearch/ +[hostAliases]: https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ +[how to install plugins guide]: https://github.com/elastic/helm-charts/blob/main/elasticsearch/README.md#how-to-install-plugins +[how to use the keystore]: https://github.com/elastic/helm-charts/blob/main/elasticsearch/README.md#how-to-use-the-keystore +[http.port]: https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-http.html#_settings +[imagePullPolicy]: https://kubernetes.io/docs/concepts/containers/images/#updating-images +[imagePullSecrets]: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/#create-a-pod-that-uses-your-secret +[ingress]: https://kubernetes.io/docs/concepts/services-networking/ingress/ +[java options]: https://www.elastic.co/guide/en/elasticsearch/reference/current/jvm-options.html +[jvm heap size]: https://www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html +[kind]: https://github.com/elastic/helm-charts/tree/main//elasticsearch/examples/kubernetes-kind +[labels]: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +[lifecycle hooks]: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/ +[loadBalancer annotations]: https://kubernetes.io/docs/concepts/services-networking/service/#ssl-support-on-aws +[loadBalancer externalTrafficPolicy]: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip +[loadBalancer]: https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer +[maxUnavailable]: https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget +[microk8s]: https://github.com/elastic/helm-charts/tree/main/elasticsearch/examples/microk8s +[migration guide]: https://github.com/elastic/helm-charts/blob/main/elasticsearch/examples/migration/README.md +[minikube]: https://github.com/elastic/helm-charts/tree/main/elasticsearch/examples/minikube +[multi]: https://github.com/elastic/helm-charts/tree/main/elasticsearch/examples/multi/ +[network.host elasticsearch setting]: https://www.elastic.co/guide/en/elasticsearch/reference/current/network.host.html +[node affinity settings]: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity-beta-feature +[nodePort]: https://kubernetes.io/docs/concepts/services-networking/service/#nodeport +[nodes types]: https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-node.html +[nodeSelector]: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector +[openshift]: https://github.com/elastic/helm-charts/tree/main/elasticsearch/examples/openshift +[priorityClass]: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass +[probe]: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/ +[resources]: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ +[roles]: https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-node.html +[secret]: https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets +[securityContext]: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ +[service types]: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types +[snapshot lifecycle management]: https://www.elastic.co/guide/en/elasticsearch/reference/current/snapshot-lifecycle-management.html +[snapshot plugin]: https://www.elastic.co/guide/en/elasticsearch/plugins/current/repository.html +[snapshot repository]: https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html +[supported configurations]: https://github.com/elastic/helm-charts/blob/main/README.md#supported-configurations +[sysctl vm.max_map_count]: https://www.elastic.co/guide/en/elasticsearch/reference/current/vm-max-map-count.html#vm-max-map-count +[terminationGracePeriod]: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods +[tolerations]: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +[transport port configuration]: https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-transport.html#_transport_settings +[updateStrategy]: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/ +[values.yaml]: https://github.com/elastic/helm-charts/blob/main/elasticsearch/values.yaml +[volumeClaimTemplate for statefulsets]: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-storage diff --git a/backing-services/elasticsearch/schoobus-onsite.values.yaml b/backing-services/elasticsearch/schoobus-onsite.values.yaml new file mode 100644 index 0000000..1ff5d06 --- /dev/null +++ b/backing-services/elasticsearch/schoobus-onsite.values.yaml @@ -0,0 +1,356 @@ +--- +clusterName: "elasticsearch" +nodeGroup: "master" + +# The service that non master groups will try to connect to when joining the cluster +# This should be set to clusterName + "-" + nodeGroup for your master group +masterService: "" + +# Elasticsearch roles that will be applied to this nodeGroup +# These will be set as environment variables. E.g. node.roles=master +# https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-node.html#node-roles +roles: + - master + - data + - data_content + - data_hot + - data_warm + - data_cold + - ingest + - ml + - remote_cluster_client + - transform + +replicas: 2 +minimumMasterNodes: 1 + +esMajorVersion: "" + +# Allows you to add any config files in /usr/share/elasticsearch/config/ +# such as elasticsearch.yml and log4j2.properties +esConfig: {} +# elasticsearch.yml: | +# key: +# nestedkey: value +# log4j2.properties: | +# key = value + +createCert: true + +esJvmOptions: {} +# processors.options: | +# -XX:ActiveProcessorCount=3 + +# Extra environment variables to append to this nodeGroup +# This will be appended to the current 'env:' key. You can use any of the kubernetes env +# syntax here +extraEnvs: [] +# - name: MY_ENVIRONMENT_VAR +# value: the_value_goes_here + +# Allows you to load environment variables from kubernetes secret or config map +envFrom: [] +# - secretRef: +# name: env-secret +# - configMapRef: +# name: config-map + +# Disable it to use your own elastic-credential Secret. +secret: + enabled: true + password: "" # generated randomly if not defined + +# A list of secrets and their paths to mount inside the pod +# This is useful for mounting certificates for security and for mounting +# the X-Pack license +secretMounts: [] +# - name: elastic-certificates +# secretName: elastic-certificates +# path: /usr/share/elasticsearch/config/certs +# defaultMode: 0755 + +hostAliases: [] +#- ip: "127.0.0.1" +# hostnames: +# - "foo.local" +# - "bar.local" + +image: "docker.elastic.co/elasticsearch/elasticsearch" +imageTag: "8.5.1" +imagePullPolicy: "IfNotPresent" + +podAnnotations: {} +# iam.amazonaws.com/role: es-cluster + +# additionals labels +labels: {} + +esJavaOpts: "" # example: "-Xmx1g -Xms1g" + +resources: + requests: + cpu: "1000m" + memory: "2Gi" + limits: + cpu: "1000m" + memory: "2Gi" + +initResources: {} +# limits: +# cpu: "25m" +# # memory: "128Mi" +# requests: +# cpu: "25m" +# memory: "128Mi" + +networkHost: "0.0.0.0" + +volumeClaimTemplate: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 30Gi + +rbac: + create: false + serviceAccountAnnotations: {} + serviceAccountName: "" + automountToken: true + +podSecurityPolicy: + create: false + name: "" + spec: + privileged: true + fsGroup: + rule: RunAsAny + runAsUser: + rule: RunAsAny + seLinux: + rule: RunAsAny + supplementalGroups: + rule: RunAsAny + volumes: + - secret + - configMap + - persistentVolumeClaim + - emptyDir + +persistence: + enabled: true + labels: + # Add default labels for the volumeClaimTemplate of the StatefulSet + enabled: false + annotations: {} + +extraVolumes: [] +# - name: extras +# emptyDir: {} + +extraVolumeMounts: [] +# - name: extras +# mountPath: /usr/share/extras +# readOnly: true + +extraContainers: [] +# - name: do-something +# image: busybox +# command: ['do', 'something'] + +extraInitContainers: [] +# - name: do-something +# image: busybox +# command: ['do', 'something'] + +# This is the PriorityClass settings as defined in +# https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass +priorityClassName: "" + +# By default this will make sure two pods don't end up on the same node +# Changing this to a region would allow you to spread pods across regions +antiAffinityTopologyKey: "kubernetes.io/hostname" + +# Hard means that by default pods will only be scheduled if there are enough nodes for them +# and that they will never end up on the same node. Setting this to soft will do this "best effort" +antiAffinity: "hard" + +# This is the node affinity settings as defined in +# https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity-beta-feature +nodeAffinity: {} + +# The default is to deploy all pods serially. By setting this to parallel all pods are started at +# the same time when bootstrapping the cluster +podManagementPolicy: "Parallel" + +# The environment variables injected by service links are not used, but can lead to slow Elasticsearch boot times when +# there are many services in the current namespace. +# If you experience slow pod startups you probably want to set this to `false`. +enableServiceLinks: true + +protocol: https +httpPort: 9200 +transportPort: 9300 + +service: + enabled: true + labels: {} + labelsHeadless: {} + type: ClusterIP + # Consider that all endpoints are considered "ready" even if the Pods themselves are not + # https://kubernetes.io/docs/reference/kubernetes-api/service-resources/service-v1/#ServiceSpec + publishNotReadyAddresses: false + nodePort: "" + annotations: {} + httpPortName: http + transportPortName: transport + loadBalancerIP: "" + loadBalancerSourceRanges: [] + externalTrafficPolicy: "" + +updateStrategy: RollingUpdate + +# This is the max unavailable setting for the pod disruption budget +# The default value of 1 will make sure that kubernetes won't allow more than 1 +# of your pods to be unavailable during maintenance +maxUnavailable: 1 + +podSecurityContext: + fsGroup: 1000 + runAsUser: 1000 + +securityContext: + capabilities: + drop: + - ALL + # readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + +# How long to wait for elasticsearch to stop gracefully +terminationGracePeriod: 120 + +sysctlVmMaxMapCount: 262144 + +readinessProbe: + failureThreshold: 3 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 3 + timeoutSeconds: 5 + +# https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-health.html#request-params wait_for_status +clusterHealthCheckParams: "wait_for_status=green&timeout=1s" + +## Use an alternate scheduler. +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +schedulerName: "" + +imagePullSecrets: [] +nodeSelector: {} +tolerations: [] + +# Enabling this will publicly expose your Elasticsearch instance. +# Only enable this if you have security enabled on your cluster +ingress: + enabled: false + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + className: "nginx" + pathtype: ImplementationSpecific + hosts: + - host: chart-example.local + paths: + - path: / + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +nameOverride: "" +fullnameOverride: "" +healthNameOverride: "" + +lifecycle: {} +# preStop: +# exec: +# command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"] +# postStart: +# exec: +# command: +# - bash +# - -c +# - | +# #!/bin/bash +# # Add a template to adjust number of shards/replicas +# TEMPLATE_NAME=my_template +# INDEX_PATTERN="logstash-*" +# SHARD_COUNT=8 +# REPLICA_COUNT=1 +# ES_URL=http://localhost:9200 +# while [[ "$(curl -s -o /dev/null -w '%{http_code}\n' $ES_URL)" != "200" ]]; do sleep 1; done +# curl -XPUT "$ES_URL/_template/$TEMPLATE_NAME" -H 'Content-Type: application/json' -d'{"index_patterns":['\""$INDEX_PATTERN"\"'],"settings":{"number_of_shards":'$SHARD_COUNT',"number_of_replicas":'$REPLICA_COUNT'}}' + +sysctlInitContainer: + enabled: true + +keystore: [] + +networkPolicy: + ## Enable creation of NetworkPolicy resources. Only Ingress traffic is filtered for now. + ## In order for a Pod to access Elasticsearch, it needs to have the following label: + ## {{ template "uname" . }}-client: "true" + ## Example for default configuration to access HTTP port: + ## elasticsearch-master-http-client: "true" + ## Example for default configuration to access transport port: + ## elasticsearch-master-transport-client: "true" + + http: + enabled: false + ## if explicitNamespacesSelector is not set or set to {}, only client Pods being in the networkPolicy's namespace + ## and matching all criteria can reach the DB. + ## But sometimes, we want the Pods to be accessible to clients from other namespaces, in this case, we can use this + ## parameter to select these namespaces + ## + # explicitNamespacesSelector: + # # Accept from namespaces with all those different rules (only from whitelisted Pods) + # matchLabels: + # role: frontend + # matchExpressions: + # - {key: role, operator: In, values: [frontend]} + + ## Additional NetworkPolicy Ingress "from" rules to set. Note that all rules are OR-ed. + ## + # additionalRules: + # - podSelector: + # matchLabels: + # role: frontend + # - podSelector: + # matchExpressions: + # - key: role + # operator: In + # values: + # - frontend + + transport: + ## Note that all Elasticsearch Pods can talk to themselves using transport port even if enabled. + enabled: false + # explicitNamespacesSelector: + # matchLabels: + # role: frontend + # matchExpressions: + # - {key: role, operator: In, values: [frontend]} + # additionalRules: + # - podSelector: + # matchLabels: + # role: frontend + # - podSelector: + # matchExpressions: + # - key: role + # operator: In + # values: + # - frontend + +tests: + enabled: true diff --git a/backing-services/elasticsearch/templates/NOTES.txt b/backing-services/elasticsearch/templates/NOTES.txt new file mode 100644 index 0000000..752526f --- /dev/null +++ b/backing-services/elasticsearch/templates/NOTES.txt @@ -0,0 +1,8 @@ +1. Watch all cluster members come up. + $ kubectl get pods --namespace={{ .Release.Namespace }} -l app={{ template "elasticsearch.uname" . }} -w +2. Retrieve elastic user's password. + $ kubectl get secrets --namespace={{ .Release.Namespace }} {{ template "elasticsearch.uname" . }}-credentials -ojsonpath='{.data.password}' | base64 -d +{{- if .Values.tests.enabled }} +3. Test cluster health using Helm test. + $ helm --namespace={{ .Release.Namespace }} test {{ .Release.Name }} +{{- end -}} diff --git a/backing-services/elasticsearch/templates/_helpers.tpl b/backing-services/elasticsearch/templates/_helpers.tpl new file mode 100644 index 0000000..b47e2fe --- /dev/null +++ b/backing-services/elasticsearch/templates/_helpers.tpl @@ -0,0 +1,97 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "elasticsearch.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 "elasticsearch.fullname" -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- define "elasticsearch.uname" -}} +{{- if empty .Values.fullnameOverride -}} +{{- if empty .Values.nameOverride -}} +{{ .Values.clusterName }}-{{ .Values.nodeGroup }} +{{- else -}} +{{ .Values.nameOverride }}-{{ .Values.nodeGroup }} +{{- end -}} +{{- else -}} +{{ .Values.fullnameOverride }} +{{- end -}} +{{- end -}} + +{{/* +Generate certificates when the secret doesn't exist +*/}} +{{- define "elasticsearch.gen-certs" -}} +{{- $certs := lookup "v1" "Secret" .Release.Namespace ( printf "%s-certs" (include "elasticsearch.uname" . ) ) -}} +{{- if $certs -}} +tls.crt: {{ index $certs.data "tls.crt" }} +tls.key: {{ index $certs.data "tls.key" }} +ca.crt: {{ index $certs.data "ca.crt" }} +{{- else -}} +{{- $altNames := list ( include "elasticsearch.masterService" . ) ( printf "%s.%s" (include "elasticsearch.masterService" .) .Release.Namespace ) ( printf "%s.%s.svc" (include "elasticsearch.masterService" .) .Release.Namespace ) -}} +{{- $ca := genCA "elasticsearch-ca" 365 -}} +{{- $cert := genSignedCert ( include "elasticsearch.masterService" . ) nil $altNames 365 $ca -}} +tls.crt: {{ $cert.Cert | toString | b64enc }} +tls.key: {{ $cert.Key | toString | b64enc }} +ca.crt: {{ $ca.Cert | toString | b64enc }} +{{- end -}} +{{- end -}} + +{{- define "elasticsearch.masterService" -}} +{{- if empty .Values.masterService -}} +{{- if empty .Values.fullnameOverride -}} +{{- if empty .Values.nameOverride -}} +{{ .Values.clusterName }}-master +{{- else -}} +{{ .Values.nameOverride }}-master +{{- end -}} +{{- else -}} +{{ .Values.fullnameOverride }} +{{- end -}} +{{- else -}} +{{ .Values.masterService }} +{{- end -}} +{{- end -}} + +{{- define "elasticsearch.endpoints" -}} +{{- $replicas := int (toString (.Values.replicas)) }} +{{- $uname := (include "elasticsearch.uname" .) }} + {{- range $i, $e := untilStep 0 $replicas 1 -}} +{{ $uname }}-{{ $i }}, + {{- end -}} +{{- end -}} + +{{- define "elasticsearch.roles" -}} +{{- range $.Values.roles -}} +{{ . }}, +{{- end -}} +{{- end -}} + +{{- define "elasticsearch.esMajorVersion" -}} +{{- if .Values.esMajorVersion -}} +{{ .Values.esMajorVersion }} +{{- else -}} +{{- $version := int (index (.Values.imageTag | splitList ".") 0) -}} + {{- if and (contains "docker.elastic.co/elasticsearch/elasticsearch" .Values.image) (not (eq $version 0)) -}} +{{ $version }} + {{- else -}} +8 + {{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Use the fullname if the serviceAccount value is not set +*/}} +{{- define "elasticsearch.serviceAccount" -}} +{{- .Values.rbac.serviceAccountName | default (include "elasticsearch.uname" .) -}} +{{- end -}} diff --git a/backing-services/elasticsearch/templates/configmap.yaml b/backing-services/elasticsearch/templates/configmap.yaml new file mode 100644 index 0000000..fd1ad30 --- /dev/null +++ b/backing-services/elasticsearch/templates/configmap.yaml @@ -0,0 +1,34 @@ +{{- if .Values.esConfig }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "elasticsearch.uname" . }}-config + labels: + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: "{{ .Chart.Name }}" + app: "{{ template "elasticsearch.uname" . }}" +data: +{{- range $path, $config := .Values.esConfig }} + {{ $path }}: | +{{ $config | indent 4 -}} +{{- end -}} +{{- end -}} +{{- if .Values.esJvmOptions }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "elasticsearch.uname" . }}-jvm-options + labels: + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: "{{ .Chart.Name }}" + app: "{{ template "elasticsearch.uname" . }}" +data: +{{- range $path, $config := .Values.esJvmOptions }} + {{ $path }}: | +{{ $config | indent 4 -}} +{{- end -}} +{{- end -}} \ No newline at end of file diff --git a/backing-services/elasticsearch/templates/ingress.yaml b/backing-services/elasticsearch/templates/ingress.yaml new file mode 100644 index 0000000..e60cebf --- /dev/null +++ b/backing-services/elasticsearch/templates/ingress.yaml @@ -0,0 +1,64 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "elasticsearch.uname" . -}} +{{- $httpPort := .Values.httpPort -}} +{{- $pathtype := .Values.ingress.pathtype -}} +{{- $ingressPath := .Values.ingress.path -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + app: {{ .Chart.Name }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- with .Values.ingress.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + {{- if .Values.ingress.className }} + ingressClassName: {{ .Values.ingress.className | quote }} + {{- end }} +{{- if .Values.ingress.tls }} + tls: + {{- if .ingressPath }} + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} +{{- else }} +{{ toYaml .Values.ingress.tls | indent 4 }} + {{- end }} +{{- end}} + rules: + {{- range .Values.ingress.hosts }} + {{- if $ingressPath }} + - host: {{ . }} + http: + paths: + - path: {{ $ingressPath }} + pathType: {{ $pathtype }} + backend: + service: + name: {{ $fullName }} + port: + number: {{ $httpPort }} + {{- else }} + - host: {{ .host }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + pathType: {{ $pathtype }} + backend: + service: + name: {{ $fullName }} + port: + number: {{ .servicePort | default $httpPort }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} diff --git a/backing-services/elasticsearch/templates/networkpolicy.yaml b/backing-services/elasticsearch/templates/networkpolicy.yaml new file mode 100644 index 0000000..62bb1bd --- /dev/null +++ b/backing-services/elasticsearch/templates/networkpolicy.yaml @@ -0,0 +1,61 @@ +{{- if (or .Values.networkPolicy.http.enabled .Values.networkPolicy.transport.enabled) }} +kind: NetworkPolicy +apiVersion: networking.k8s.io/v1 +metadata: + name: {{ template "elasticsearch.uname" . }} + labels: + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: "{{ .Chart.Name }}" + app: "{{ template "elasticsearch.uname" . }}" +spec: + podSelector: + matchLabels: + app: "{{ template "elasticsearch.uname" . }}" + ingress: # Allow inbound connections + +{{- if .Values.networkPolicy.http.enabled }} + # For HTTP access + - ports: + - port: {{ .Values.httpPort }} + from: + # From authorized Pods (having the correct label) + - podSelector: + matchLabels: + {{ template "elasticsearch.uname" . }}-http-client: "true" +{{- with .Values.networkPolicy.http.explicitNamespacesSelector }} + # From authorized namespaces + namespaceSelector: +{{ toYaml . | indent 12 }} +{{- end }} +{{- with .Values.networkPolicy.http.additionalRules }} + # Or from custom additional rules +{{ toYaml . | indent 8 }} +{{- end }} +{{- end }} + +{{- if .Values.networkPolicy.transport.enabled }} + # For transport access + - ports: + - port: {{ .Values.transportPort }} + from: + # From authorized Pods (having the correct label) + - podSelector: + matchLabels: + {{ template "elasticsearch.uname" . }}-transport-client: "true" +{{- with .Values.networkPolicy.transport.explicitNamespacesSelector }} + # From authorized namespaces + namespaceSelector: +{{ toYaml . | indent 12 }} +{{- end }} +{{- with .Values.networkPolicy.transport.additionalRules }} + # Or from custom additional rules +{{ toYaml . | indent 8 }} +{{- end }} + # Or from other ElasticSearch Pods + - podSelector: + matchLabels: + app: "{{ template "elasticsearch.uname" . }}" +{{- end }} + +{{- end }} diff --git a/backing-services/elasticsearch/templates/poddisruptionbudget.yaml b/backing-services/elasticsearch/templates/poddisruptionbudget.yaml new file mode 100644 index 0000000..6d0bdf3 --- /dev/null +++ b/backing-services/elasticsearch/templates/poddisruptionbudget.yaml @@ -0,0 +1,15 @@ +{{- if .Values.maxUnavailable }} +{{- if .Capabilities.APIVersions.Has "policy/v1" -}} +apiVersion: policy/v1 +{{- else}} +apiVersion: policy/v1beta1 +{{- end }} +kind: PodDisruptionBudget +metadata: + name: "{{ template "elasticsearch.uname" . }}-pdb" +spec: + maxUnavailable: {{ .Values.maxUnavailable }} + selector: + matchLabels: + app: "{{ template "elasticsearch.uname" . }}" +{{- end }} diff --git a/backing-services/elasticsearch/templates/podsecuritypolicy.yaml b/backing-services/elasticsearch/templates/podsecuritypolicy.yaml new file mode 100644 index 0000000..d8b3545 --- /dev/null +++ b/backing-services/elasticsearch/templates/podsecuritypolicy.yaml @@ -0,0 +1,14 @@ +{{- if .Values.podSecurityPolicy.create -}} +{{- $fullName := include "elasticsearch.uname" . -}} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ default $fullName .Values.podSecurityPolicy.name | quote }} + labels: + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + app: {{ $fullName | quote }} +spec: +{{ toYaml .Values.podSecurityPolicy.spec | indent 2 }} +{{- end -}} diff --git a/backing-services/elasticsearch/templates/role.yaml b/backing-services/elasticsearch/templates/role.yaml new file mode 100644 index 0000000..d3a7ee3 --- /dev/null +++ b/backing-services/elasticsearch/templates/role.yaml @@ -0,0 +1,25 @@ +{{- if .Values.rbac.create -}} +{{- $fullName := include "elasticsearch.uname" . -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ $fullName | quote }} + labels: + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + app: {{ $fullName | quote }} +rules: + - apiGroups: + - extensions + resources: + - podsecuritypolicies + resourceNames: + {{- if eq .Values.podSecurityPolicy.name "" }} + - {{ $fullName | quote }} + {{- else }} + - {{ .Values.podSecurityPolicy.name | quote }} + {{- end }} + verbs: + - use +{{- end -}} diff --git a/backing-services/elasticsearch/templates/rolebinding.yaml b/backing-services/elasticsearch/templates/rolebinding.yaml new file mode 100644 index 0000000..e0ecced --- /dev/null +++ b/backing-services/elasticsearch/templates/rolebinding.yaml @@ -0,0 +1,20 @@ +{{- if .Values.rbac.create -}} +{{- $fullName := include "elasticsearch.uname" . -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ $fullName | quote }} + labels: + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + app: {{ $fullName | quote }} +subjects: + - kind: ServiceAccount + name: "{{ template "elasticsearch.serviceAccount" . }}" + namespace: {{ .Release.Namespace | quote }} +roleRef: + kind: Role + name: {{ $fullName | quote }} + apiGroup: rbac.authorization.k8s.io +{{- end -}} diff --git a/backing-services/elasticsearch/templates/secret-cert.yaml b/backing-services/elasticsearch/templates/secret-cert.yaml new file mode 100644 index 0000000..97d8dec --- /dev/null +++ b/backing-services/elasticsearch/templates/secret-cert.yaml @@ -0,0 +1,14 @@ +{{- if .Values.createCert }} +apiVersion: v1 +kind: Secret +type: kubernetes.io/tls +metadata: + name: {{ template "elasticsearch.uname" . }}-certs + labels: + app: {{ template "elasticsearch.uname" . }} + chart: "{{ .Chart.Name }}" + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} +data: +{{ ( include "elasticsearch.gen-certs" . ) | indent 2 }} +{{- end }} diff --git a/backing-services/elasticsearch/templates/secret.yaml b/backing-services/elasticsearch/templates/secret.yaml new file mode 100644 index 0000000..cbdcbba --- /dev/null +++ b/backing-services/elasticsearch/templates/secret.yaml @@ -0,0 +1,23 @@ +{{- if .Values.secret.enabled -}} +{{- $passwordValue := (randAlphaNum 16) | b64enc | quote }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "elasticsearch.uname" . }}-credentials + labels: + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: "{{ .Chart.Name }}" + app: "{{ template "elasticsearch.uname" . }}" + {{- range $key, $value := .Values.labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} +type: Opaque +data: + username: {{ "elastic" | b64enc }} + {{- if .Values.secret.password }} + password: {{ .Values.secret.password | b64enc }} + {{- else }} + password: {{ $passwordValue }} + {{- end }} +{{- end }} diff --git a/backing-services/elasticsearch/templates/service.yaml b/backing-services/elasticsearch/templates/service.yaml new file mode 100644 index 0000000..5fe52eb --- /dev/null +++ b/backing-services/elasticsearch/templates/service.yaml @@ -0,0 +1,78 @@ +{{- if .Values.service.enabled -}} +--- +kind: Service +apiVersion: v1 +metadata: +{{- if eq .Values.nodeGroup "master" }} + name: {{ template "elasticsearch.masterService" . }} +{{- else }} + name: {{ template "elasticsearch.uname" . }} +{{- end }} + labels: + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: "{{ .Chart.Name }}" + app: "{{ template "elasticsearch.uname" . }}" +{{- if .Values.service.labels }} +{{ toYaml .Values.service.labels | indent 4}} +{{- end }} + annotations: +{{ toYaml .Values.service.annotations | indent 4 }} +spec: + type: {{ .Values.service.type }} + selector: + release: {{ .Release.Name | quote }} + chart: "{{ .Chart.Name }}" + app: "{{ template "elasticsearch.uname" . }}" + publishNotReadyAddresses: {{ .Values.service.publishNotReadyAddresses }} + ports: + - name: {{ .Values.service.httpPortName | default "http" }} + protocol: TCP + port: {{ .Values.httpPort }} +{{- if .Values.service.nodePort }} + nodePort: {{ .Values.service.nodePort }} +{{- end }} + - name: {{ .Values.service.transportPortName | default "transport" }} + protocol: TCP + port: {{ .Values.transportPort }} +{{- if .Values.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} +{{- end }} +{{- with .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: +{{ toYaml . | indent 4 }} +{{- end }} +{{- if .Values.service.externalTrafficPolicy }} + externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy }} +{{- end }} +{{- end }} +--- +kind: Service +apiVersion: v1 +metadata: +{{- if eq .Values.nodeGroup "master" }} + name: {{ template "elasticsearch.masterService" . }}-headless +{{- else }} + name: {{ template "elasticsearch.uname" . }}-headless +{{- end }} + labels: + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: "{{ .Chart.Name }}" + app: "{{ template "elasticsearch.uname" . }}" +{{- if .Values.service.labelsHeadless }} +{{ toYaml .Values.service.labelsHeadless | indent 4 }} +{{- end }} + annotations: + service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" +spec: + clusterIP: None # This is needed for statefulset hostnames like elasticsearch-0 to resolve + # Create endpoints also if the related pod isn't ready + publishNotReadyAddresses: true + selector: + app: "{{ template "elasticsearch.uname" . }}" + ports: + - name: {{ .Values.service.httpPortName | default "http" }} + port: {{ .Values.httpPort }} + - name: {{ .Values.service.transportPortName | default "transport" }} + port: {{ .Values.transportPort }} diff --git a/backing-services/elasticsearch/templates/serviceaccount.yaml b/backing-services/elasticsearch/templates/serviceaccount.yaml new file mode 100644 index 0000000..a7ef847 --- /dev/null +++ b/backing-services/elasticsearch/templates/serviceaccount.yaml @@ -0,0 +1,16 @@ +{{- if .Values.rbac.create -}} +{{- $fullName := include "elasticsearch.uname" . -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: "{{ template "elasticsearch.serviceAccount" . }}" + annotations: + {{- with .Values.rbac.serviceAccountAnnotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + app: {{ $fullName | quote }} +{{- end -}} diff --git a/backing-services/elasticsearch/templates/statefulset.yaml b/backing-services/elasticsearch/templates/statefulset.yaml new file mode 100644 index 0000000..64fd423 --- /dev/null +++ b/backing-services/elasticsearch/templates/statefulset.yaml @@ -0,0 +1,427 @@ +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ template "elasticsearch.uname" . }} + labels: + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + chart: "{{ .Chart.Name }}" + app: "{{ template "elasticsearch.uname" . }}" + {{- range $key, $value := .Values.labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + annotations: + esMajorVersion: "{{ include "elasticsearch.esMajorVersion" . }}" +spec: + serviceName: {{ template "elasticsearch.uname" . }}-headless + selector: + matchLabels: + app: "{{ template "elasticsearch.uname" . }}" + replicas: {{ .Values.replicas }} + podManagementPolicy: {{ .Values.podManagementPolicy }} + updateStrategy: + type: {{ .Values.updateStrategy }} + {{- if .Values.persistence.enabled }} + volumeClaimTemplates: + - metadata: + name: {{ template "elasticsearch.uname" . }} + {{- if .Values.persistence.labels.enabled }} + labels: + release: {{ .Release.Name | quote }} + chart: "{{ .Chart.Name }}" + app: "{{ template "elasticsearch.uname" . }}" + {{- range $key, $value := .Values.labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- end }} + {{- with .Values.persistence.annotations }} + annotations: +{{ toYaml . | indent 8 }} + {{- end }} + spec: +{{ toYaml .Values.volumeClaimTemplate | indent 6 }} + {{- end }} + template: + metadata: + name: "{{ template "elasticsearch.uname" . }}" + labels: + release: {{ .Release.Name | quote }} + chart: "{{ .Chart.Name }}" + app: "{{ template "elasticsearch.uname" . }}" + {{- range $key, $value := .Values.labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + annotations: + {{- range $key, $value := .Values.podAnnotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{/* This forces a restart if the configmap has changed */}} + {{- if or .Values.esConfig .Values.esJvmOptions }} + configchecksum: {{ include (print .Template.BasePath "/configmap.yaml") . | sha256sum | trunc 63 }} + {{- end }} + spec: + {{- if .Values.schedulerName }} + schedulerName: "{{ .Values.schedulerName }}" + {{- end }} + securityContext: +{{ toYaml .Values.podSecurityContext | indent 8 }} + {{- if .Values.fsGroup }} + fsGroup: {{ .Values.fsGroup }} # Deprecated value, please use .Values.podSecurityContext.fsGroup + {{- end }} + {{- if or .Values.rbac.create .Values.rbac.serviceAccountName }} + serviceAccountName: "{{ template "elasticsearch.serviceAccount" . }}" + {{- end }} + automountServiceAccountToken: {{ .Values.rbac.automountToken }} + {{- with .Values.tolerations }} + tolerations: +{{ toYaml . | indent 6 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: +{{ toYaml . | indent 8 }} + {{- end }} + {{- if or (eq .Values.antiAffinity "hard") (eq .Values.antiAffinity "soft") .Values.nodeAffinity }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + affinity: + {{- end }} + {{- if eq .Values.antiAffinity "hard" }} + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app + operator: In + values: + - "{{ template "elasticsearch.uname" .}}" + topologyKey: {{ .Values.antiAffinityTopologyKey }} + {{- else if eq .Values.antiAffinity "soft" }} + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 + podAffinityTerm: + topologyKey: {{ .Values.antiAffinityTopologyKey }} + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - "{{ template "elasticsearch.uname" . }}" + {{- end }} + {{- with .Values.nodeAffinity }} + nodeAffinity: +{{ toYaml . | indent 10 }} + {{- end }} + terminationGracePeriodSeconds: {{ .Values.terminationGracePeriod }} + volumes: + {{- range .Values.secretMounts }} + - name: {{ .name }} + secret: + secretName: {{ .secretName }} + {{- if .defaultMode }} + defaultMode: {{ .defaultMode }} + {{- end }} + {{- end }} + {{- if .Values.esConfig }} + - name: esconfig + configMap: + name: {{ template "elasticsearch.uname" . }}-config + {{- end }} + {{- if .Values.esJvmOptions }} + - name: esjvmoptions + configMap: + name: {{ template "elasticsearch.uname" . }}-jvm-options + {{- end }} + {{- if .Values.createCert }} + - name: elasticsearch-certs + secret: + secretName: {{ template "elasticsearch.uname" . }}-certs + {{- end }} +{{- if .Values.keystore }} + - name: keystore + emptyDir: {} + {{- range .Values.keystore }} + - name: keystore-{{ .secretName }} + secret: {{ toYaml . | nindent 12 }} + {{- end }} +{{ end }} + {{- if .Values.extraVolumes }} + # Currently some extra blocks accept strings + # to continue with backwards compatibility this is being kept + # whilst also allowing for yaml to be specified too. + {{- if eq "string" (printf "%T" .Values.extraVolumes) }} +{{ tpl .Values.extraVolumes . | indent 8 }} + {{- else }} +{{ toYaml .Values.extraVolumes | indent 8 }} + {{- end }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: +{{ toYaml .Values.imagePullSecrets | indent 8 }} + {{- end }} + enableServiceLinks: {{ .Values.enableServiceLinks }} + {{- if .Values.hostAliases }} + hostAliases: {{ toYaml .Values.hostAliases | nindent 8 }} + {{- end }} + {{- if or (.Values.extraInitContainers) (.Values.sysctlInitContainer.enabled) (.Values.keystore) }} + initContainers: + {{- if .Values.sysctlInitContainer.enabled }} + - name: configure-sysctl + securityContext: + runAsUser: 0 + privileged: true + image: "{{ .Values.image }}:{{ .Values.imageTag }}" + imagePullPolicy: "{{ .Values.imagePullPolicy }}" + command: ["sysctl", "-w", "vm.max_map_count={{ .Values.sysctlVmMaxMapCount}}"] + resources: +{{ toYaml .Values.initResources | indent 10 }} + {{- end }} +{{ if .Values.keystore }} + - name: keystore + securityContext: +{{ toYaml .Values.securityContext | indent 10 }} + image: "{{ .Values.image }}:{{ .Values.imageTag }}" + imagePullPolicy: "{{ .Values.imagePullPolicy }}" + command: + - bash + - -c + - | + set -euo pipefail + + elasticsearch-keystore create + + for i in /tmp/keystoreSecrets/*/*; do + key=$(basename $i) + echo "Adding file $i to keystore key $key" + elasticsearch-keystore add-file "$key" "$i" + done + + # Add the bootstrap password since otherwise the Elasticsearch entrypoint tries to do this on startup + if [ ! -z ${ELASTIC_PASSWORD+x} ]; then + echo 'Adding env $ELASTIC_PASSWORD to keystore as key bootstrap.password' + echo "$ELASTIC_PASSWORD" | elasticsearch-keystore add -x bootstrap.password + fi + + cp -a /usr/share/elasticsearch/config/elasticsearch.keystore /tmp/keystore/ + env: {{ toYaml .Values.extraEnvs | nindent 10 }} + envFrom: {{ toYaml .Values.envFrom | nindent 10 }} + resources: {{ toYaml .Values.initResources | nindent 10 }} + volumeMounts: + - name: keystore + mountPath: /tmp/keystore + {{- range .Values.keystore }} + - name: keystore-{{ .secretName }} + mountPath: /tmp/keystoreSecrets/{{ .secretName }} + {{- end }} +{{ end }} + {{- if .Values.extraInitContainers }} + # Currently some extra blocks accept strings + # to continue with backwards compatibility this is being kept + # whilst also allowing for yaml to be specified too. + {{- if eq "string" (printf "%T" .Values.extraInitContainers) }} +{{ tpl .Values.extraInitContainers . | indent 6 }} + {{- else }} +{{ toYaml .Values.extraInitContainers | indent 6 }} + {{- end }} + {{- end }} + {{- end }} + containers: + - name: "{{ template "elasticsearch.name" . }}" + securityContext: +{{ toYaml .Values.securityContext | indent 10 }} + image: "{{ .Values.image }}:{{ .Values.imageTag }}" + imagePullPolicy: "{{ .Values.imagePullPolicy }}" + readinessProbe: + exec: + command: + - bash + - -c + - | + set -e + + # Exit if ELASTIC_PASSWORD in unset + if [ -z "${ELASTIC_PASSWORD}" ]; then + echo "ELASTIC_PASSWORD variable is missing, exiting" + exit 1 + fi + + # If the node is starting up wait for the cluster to be ready (request params: "{{ .Values.clusterHealthCheckParams }}" ) + # Once it has started only check that the node itself is responding + START_FILE=/tmp/.es_start_file + + # Disable nss cache to avoid filling dentry cache when calling curl + # This is required with Elasticsearch Docker using nss < 3.52 + export NSS_SDB_USE_CACHE=no + + http () { + local path="${1}" + local args="${2}" + set -- -XGET -s + + if [ "$args" != "" ]; then + set -- "$@" $args + fi + + set -- "$@" -u "elastic:${ELASTIC_PASSWORD}" + + curl --output /dev/null -k "$@" "{{ .Values.protocol }}://127.0.0.1:{{ .Values.httpPort }}${path}" + } + + if [ -f "${START_FILE}" ]; then + echo 'Elasticsearch is already running, lets check the node is healthy' + HTTP_CODE=$(http "/" "-w %{http_code}") + RC=$? + if [[ ${RC} -ne 0 ]]; then + echo "curl --output /dev/null -k -XGET -s -w '%{http_code}' \${BASIC_AUTH} {{ .Values.protocol }}://127.0.0.1:{{ .Values.httpPort }}/ failed with RC ${RC}" + exit ${RC} + fi + # ready if HTTP code 200, 503 is tolerable if ES version is 6.x + if [[ ${HTTP_CODE} == "200" ]]; then + exit 0 + elif [[ ${HTTP_CODE} == "503" && "{{ include "elasticsearch.esMajorVersion" . }}" == "6" ]]; then + exit 0 + else + echo "curl --output /dev/null -k -XGET -s -w '%{http_code}' \${BASIC_AUTH} {{ .Values.protocol }}://127.0.0.1:{{ .Values.httpPort }}/ failed with HTTP code ${HTTP_CODE}" + exit 1 + fi + + else + echo 'Waiting for elasticsearch cluster to become ready (request params: "{{ .Values.clusterHealthCheckParams }}" )' + if http "/_cluster/health?{{ .Values.clusterHealthCheckParams }}" "--fail" ; then + touch ${START_FILE} + exit 0 + else + echo 'Cluster is not yet ready (request params: "{{ .Values.clusterHealthCheckParams }}" )' + exit 1 + fi + fi +{{ toYaml .Values.readinessProbe | indent 10 }} + ports: + - name: http + containerPort: {{ .Values.httpPort }} + - name: transport + containerPort: {{ .Values.transportPort }} + resources: +{{ toYaml .Values.resources | indent 10 }} + env: + - name: node.name + valueFrom: + fieldRef: + fieldPath: metadata.name + {{- if has "master" .Values.roles }} + - name: cluster.initial_master_nodes + value: "{{ template "elasticsearch.endpoints" . }}" + {{- end }} + {{- if gt (len (include "elasticsearch.roles" .)) 0 }} + - name: node.roles + value: "{{ template "elasticsearch.roles" . }}" + {{- end }} + {{- if lt (int (include "elasticsearch.esMajorVersion" .)) 7 }} + - name: discovery.zen.ping.unicast.hosts + value: "{{ template "elasticsearch.masterService" . }}-headless" + {{- else }} + - name: discovery.seed_hosts + value: "{{ template "elasticsearch.masterService" . }}-headless" + {{- end }} + - name: cluster.name + value: "{{ .Values.clusterName }}" + - name: network.host + value: "{{ .Values.networkHost }}" + {{- if .Values.secret.enabled }} + - name: ELASTIC_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "elasticsearch.uname" . }}-credentials + key: password + {{- end }} + {{- if .Values.esJavaOpts }} + - name: ES_JAVA_OPTS + value: "{{ .Values.esJavaOpts }}" + {{- end }} + {{- if .Values.createCert }} + - name: xpack.security.enabled + value: "true" + - name: xpack.security.transport.ssl.enabled + value: "true" + - name: xpack.security.http.ssl.enabled + value: "true" + - name: xpack.security.transport.ssl.verification_mode + value: "certificate" + - name: xpack.security.transport.ssl.key + value: "/usr/share/elasticsearch/config/certs/tls.key" + - name: xpack.security.transport.ssl.certificate + value: "/usr/share/elasticsearch/config/certs/tls.crt" + - name: xpack.security.transport.ssl.certificate_authorities + value: "/usr/share/elasticsearch/config/certs/ca.crt" + - name: xpack.security.http.ssl.key + value: "/usr/share/elasticsearch/config/certs/tls.key" + - name: xpack.security.http.ssl.certificate + value: "/usr/share/elasticsearch/config/certs/tls.crt" + - name: xpack.security.http.ssl.certificate_authorities + value: "/usr/share/elasticsearch/config/certs/ca.crt" + {{- end }} +{{- if .Values.extraEnvs }} +{{ toYaml .Values.extraEnvs | indent 10 }} +{{- end }} +{{- if .Values.envFrom }} + envFrom: +{{ toYaml .Values.envFrom | indent 10 }} +{{- end }} + volumeMounts: + {{- if .Values.persistence.enabled }} + - name: "{{ template "elasticsearch.uname" . }}" + mountPath: /usr/share/elasticsearch/data + {{- end }} + {{- if .Values.createCert }} + - name: elasticsearch-certs + mountPath: /usr/share/elasticsearch/config/certs + readOnly: true + {{- end }} +{{ if .Values.keystore }} + - name: keystore + mountPath: /usr/share/elasticsearch/config/elasticsearch.keystore + subPath: elasticsearch.keystore +{{ end }} + {{- range .Values.secretMounts }} + - name: {{ .name }} + mountPath: {{ .path }} + {{- if .subPath }} + subPath: {{ .subPath }} + {{- end }} + {{- end }} + {{- range $path, $config := .Values.esConfig }} + - name: esconfig + mountPath: /usr/share/elasticsearch/config/{{ $path }} + subPath: {{ $path }} + {{- end -}} + {{- range $path, $config := .Values.esJvmOptions }} + - name: esjvmoptions + mountPath: /usr/share/elasticsearch/config/jvm.options.d/{{ $path }} + subPath: {{ $path }} + {{- end -}} + {{- if .Values.extraVolumeMounts }} + # Currently some extra blocks accept strings + # to continue with backwards compatibility this is being kept + # whilst also allowing for yaml to be specified too. + {{- if eq "string" (printf "%T" .Values.extraVolumeMounts) }} +{{ tpl .Values.extraVolumeMounts . | indent 10 }} + {{- else }} +{{ toYaml .Values.extraVolumeMounts | indent 10 }} + {{- end }} + {{- end }} +{{- if .Values.lifecycle }} + lifecycle: +{{ toYaml .Values.lifecycle | indent 10 }} +{{- end }} + {{- if .Values.extraContainers }} + # Currently some extra blocks accept strings + # to continue with backwards compatibility this is being kept + # whilst also allowing for yaml to be specified too. + {{- if eq "string" (printf "%T" .Values.extraContainers) }} +{{ tpl .Values.extraContainers . | indent 6 }} + {{- else }} +{{ toYaml .Values.extraContainers | indent 6 }} + {{- end }} + {{- end }} diff --git a/backing-services/elasticsearch/templates/test/test-elasticsearch-health.yaml b/backing-services/elasticsearch/templates/test/test-elasticsearch-health.yaml new file mode 100644 index 0000000..d0890fb --- /dev/null +++ b/backing-services/elasticsearch/templates/test/test-elasticsearch-health.yaml @@ -0,0 +1,50 @@ +{{- if .Values.tests.enabled -}} +--- +apiVersion: v1 +kind: Pod +metadata: +{{- if .Values.healthNameOverride }} + name: {{ .Values.healthNameOverride | quote }} +{{- else }} + name: "{{ .Release.Name }}-{{ randAlpha 5 | lower }}-test" +{{- end }} + annotations: + "helm.sh/hook": test + "helm.sh/hook-delete-policy": hook-succeeded +spec: + securityContext: +{{ toYaml .Values.podSecurityContext | indent 4 }} + containers: +{{- if .Values.healthNameOverride }} + - name: {{ .Values.healthNameOverride | quote }} +{{- else }} + - name: "{{ .Release.Name }}-{{ randAlpha 5 | lower }}-test" +{{- end }} + env: + - name: ELASTIC_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "elasticsearch.uname" . }}-credentials + key: password + image: "{{ .Values.image }}:{{ .Values.imageTag }}" + imagePullPolicy: "{{ .Values.imagePullPolicy }}" + command: + - "sh" + - "-c" + - | + #!/usr/bin/env bash -e + curl -XGET --fail --cacert /usr/share/elasticsearch/config/certs/tls.crt -u "elastic:${ELASTIC_PASSWORD}" https://'{{ template "elasticsearch.uname" . }}:{{ .Values.httpPort }}/_cluster/health?{{ .Values.clusterHealthCheckParams }}' + volumeMounts: + - name: elasticsearch-certs + mountPath: /usr/share/elasticsearch/config/certs + readOnly: true + {{- if .Values.imagePullSecrets }} + imagePullSecrets: +{{ toYaml .Values.imagePullSecrets | indent 4 }} + {{- end }} + restartPolicy: Never + volumes: + - name: elasticsearch-certs + secret: + secretName: {{ template "elasticsearch.uname" . }}-certs +{{- end -}} diff --git a/backing-services/elasticsearch/values.yaml b/backing-services/elasticsearch/values.yaml new file mode 100644 index 0000000..4143d61 --- /dev/null +++ b/backing-services/elasticsearch/values.yaml @@ -0,0 +1,356 @@ +--- +clusterName: "elasticsearch" +nodeGroup: "master" + +# The service that non master groups will try to connect to when joining the cluster +# This should be set to clusterName + "-" + nodeGroup for your master group +masterService: "" + +# Elasticsearch roles that will be applied to this nodeGroup +# These will be set as environment variables. E.g. node.roles=master +# https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-node.html#node-roles +roles: + - master + - data + - data_content + - data_hot + - data_warm + - data_cold + - ingest + - ml + - remote_cluster_client + - transform + +replicas: 3 +minimumMasterNodes: 2 + +esMajorVersion: "" + +# Allows you to add any config files in /usr/share/elasticsearch/config/ +# such as elasticsearch.yml and log4j2.properties +esConfig: {} +# elasticsearch.yml: | +# key: +# nestedkey: value +# log4j2.properties: | +# key = value + +createCert: true + +esJvmOptions: {} +# processors.options: | +# -XX:ActiveProcessorCount=3 + +# Extra environment variables to append to this nodeGroup +# This will be appended to the current 'env:' key. You can use any of the kubernetes env +# syntax here +extraEnvs: [] +# - name: MY_ENVIRONMENT_VAR +# value: the_value_goes_here + +# Allows you to load environment variables from kubernetes secret or config map +envFrom: [] +# - secretRef: +# name: env-secret +# - configMapRef: +# name: config-map + +# Disable it to use your own elastic-credential Secret. +secret: + enabled: true + password: "" # generated randomly if not defined + +# A list of secrets and their paths to mount inside the pod +# This is useful for mounting certificates for security and for mounting +# the X-Pack license +secretMounts: [] +# - name: elastic-certificates +# secretName: elastic-certificates +# path: /usr/share/elasticsearch/config/certs +# defaultMode: 0755 + +hostAliases: [] +#- ip: "127.0.0.1" +# hostnames: +# - "foo.local" +# - "bar.local" + +image: "docker.elastic.co/elasticsearch/elasticsearch" +imageTag: "8.5.1" +imagePullPolicy: "IfNotPresent" + +podAnnotations: {} +# iam.amazonaws.com/role: es-cluster + +# additionals labels +labels: {} + +esJavaOpts: "" # example: "-Xmx1g -Xms1g" + +resources: + requests: + cpu: "1000m" + memory: "2Gi" + limits: + cpu: "1000m" + memory: "2Gi" + +initResources: {} +# limits: +# cpu: "25m" +# # memory: "128Mi" +# requests: +# cpu: "25m" +# memory: "128Mi" + +networkHost: "0.0.0.0" + +volumeClaimTemplate: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 30Gi + +rbac: + create: false + serviceAccountAnnotations: {} + serviceAccountName: "" + automountToken: true + +podSecurityPolicy: + create: false + name: "" + spec: + privileged: true + fsGroup: + rule: RunAsAny + runAsUser: + rule: RunAsAny + seLinux: + rule: RunAsAny + supplementalGroups: + rule: RunAsAny + volumes: + - secret + - configMap + - persistentVolumeClaim + - emptyDir + +persistence: + enabled: true + labels: + # Add default labels for the volumeClaimTemplate of the StatefulSet + enabled: false + annotations: {} + +extraVolumes: [] +# - name: extras +# emptyDir: {} + +extraVolumeMounts: [] +# - name: extras +# mountPath: /usr/share/extras +# readOnly: true + +extraContainers: [] +# - name: do-something +# image: busybox +# command: ['do', 'something'] + +extraInitContainers: [] +# - name: do-something +# image: busybox +# command: ['do', 'something'] + +# This is the PriorityClass settings as defined in +# https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass +priorityClassName: "" + +# By default this will make sure two pods don't end up on the same node +# Changing this to a region would allow you to spread pods across regions +antiAffinityTopologyKey: "kubernetes.io/hostname" + +# Hard means that by default pods will only be scheduled if there are enough nodes for them +# and that they will never end up on the same node. Setting this to soft will do this "best effort" +antiAffinity: "hard" + +# This is the node affinity settings as defined in +# https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity-beta-feature +nodeAffinity: {} + +# The default is to deploy all pods serially. By setting this to parallel all pods are started at +# the same time when bootstrapping the cluster +podManagementPolicy: "Parallel" + +# The environment variables injected by service links are not used, but can lead to slow Elasticsearch boot times when +# there are many services in the current namespace. +# If you experience slow pod startups you probably want to set this to `false`. +enableServiceLinks: true + +protocol: https +httpPort: 9200 +transportPort: 9300 + +service: + enabled: true + labels: {} + labelsHeadless: {} + type: ClusterIP + # Consider that all endpoints are considered "ready" even if the Pods themselves are not + # https://kubernetes.io/docs/reference/kubernetes-api/service-resources/service-v1/#ServiceSpec + publishNotReadyAddresses: false + nodePort: "" + annotations: {} + httpPortName: http + transportPortName: transport + loadBalancerIP: "" + loadBalancerSourceRanges: [] + externalTrafficPolicy: "" + +updateStrategy: RollingUpdate + +# This is the max unavailable setting for the pod disruption budget +# The default value of 1 will make sure that kubernetes won't allow more than 1 +# of your pods to be unavailable during maintenance +maxUnavailable: 1 + +podSecurityContext: + fsGroup: 1000 + runAsUser: 1000 + +securityContext: + capabilities: + drop: + - ALL + # readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + +# How long to wait for elasticsearch to stop gracefully +terminationGracePeriod: 120 + +sysctlVmMaxMapCount: 262144 + +readinessProbe: + failureThreshold: 3 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 3 + timeoutSeconds: 5 + +# https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-health.html#request-params wait_for_status +clusterHealthCheckParams: "wait_for_status=green&timeout=1s" + +## Use an alternate scheduler. +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +schedulerName: "" + +imagePullSecrets: [] +nodeSelector: {} +tolerations: [] + +# Enabling this will publicly expose your Elasticsearch instance. +# Only enable this if you have security enabled on your cluster +ingress: + enabled: false + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + className: "nginx" + pathtype: ImplementationSpecific + hosts: + - host: chart-example.local + paths: + - path: / + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +nameOverride: "" +fullnameOverride: "" +healthNameOverride: "" + +lifecycle: {} +# preStop: +# exec: +# command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"] +# postStart: +# exec: +# command: +# - bash +# - -c +# - | +# #!/bin/bash +# # Add a template to adjust number of shards/replicas +# TEMPLATE_NAME=my_template +# INDEX_PATTERN="logstash-*" +# SHARD_COUNT=8 +# REPLICA_COUNT=1 +# ES_URL=http://localhost:9200 +# while [[ "$(curl -s -o /dev/null -w '%{http_code}\n' $ES_URL)" != "200" ]]; do sleep 1; done +# curl -XPUT "$ES_URL/_template/$TEMPLATE_NAME" -H 'Content-Type: application/json' -d'{"index_patterns":['\""$INDEX_PATTERN"\"'],"settings":{"number_of_shards":'$SHARD_COUNT',"number_of_replicas":'$REPLICA_COUNT'}}' + +sysctlInitContainer: + enabled: true + +keystore: [] + +networkPolicy: + ## Enable creation of NetworkPolicy resources. Only Ingress traffic is filtered for now. + ## In order for a Pod to access Elasticsearch, it needs to have the following label: + ## {{ template "uname" . }}-client: "true" + ## Example for default configuration to access HTTP port: + ## elasticsearch-master-http-client: "true" + ## Example for default configuration to access transport port: + ## elasticsearch-master-transport-client: "true" + + http: + enabled: false + ## if explicitNamespacesSelector is not set or set to {}, only client Pods being in the networkPolicy's namespace + ## and matching all criteria can reach the DB. + ## But sometimes, we want the Pods to be accessible to clients from other namespaces, in this case, we can use this + ## parameter to select these namespaces + ## + # explicitNamespacesSelector: + # # Accept from namespaces with all those different rules (only from whitelisted Pods) + # matchLabels: + # role: frontend + # matchExpressions: + # - {key: role, operator: In, values: [frontend]} + + ## Additional NetworkPolicy Ingress "from" rules to set. Note that all rules are OR-ed. + ## + # additionalRules: + # - podSelector: + # matchLabels: + # role: frontend + # - podSelector: + # matchExpressions: + # - key: role + # operator: In + # values: + # - frontend + + transport: + ## Note that all Elasticsearch Pods can talk to themselves using transport port even if enabled. + enabled: false + # explicitNamespacesSelector: + # matchLabels: + # role: frontend + # matchExpressions: + # - {key: role, operator: In, values: [frontend]} + # additionalRules: + # - podSelector: + # matchLabels: + # role: frontend + # - podSelector: + # matchExpressions: + # - key: role + # operator: In + # values: + # - frontend + +tests: + enabled: true diff --git a/backing-services/emqx/Chart.yaml b/backing-services/emqx/Chart.yaml new file mode 100644 index 0000000..3ec85b0 --- /dev/null +++ b/backing-services/emqx/Chart.yaml @@ -0,0 +1,21 @@ +apiVersion: v2 +name: emqx +icon: https://github.com/emqx.png +description: A Helm chart for EMQX +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +version: 5.8.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. +appVersion: 5.8.0 diff --git a/backing-services/emqx/README.md b/backing-services/emqx/README.md new file mode 100644 index 0000000..a06d12b --- /dev/null +++ b/backing-services/emqx/README.md @@ -0,0 +1,144 @@ +# Introduction + +This chart bootstraps an emqx deployment on a Kubernetes cluster using the Helm package manager. + +# Prerequisites + ++ Kubernetes 1.6+ ++ Helm + +# Installing the Chart + +To install the chart with the release name `my-emqx`: + ++ From Github + ``` + $ git clone https://github.com/emqx/emqx.git + $ cd emqx/deploy/charts/emqx + $ helm install my-emqx . + ``` + ++ From chart Repos + ``` + helm repo add emqx https://repos.emqx.io/charts + helm install my-emqx emqx/emqx + ``` + > If you want to install an unstable version, you need to add `--devel` when you execute the `helm install` command. + +# Uninstalling the Chart + +To uninstall/delete the `my-emqx` deployment: + +``` +$ helm del my-emqx +``` + +# Configuration + +The following table lists the configurable parameters of the emqx chart and their default values. + +| Parameter | Description | Default Value | +|--------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| +| `replicaCount` | It is recommended to have odd number of nodes in a cluster, otherwise the emqx cluster cannot be automatically healed in case of net-split. | 3 | +| `image.repository` | EMQX Image name | emqx/emqx | +| `image.pullPolicy` | The image pull policy | IfNotPresent | +| `image.pullSecrets ` | The image pull secrets | `[]` (does not add image pull secrets to deployed pods) | +| `serviceAccount.create` | If `true`, create a new service account | `true` | +| `serviceAccount.name` | Service account to be used. If not set and `serviceAccount.create` is `true`, a name is generated using the full-name template | | +| `serviceAccount.annotations` | Annotations to add to the service account | | +| `envFromSecret` | The name pull a secret in the same Kubernetes namespace which contains values that will be added to the environment | nil | +| `recreatePods` | Forces the recreation of pods during upgrades, which can be useful to always apply the most recent configuration. | false | +| `podAnnotations ` | Annotations for pod | `{}` | +| `podManagementPolicy` | To redeploy a chart with existing PVC(s), the value must be set to Parallel to avoid deadlock | `Parallel` | +| `persistence.enabled` | Enable EMQX persistence using PVC | false | +| `persistence.storageClass` | Storage class of backing PVC | `nil` (uses alpha storage class annotation) | +| `persistence.existingClaim` | EMQX data Persistent Volume existing claim name, evaluated as a template | "" | +| `persistence.accessMode` | PVC Access Mode for EMQX volume | ReadWriteOnce | +| `persistence.size` | PVC Storage Request for EMQX volume | 20Mi | +| `initContainers` | Containers that run before the creation of EMQX containers. They can contain utilities or setup scripts. | `{}` | +| `resources` | CPU/Memory resource requests/limits | {} | +| `extraVolumeMounts` | Additional volumeMounts to the default backend container. | [] | +| `extraVolumes` | Additional volumes to the default backend pod. | [] | +| `nodeSelector` | Node labels for pod assignment | `{}` | +| `tolerations` | Toleration labels for pod assignment | `[]` | +| `affinity` | Map of node/pod affinities | `{}` | +| `topologySpreadConstraints` | List of topology spread constraints without labelSelector | `[]` | +| `service.type` | Kubernetes Service type. | ClusterIP | +| `service.mqtt` | Port for MQTT. | 1883 | +| `service.mqttssl` | Port for MQTT(SSL). | 8883 | +| `service.ws` | Port for WebSocket/HTTP. | 8083 | +| `service.wss` | Port for WSS/HTTPS. | 8084 | +| `service.dashboard` | Port for dashboard and API. | 18083 | +| `service.nodePorts.mqtt` | Kubernetes node port for MQTT. | nil | +| `service.nodePorts.mqttssl` | Kubernetes node port for MQTT(SSL). | nil | +| `service.nodePorts.ws` | Kubernetes node port for WebSocket/HTTP. | nil | +| `service.nodePorts.wss` | Kubernetes node port for WSS/HTTPS. | nil | +| `service.nodePorts.dashboard` | Kubernetes node port for dashboard. | nil | +| `service.loadBalancerClass` | The load balancer implementation this Service belongs to | | +| `service.loadBalancerIP` | loadBalancerIP for Service | nil | +| `service.loadBalancerSourceRanges` | Address(es) that are allowed when service is LoadBalancer | [] | +| `service.externalIPs` | ExternalIPs for the service | [] | +| `service.externalTrafficPolicy` | External Traffic Policy for the service | `Cluster` | +| `service.annotations` | Service/ServiceMonitor annotations | {}(evaluated as a template) | +| `service.labels` | Service/ServiceMonitor labels | {}(evaluated as a template) | +| `ingress.dashboard.enabled` | Enable ingress for EMQX Dashboard | false | +| `ingress.dashboard.ingressClassName` | Set the ingress class for EMQX Dashboard | | +| `ingress.dashboard.path` | Ingress path for EMQX Dashboard | / | +| `ingress.dashboard.pathType` | Ingress pathType for EMQX Dashboard | `ImplementationSpecific` | +| `ingress.dashboard.hosts` | Ingress hosts for EMQX Dashboard | dashboard.emqx.local | +| `ingress.dashboard.tls` | Ingress tls for EMQX Dashboard | [] | +| `ingress.dashboard.annotations` | Ingress annotations for EMQX Dashboard | {} | +| `ingress.dashboard.ingressClassName` | Set the ingress class for EMQX Dashboard | | +| `ingress.mqtt.enabled` | Enable ingress for MQTT | false | +| `ingress.mqtt.ingressClassName` | Set the ingress class for MQTT | | +| `ingress.mqtt.path` | Ingress path for MQTT | / | +| `ingress.mqtt.pathType` | Ingress pathType for MQTT | `ImplementationSpecific` | +| `ingress.mqtt.hosts` | Ingress hosts for MQTT | mqtt.emqx.local | +| `ingress.mqtt.tls` | Ingress tls for MQTT | [] | +| `ingress.mqtt.annotations` | Ingress annotations for MQTT | {} | +| `ingress.mqtt.ingressClassName` | Set the ingress class for MQTT | | +| `metrics.enable` | If set to true, [prometheus-operator](https://github.com/prometheus-operator/prometheus-operator) needs to be installed, and emqx_prometheus needs to enable | false | +| `metrics.type` | Now we only supported "prometheus" | "prometheus" | +| `ssl.enabled` | Enable SSL support | false | +| `ssl.useExisting` | Use existing certificate or let cert-manager generate one | false | +| `ssl.existingName` | Name of existing certificate | emqx-tls | +| `ssl.commonName` | Common name for or certificate to be generated | | +| `ssl.dnsnames` | DNS name(s) for certificate to be generated | {} | +| `ssl.issuer.name` | Issuer name for certificate generation | letsencrypt-dns | +| `ssl.issuer.kind` | Issuer kind for certificate generation | ClusterIssuer | + +## EMQX specific settings + +The following table lists the configurable [EMQX](https://www.emqx.io/)-specific parameters of the chart and their +default values. +| Parameter | Description | Default Value | +|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------|---------------| +| `emqxConfig` | Map of [configuration](https://www.emqx.io/docs/en/v5.0/admin/cfg.html) items | | +| expressed as [environment variables](https://www.emqx.io/docs/en/v5.0/admin/cfg.html#environment-variables) (prefix `EMQX_` can be omitted) or using the configuration | | | +| files [namespaced dotted notation](https://www.emqx.io/docs/en/v5.0/admin/cfg.html#syntax) | `nil` | | +| `emqxLicenseSecretName` | Name of the secret that holds the license information | `nil` | + +## SSL settings +`cert-manager` generates secrets with certificate data using the keys `tls.crt` and `tls.key`. The helm chart always mounts those keys as files to `/tmp/ssl/` +which needs to explicitly configured by either changing the emqx config file or by passing the following environment variables: + +``` + EMQX_LISTENERS__SSL__DEFAULT__SSL_OPTIONS__CERTFILE: /tmp/ssl/tls.crt + EMQX_LISTENERS__SSL__DEFAULT__SSL_OPTIONS__KEYFILE: /tmp/ssl/tls.key +``` + +If you chose to use an existing certificate, make sure, you update the filenames accordingly. + +## Tips +Enable the Proxy Protocol V1/2 if the EMQX cluster is deployed behind HAProxy or Nginx. +In order to preserve the original client's IP address, you could change the emqx config by passing the following environment variable: + +``` +EMQX_LISTENERS__TCP__DEFAULT__PROXY_PROTOCOL: "true" +``` + +With HAProxy you'd also need the following ingress annotation: + +``` +haproxy-ingress.github.io/proxy-protocol: "v2" +``` diff --git a/backing-services/emqx/schoobus-onsite.values.yaml b/backing-services/emqx/schoobus-onsite.values.yaml new file mode 100644 index 0000000..42ae0d6 --- /dev/null +++ b/backing-services/emqx/schoobus-onsite.values.yaml @@ -0,0 +1,15 @@ +replicaCount: 3 + +service: + ## Service type + ## + type: NodePort + + +resources: + limits: + cpu: 1000m + memory: 512Mi + requests: + cpu: 1000m + memory: 512Mi \ No newline at end of file diff --git a/backing-services/emqx/school-stage-eks.values.yaml b/backing-services/emqx/school-stage-eks.values.yaml new file mode 100644 index 0000000..bab17e2 --- /dev/null +++ b/backing-services/emqx/school-stage-eks.values.yaml @@ -0,0 +1,29 @@ +replicaCount: 3 + +service: + type: LoadBalancer + annotations: + service.beta.kubernetes.io/aws-load-balancer-type: "nlb" + service.beta.kubernetes.io/aws-load-balancer-type: external + service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing + service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: instance + +resources: + limits: + cpu: 1000m + memory: 512Mi + requests: + cpu: 1000m + memory: 512Mi + +persistence: + enabled: true + size: 20Mi + storageClassName: "efs-sc" + accessMode: ReadWriteOnce + +serviceAccount: + create: true + name: "emqxservcieaccount" + annotations: + eks.amazonaws.com/role-arn: "arn:aws:iam::889565812003:role/schoolbuses-cluster-20241110104436981500000002" diff --git a/backing-services/emqx/school-stage-tavana.values.yaml b/backing-services/emqx/school-stage-tavana.values.yaml new file mode 100644 index 0000000..cac2376 --- /dev/null +++ b/backing-services/emqx/school-stage-tavana.values.yaml @@ -0,0 +1,55 @@ +replicaCount: 1 + +image: + repository: 172.16.16.1:30516/emqx/emqx + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +service: + ## Service type + ## + type: NodePort + +resources: + limits: + cpu: 1000m + memory: 512Mi + requests: + cpu: 1000m + memory: 512Mi + + +ingress: + ## ingress for EMQX Dashboard + dashboard: + enabled: true + ingressClassName: nginx + annotations: + kubernetes.io/ingress.class: nginx + path: / + pathType: ImplementationSpecific + hosts: + - dashbaordemqx.tavanasys.app + tls: [] + ## ingress for MQTT + mqtt: + enabled: true + ingressClassName: nginx + annotations: + kubernetes.io/ingress.class: nginx + path: / + pathType: ImplementationSpecific + hosts: + - mqtt.tavanasys.app + tls: [] + ws: + enabled: true + ingressClassName: nginx + annotations: + kubernetes.io/ingress.class: nginx + path: /mqtt + pathType: ImplementationSpecific + hosts: + - ws.tavanasys.app + tls: [] \ No newline at end of file diff --git a/backing-services/emqx/schoolbus-demo.values.yaml b/backing-services/emqx/schoolbus-demo.values.yaml new file mode 100644 index 0000000..886ef94 --- /dev/null +++ b/backing-services/emqx/schoolbus-demo.values.yaml @@ -0,0 +1,55 @@ +replicaCount: 1 + +image: + repository: 172.16.16.2:30516/emqx/emqx + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "latest" + +service: + ## Service type + ## + type: NodePort + +resources: + limits: + cpu: 300m + memory: 300Mi + requests: + cpu: 300m + memory: 300Mi + + +ingress: + ## ingress for EMQX Dashboard + dashboard: + enabled: true + ingressClassName: traefik + annotations: + kubernetes.io/ingress.class: traefik + path: / + pathType: ImplementationSpecific + hosts: + - emqxconsole.tavanasys.app + tls: [] + ## ingress for MQTT + mqtt: + enabled: true + ingressClassName: traefik + annotations: + kubernetes.io/ingress.class: traefik + path: / + pathType: ImplementationSpecific + hosts: + - mqtt.tavanasys.app + tls: [] + ws: + enabled: true + ingressClassName: traefik + annotations: + kubernetes.io/ingress.class: traefik + path: /mqtt + pathType: ImplementationSpecific + hosts: + - emqx.tavanasys.app + tls: [] \ No newline at end of file diff --git a/backing-services/emqx/templates/StatefulSet.yaml b/backing-services/emqx/templates/StatefulSet.yaml new file mode 100644 index 0000000..9298951 --- /dev/null +++ b/backing-services/emqx/templates/StatefulSet.yaml @@ -0,0 +1,206 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "emqx.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "emqx.name" . }} + helm.sh/chart: {{ include "emqx.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + serviceName: {{ include "emqx.fullname" . }}-headless + podManagementPolicy: {{ .Values.podManagementPolicy }} + {{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }} + volumeClaimTemplates: + - metadata: + name: emqx-data + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "emqx.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + spec: + {{- if .Values.persistence.storageClassName }} + storageClassName: {{ .Values.persistence.storageClassName | quote }} + {{- end }} + accessModes: + - {{ .Values.persistence.accessMode | quote }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- end }} + updateStrategy: + type: RollingUpdate + {{- if .Values.minReadySeconds }} + minReadySeconds: {{ .Values.minReadySeconds }} + {{- end }} + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "emqx.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + app: {{ include "emqx.name" . }} + version: {{ .Chart.AppVersion }} + app.kubernetes.io/name: {{ include "emqx.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + annotations: + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.recreatePods }} + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum | quote }} + {{- end }} + spec: + serviceAccountName: {{ include "emqx.serviceAccountName" . }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + volumes: + {{- if .Values.ssl.enabled }} + - name: ssl-cert + secret: + secretName: {{ include "emqx.ssl.secretName" . }} + {{- end }} + {{- if not .Values.persistence.enabled }} + - name: emqx-data + emptyDir: {} + {{- else if .Values.persistence.existingClaim }} + - name: emqx-data + persistentVolumeClaim: + {{- with .Values.persistence.existingClaim }} + claimName: {{ tpl . $ }} + {{- end }} + {{- end }} + {{- if .Values.emqxLicenseSecretName }} + - name: emqx-license + secret: + secretName: {{ .Values.emqxLicenseSecretName }} + {{- end }} + {{- if .Values.extraVolumes }} + {{- toYaml .Values.extraVolumes | nindent 6 }} + {{- end }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- omit .Values.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.initContainers }} + initContainers: + {{- toYaml .Values.initContainers | nindent 8 }} + {{- end }} + {{- if .Values.image.pullSecrets }} + imagePullSecrets: + {{- range .Values.image.pullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} + containers: + - name: emqx + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + ports: + - name: mqtt + containerPort: {{ splitList ":" ( .Values.emqxConfig.EMQX_LISTENERS__TCP__DEFAULT__BIND | default "1883" ) | last }} + - name: mqttssl + containerPort: {{ splitList ":" ( .Values.emqxConfig.EMQX_LISTENERS__SSL__DEFAULT__BIND | default "8883" ) | last }} + - name: ws + containerPort: {{ splitList ":" ( .Values.emqxConfig.EMQX_LISTENERS__WS__DEFAULT__BIND | default "8083" ) | last }} + - name: wss + containerPort: {{ splitList ":" ( .Values.emqxConfig.EMQX_LISTENERS__WSS__DEFAULT__BIND | default "8084" ) | last }} + - name: dashboard + containerPort: {{ splitList ":" ( .Values.emqxConfig.EMQX_DASHBOARD__LISTENERS__HTTP__BIND | default "18083" ) | last }} + {{- if not (empty .Values.emqxConfig.EMQX_DASHBOARD__LISTENERS__HTTPS__BIND) }} + - name: dashboardtls + containerPort: {{ splitList ":" .Values.emqxConfig.EMQX_DASHBOARD__LISTENERS__HTTPS__BIND | last }} + {{- end }} + - name: ekka + containerPort: 4370 + - name: genrpc-manual + containerPort: 5369 + envFrom: + - configMapRef: + name: {{ include "emqx.fullname" . }}-env + {{- if .Values.envFromSecret }} + - secretRef: + name: {{ .Values.envFromSecret }} + {{- end }} + resources: +{{ toYaml .Values.resources | indent 12 }} + volumeMounts: + - name: emqx-data + mountPath: "/opt/emqx/data" + {{- if .Values.ssl.enabled }} + - name: ssl-cert + mountPath: /tmp/ssl + readOnly: true + {{- end}} + {{ if .Values.emqxLicenseSecretName }} + - name: emqx-license + mountPath: "/opt/emqx/etc/emqx.lic" + subPath: "emqx.lic" + readOnly: true + {{- end }} + {{- if .Values.extraVolumeMounts }} + {{- toYaml .Values.extraVolumeMounts | nindent 10 }} + {{- end }} + readinessProbe: + httpGet: + path: /status + port: {{ splitList ":" ( .Values.emqxConfig.EMQX_DASHBOARD__LISTENERS__HTTP__BIND | default "18083" ) | last }} + initialDelaySeconds: 10 + periodSeconds: 5 + failureThreshold: 30 + livenessProbe: + httpGet: + path: /status + port: {{ splitList ":" ( .Values.emqxConfig.EMQX_DASHBOARD__LISTENERS__HTTP__BIND | default "18083" ) | last }} + initialDelaySeconds: 60 + periodSeconds: 30 + failureThreshold: 10 + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.topologySpreadConstraints }} + topologySpreadConstraints: + {{- range . }} + - maxSkew: {{ .maxSkew }} + topologyKey: {{ .topologyKey }} + whenUnsatisfiable: {{ .whenUnsatisfiable }} + labelSelector: + matchLabels: + app.kubernetes.io/name: {{ include "emqx.name" $ }} + app.kubernetes.io/instance: {{ $.Release.Name }} + {{- if .minDomains }} + minDomains: {{ .minDomains }} + {{- end }} + {{- if .matchLabelKeys }} + matchLabelKeys: + {{- range .matchLabelKeys }} + - {{ . }} + {{- end }} + {{- end }} + {{- if .nodeAffinityPolicy }} + nodeAffinityPolicy: {{ .nodeAffinityPolicy }} + {{- end }} + {{- if .nodeTaintsPolicy }} + nodeTaintsPolicy: {{ .nodeTaintsPolicy }} + {{- end }} + {{- end }} + {{- end }} diff --git a/backing-services/emqx/templates/_helpers.tpl b/backing-services/emqx/templates/_helpers.tpl new file mode 100644 index 0000000..64acf79 --- /dev/null +++ b/backing-services/emqx/templates/_helpers.tpl @@ -0,0 +1,55 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "emqx.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "emqx.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "emqx.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + + +{{/* +Get ssl secret name . +*/}} +{{- define "emqx.ssl.secretName" -}} +{{- if and .Values.ssl.useExisting .Values.ssl.existingName -}} + {{ .Values.ssl.existingName }} +{{- else -}} + {{ include "emqx.fullname" . }}-tls +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "emqx.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "emqx.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/backing-services/emqx/templates/certificate.yaml b/backing-services/emqx/templates/certificate.yaml new file mode 100644 index 0000000..528f989 --- /dev/null +++ b/backing-services/emqx/templates/certificate.yaml @@ -0,0 +1,19 @@ +{{- if and (.Values.ssl.enabled) (not .Values.ssl.useExisting) -}} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ include "emqx.fullname" . }}-tls +spec: + secretName: {{ include "emqx.fullname" . }}-tls + issuerRef: + name: {{ default "letsencrypt-staging" .Values.ssl.issuer.name }} + kind: {{ default "ClusterIssuer" .Values.ssl.issuer.kind }} + {{- if .Values.ssl.commonName }} + commonName: {{ .Values.ssl.commonName }} + {{- end }} + dnsNames: + {{- range .Values.ssl.dnsnames }} + - {{ . }} + {{- end }} +{{- end -}} diff --git a/backing-services/emqx/templates/configmap.yaml b/backing-services/emqx/templates/configmap.yaml new file mode 100644 index 0000000..6bd815c --- /dev/null +++ b/backing-services/emqx/templates/configmap.yaml @@ -0,0 +1,34 @@ +{{- if .Values.emqxConfig }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "emqx.fullname" . }}-env + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "emqx.name" . }} + helm.sh/chart: {{ include "emqx.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +data: + EMQX_NAME: {{ .Release.Name }} + {{- if eq (.Values.emqxConfig.EMQX_CLUSTER__DISCOVERY_STRATEGY) "k8s" }} + EMQX_CLUSTER__K8S__APISERVER: "https://kubernetes.default.svc:443" + EMQX_CLUSTER__K8S__SERVICE_NAME: {{ include "emqx.fullname" . }}-headless + EMQX_CLUSTER__K8S__NAMESPACE: {{ .Release.Namespace }} + EMQX_CLUSTER__K8S__ADDRESS_TYPE: "hostname" + EMQX_CLUSTER__K8S__SUFFIX: "svc.{{ .Values.clusterDomain }}" + {{- else if eq (.Values.emqxConfig.EMQX_CLUSTER__DISCOVERY_STRATEGY) "dns" }} + EMQX_CLUSTER__DNS__NAME: "{{ include "emqx.fullname" . }}-headless.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }}" + EMQX_CLUSTER__DNS__RECORD_TYPE: "srv" + {{- end -}} + {{- range $index, $value := .Values.emqxConfig }} + {{- if $value }} + {{- $key := (regexReplaceAllLiteral "\\." (regexReplaceAllLiteral "EMQX[_\\.]" (upper (trimAll " " $index)) "") "__") }} + {{- if or (kindIs "map" $value) (kindIs "slice" $value) }} + {{ print "EMQX_" $key }}: {{ tpl (printf "%q" (toJson $value)) $ }} + {{- else }} + {{ print "EMQX_" $key }}: "{{ tpl (printf "%v" $value) $ }}" + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/emqx/templates/ingress.yaml b/backing-services/emqx/templates/ingress.yaml new file mode 100644 index 0000000..58df81b --- /dev/null +++ b/backing-services/emqx/templates/ingress.yaml @@ -0,0 +1,150 @@ +{{- if .Values.ingress.dashboard.enabled -}} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ printf "%s-%s" (include "emqx.fullname" .) "dashboard" }} + labels: + app.kubernetes.io/name: {{ include "emqx.name" . }} + helm.sh/chart: {{ include "emqx.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + {{- if .Values.ingress.dashboard.annotations }} + annotations: + {{- toYaml .Values.ingress.dashboard.annotations | nindent 4 }} + {{- end }} +spec: +{{- if and .Values.ingress.dashboard.ingressClassName (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.dashboard.ingressClassName }} +{{- end }} + rules: + {{- range $host := .Values.ingress.dashboard.hosts }} + - host: {{ $host }} + http: + paths: + - path: {{ $.Values.ingress.dashboard.path | default "/" }} + {{- if (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ $.Values.ingress.dashboard.pathType | default "ImplementationSpecific" }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ include "emqx.fullname" $ }} + port: + number: {{ $.Values.service.dashboard }} + {{- else }} + serviceName: {{ include "emqx.fullname" $ }} + servicePort: {{ $.Values.service.dashboard }} + {{- end }} + {{- end -}} + {{- if .Values.ingress.dashboard.tls }} + tls: + {{- toYaml .Values.ingress.dashboard.tls | nindent 4 }} + {{- end }} +--- +{{- end }} +{{- if .Values.ingress.mqtt.enabled -}} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ printf "%s-%s" (include "emqx.fullname" .) "mqtt" }} + labels: + app.kubernetes.io/name: {{ include "emqx.name" . }} + helm.sh/chart: {{ include "emqx.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + {{- if .Values.ingress.mqtt.annotations }} + annotations: + {{- toYaml .Values.ingress.mqtt.annotations | nindent 4 }} + {{- end }} +spec: +{{- if and .Values.ingress.mqtt.ingressClassName (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.mqtt.ingressClassName }} +{{- end }} + rules: + {{- range $host := .Values.ingress.mqtt.hosts }} + - host: {{ $host }} + http: + paths: + - path: {{ $.Values.ingress.mqtt.path | default "/" }} + {{- if (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ $.Values.ingress.mqtt.pathType | default "ImplementationSpecific" }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ include "emqx.fullname" $ }} + port: + number: {{ $.Values.service.mqtt }} + {{- else }} + serviceName: {{ include "emqx.fullname" $ }} + servicePort: {{ $.Values.service.mqtt }} + {{- end }} + {{- end -}} + {{- if .Values.ingress.mqtt.tls }} + tls: + {{- toYaml .Values.ingress.mqtt.tls | nindent 4 }} + {{- end }} +--- +{{- end }} +{{- if .Values.ingress.ws.enabled -}} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ printf "%s-%s" (include "emqx.fullname" .) "ws" }} + labels: + app.kubernetes.io/name: {{ include "emqx.name" . }} + helm.sh/chart: {{ include "emqx.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + {{- if .Values.ingress.ws.annotations }} + annotations: + {{- toYaml .Values.ingress.ws.annotations | nindent 4 }} + {{- end }} +spec: +{{- if and .Values.ingress.ws.ingressClassName (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.ws.ingressClassName }} +{{- end }} + rules: + {{- range $host := .Values.ingress.ws.hosts }} + - host: {{ $host }} + http: + paths: + - path: {{ $.Values.ingress.ws.path | default "/mqtt" }} + {{- if (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ $.Values.ingress.ws.pathType | default "ImplementationSpecific" }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ include "emqx.fullname" $ }} + port: + number: {{ $.Values.service.ws }} + {{- else }} + serviceName: {{ include "emqx.fullname" $ }} + servicePort: {{ $.Values.service.ws }} + {{- end }} + {{- end -}} + {{- if .Values.ingress.ws.tls }} + tls: + {{- toYaml .Values.ingress.ws.tls | nindent 4 }} + {{- end }} +--- +{{- end }} diff --git a/backing-services/emqx/templates/pdb.yaml b/backing-services/emqx/templates/pdb.yaml new file mode 100644 index 0000000..a3f2330 --- /dev/null +++ b/backing-services/emqx/templates/pdb.yaml @@ -0,0 +1,18 @@ +{{- if and (.Values.pdb.enabled) (.Capabilities.APIVersions.Has "policy/v1/PodDisruptionBudget") }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "emqx.fullname" . }}-pdb + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "emqx.name" . }} + helm.sh/chart: {{ include "emqx.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + maxUnavailable: {{ .Values.pdb.maxUnavailable }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "emqx.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} diff --git a/backing-services/emqx/templates/rbac.yaml b/backing-services/emqx/templates/rbac.yaml new file mode 100644 index 0000000..9faf4e1 --- /dev/null +++ b/backing-services/emqx/templates/rbac.yaml @@ -0,0 +1,63 @@ +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "emqx.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "emqx.name" . }} + helm.sh/chart: {{ include "emqx.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} + +--- +{{- if .Values.serviceAccount.create }} +{{- if eq .Values.emqxConfig.EMQX_CLUSTER__DISCOVERY_STRATEGY "k8s" }} +kind: Role +{{- if semverCompare ">=1.17-0" .Capabilities.KubeVersion.GitVersion }} +apiVersion: rbac.authorization.k8s.io/v1 +{{- else }} +apiVersion: rbac.authorization.k8s.io/v1beta1 +{{- end }} +metadata: + namespace: {{ .Release.Namespace }} + name: {{ include "emqx.fullname" . }} +rules: +- apiGroups: + - "" + resources: + - endpoints + verbs: + - get + - watch + - list +{{- end }} +{{- end }} + +--- +{{- if .Values.serviceAccount.create }} +{{- if eq .Values.emqxConfig.EMQX_CLUSTER__DISCOVERY_STRATEGY "k8s" }} +kind: RoleBinding +{{- if semverCompare ">=1.17-0" .Capabilities.KubeVersion.GitVersion }} +apiVersion: rbac.authorization.k8s.io/v1 +{{- else }} +apiVersion: rbac.authorization.k8s.io/v1beta1 +{{- end }} +metadata: + namespace: {{ .Release.Namespace }} + name: {{ include "emqx.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ include "emqx.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: Role + name: {{ include "emqx.fullname" . }} + apiGroup: rbac.authorization.k8s.io +{{- end }} +{{- end }} diff --git a/backing-services/emqx/templates/secret.yaml b/backing-services/emqx/templates/secret.yaml new file mode 100644 index 0000000..440f50d --- /dev/null +++ b/backing-services/emqx/templates/secret.yaml @@ -0,0 +1,11 @@ +{{- if .Values.metrics.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "emqx.fullname" . }}-basic-auth + namespace: {{ .Release.Namespace }} +type: kubernetes.io/basic-auth +stringData: + username: {{ .Values.emqxConfig.EMQX_DASHBOARD__DEFAULT_USERNAME | default "admin" }} + password: {{ .Values.emqxConfig.EMQX_DASHBOARD__DEFAULT_PASSWORD | default "public" }} +{{- end }} diff --git a/backing-services/emqx/templates/service-monitor.yaml b/backing-services/emqx/templates/service-monitor.yaml new file mode 100644 index 0000000..cb5c876 --- /dev/null +++ b/backing-services/emqx/templates/service-monitor.yaml @@ -0,0 +1,42 @@ +{{- if and (.Values.metrics.enabled) (eq .Values.metrics.type "prometheus") }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "emqx.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "emqx.name" . }} + helm.sh/chart: {{ include "emqx.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + {{- if .Values.service.labels }} + {{- toYaml .Values.service.labels | nindent 4 }} + {{- end }} + {{- if .Values.service.annotations }} + annotations: + {{- toYaml .Values.service.annotations | nindent 4 }} + {{- end }} +spec: + endpoints: + - interval: 10s + port: dashboard + scheme: http + path: /api/v5/prometheus/stats + params: + type: + - prometheus + basicAuth: + password: + name: {{ include "emqx.fullname" . }}-basic-auth + key: password + username: + name: {{ include "emqx.fullname" . }}-basic-auth + key: username + jobLabel: {{ .Release.Name }}-scraping + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "emqx.name" . }} +{{- end }} diff --git a/backing-services/emqx/templates/service.yaml b/backing-services/emqx/templates/service.yaml new file mode 100644 index 0000000..36bf224 --- /dev/null +++ b/backing-services/emqx/templates/service.yaml @@ -0,0 +1,141 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "emqx.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "emqx.name" . }} + helm.sh/chart: {{ include "emqx.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + {{- if .Values.service.labels }} + {{- toYaml .Values.service.labels | nindent 4 }} + {{- end }} + {{- if .Values.service.annotations }} + annotations: + {{- toYaml .Values.service.annotations | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + {{- if or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy | default "Cluster" }} + {{- end }} + {{- if eq .Values.service.type "LoadBalancer" }} + {{- if .Values.service.loadBalancerClass }} + loadBalancerClass: {{ .Values.service.loadBalancerClass }} + {{- end }} + {{- if .Values.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + {{- if .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{- toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + {{- if .Values.service.externalIPs }} + externalIPs: {{- toYaml .Values.service.externalIPs | nindent 4 }} + {{- end }} + {{- end }} + ports: + - name: mqtt + port: {{ .Values.service.mqtt | default 1883 }} + protocol: TCP + targetPort: mqtt + {{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.mqtt)) }} + nodePort: {{ .Values.service.nodePorts.mqtt }} + {{- else if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- end }} + - name: mqttssl + port: {{ .Values.service.mqttssl | default 8883 }} + protocol: TCP + targetPort: mqttssl + {{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.mqttssl)) }} + nodePort: {{ .Values.service.nodePorts.mqttssl }} + {{- else if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- end }} + - name: ws + port: {{ .Values.service.ws | default 8083 }} + protocol: TCP + targetPort: ws + {{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.ws)) }} + nodePort: {{ .Values.service.nodePorts.ws }} + {{- else if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- end }} + - name: wss + port: {{ .Values.service.wss | default 8084 }} + protocol: TCP + targetPort: wss + {{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.wss)) }} + nodePort: {{ .Values.service.nodePorts.wss }} + {{- else if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- end }} + - name: dashboard + port: {{ .Values.service.dashboard | default 18083 }} + protocol: TCP + targetPort: dashboard + {{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.dashboard)) }} + nodePort: {{ .Values.service.nodePorts.dashboard }} + {{- else if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if not (empty .Values.service.dashboardtls) }} + - name: dashboardtls + port: {{ .Values.service.dashboardtls }} + protocol: TCP + targetPort: dashboardtls + {{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.dashboardtls)) }} + nodePort: {{ .Values.service.nodePorts.dashboardtls }} + {{- else if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- end }} + selector: + app.kubernetes.io/name: {{ include "emqx.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "emqx.fullname" . }}-headless + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "emqx.name" . }} + helm.sh/chart: {{ include "emqx.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + type: ClusterIP + sessionAffinity: None + clusterIP: {{ .Values.service.clusterIP | default "None" }} + publishNotReadyAddresses: true + ports: + - name: mqtt + port: {{ .Values.service.mqtt | default 1883 }} + protocol: TCP + targetPort: mqtt + - name: mqttssl + port: {{ .Values.service.mqttssl | default 8883 }} + protocol: TCP + targetPort: mqttssl + - name: ws + port: {{ .Values.service.ws | default 8083 }} + protocol: TCP + targetPort: ws + - name: wss + port: {{ .Values.service.wss | default 8084 }} + protocol: TCP + targetPort: wss + - name: dashboard + port: {{ .Values.service.dashboard | default 18083 }} + protocol: TCP + targetPort: dashboard + - name: ekka + port: 4370 + protocol: TCP + targetPort: ekka + selector: + app.kubernetes.io/name: {{ include "emqx.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} diff --git a/backing-services/emqx/values.yaml b/backing-services/emqx/values.yaml new file mode 100644 index 0000000..74d30b1 --- /dev/null +++ b/backing-services/emqx/values.yaml @@ -0,0 +1,283 @@ +## Default values for emqx. +## This is a YAML-formatted file. +## Declare variables to be passed into your templates. + +## It is recommended to have odd number of nodes in a cluster, otherwise the emqx cluster cannot be automatically healed in case of net-split. +replicaCount: 3 +image: + repository: emqx/emqx + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + ## 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 + +serviceAccount: + # Specifies whether a service account should be created + # If set false, means you need create service account by yourself + create: true + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + # Annotations to add to the service account + annotations: {} + +# The name of a secret in the same kubernetes namespace which contains values to +# be added to the environment (must be manually created) +# This can be useful for passwords and logins, etc. + +# envFromSecret: "emqx-secrets" + +## Forces the recreation of pods during helm upgrades. This can be useful to update configuration values even if the container image did not change. +recreatePods: false + +## Sets the minReadySeconds parameter on the stateful set. This can be used to add delay between restart / updates between the single pods. +minReadySeconds: + +## Sets the priorityClassName parameter on the pods. This can be used to run the pods with increased priority. +priorityClassName: + +clusterDomain: cluster.local + +## Custom annotations to be added to the pods +podAnnotations: {} + +## Custom labels to be added to the pods +podLabels: {} + +# Pod deployment policy +# value: OrderedReady | Parallel +# To redeploy a chart with existing PVC(s), the value must be set to Parallel to avoid deadlock +podManagementPolicy: Parallel + +persistence: + enabled: false + size: 20Mi + storageClassName: "" + accessMode: ReadWriteOnce + ## Existing PersistentVolumeClaims + ## The value is evaluated as a template + ## So, for example, the name can depend on .Release or .Chart + # existingClaim: "" + +resources: {} + # limits: + # cpu: 500m + # memory: 512Mi + # requests: + # cpu: 500m + # memory: 512Mi + +extraVolumeMounts: [] +## Additional volumeMounts to the default backend container. +# - name: my-owner-acl +# mountPath: /opt/emqx/etc/acl.conf +# subPath: acl.conf + +extraVolumes: [] +## Additional volumes to the default backend pod. +# - name: my-owner-acl +# secret: fake-acl-conf + +# Containers that run before the creation of EMQX containers. They can contain utilities or setup scripts. +initContainers: {} + # - name: sysctl + # image: busybox + # securityContext: + # runAsUser: 0 + # runAsGroup: 0 + # capabilities: + # add: + # - SYS_ADMIN + # drop: + # - ALL + # command: + # - /bin/sh + # - -c + # - | + # mount -o remount rw /proc/sys + # sysctl -w net.core.somaxconn=65535 + # sysctl -w net.ipv4.ip_local_port_range="1024 65535" + # sysctl -w kernel.core_uses_pid=0 + # sysctl -w net.ipv4.tcp_tw_reuse=1 + # sysctl -w fs.nr_open=1000000000 + # sysctl -w fs.file-max=1000000000 + # sysctl -w net.ipv4.ip_local_port_range='1025 65534' + # sysctl -w net.ipv4.udp_mem='74583000 499445000 749166000' + # sysctl -w net.ipv4.tcp_max_sync_backlog=163840 + # sysctl -w net.core.netdev_max_backlog=163840 + # sysctl -w net.core.optmem_max=16777216 + # sysctl -w net.ipv4.tcp_rmem='1024 4096 16777216' + # sysctl -w net.ipv4.tcp_wmem='1024 4096 16777216' + # sysctl -w net.ipv4.tcp_max_tw_buckets=1048576 + # sysctl -w net.ipv4.tcp_fin_timeout=15 + # sysctl -w net.core.rmem_default=262144000 + # sysctl -w net.core.wmem_default=262144000 + # sysctl -w net.core.rmem_max=262144000 + # sysctl -w net.core.wmem_max=262144000 + # sysctl -w net.ipv4.tcp_mem='378150000 504200000 756300000' + # sysctl -w net.netfilter.nf_conntrack_max=1000000 + # sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30 + +## EMQX configuration item, see the documentation (https://hub.docker.com/r/emqx/emqx) +emqxConfig: + EMQX_CLUSTER__DISCOVERY_STRATEGY: "dns" + EMQX_DASHBOARD__DEFAULT_USERNAME: "admin" + EMQX_DASHBOARD__DEFAULT_PASSWORD: "public" + +## EMQX Enterprise Edition requires manual creation of a Secret containing the licensed content. Write the name of Secret to the value of "emqxLicenseSecretName" +## Example: +## kubectl create secret generic emqx-license-secret-name --from-file=/path/to/emqx.lic +emqxLicenseSecretName: + +service: + ## Service type + ## + type: ClusterIP + ## The cluster IP if one wants to customize it to a fixed value + ## + clusterIP: None + ## Port for MQTT + ## + mqtt: 1883 + ## Port for MQTT(SSL) + ## + mqttssl: 8883 + ## Port for WebSocket/HTTP + ## + ws: 8083 + ## Port for WSS/HTTPS + ## + wss: 8084 + ## Port for dashboard and API + ## + dashboard: 18083 + ## Port for dashboard and API over HTTPS + ## + # dashboardtls: 18084 + ## Specify the nodePort(s) value for the LoadBalancer and NodePort service types. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + nodePorts: + mqtt: + mqttssl: + mgmt: + ws: + wss: + dashboard: + dashboardtls: + ## Specifies the load balancer implementation this Service belongs to. + ## Once set, it can not be changed. + ## + # loadBalancerClass: + ## Set the LoadBalancer service type to internal only. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + # loadBalancerIP: + ## Load Balancer sources + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## Example: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## Set the ExternalIPs + ## + externalIPs: [] + ## Denotes if this Service desires to route external traffic to node-local or cluster-wide endpoints. + ## There are two available options: Cluster (default) and Local. + ## Cluster obscures the client source IP and may cause a second hop to another node, but should have good overall load-spreading. + ## Local preserves the client source IP and avoids a second hop for LoadBalancer and NodePort type Services, but risks potentially imbalanced traffic spreading. + ## + externalTrafficPolicy: "Cluster" + ## Provide any additional annotations which may be required. Evaluated as a template + ## + annotations: {} + labels: {} + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +topologySpreadConstraints: [] + +ingress: + ## ingress for EMQX Dashboard + dashboard: + enabled: false + # ingressClassName: nginx + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + path: / + pathType: ImplementationSpecific + hosts: + - dashboard.emqx.local + tls: [] + ## ingress for MQTT + mqtt: + enabled: false + # ingressClassName: haproxy + annotations: {} + # kubernetes.io/ingress.class: haproxy + # kubernetes.io/tls-acme: "true" + # haproxy-ingress.github.io/tcp-service-port: "8883" + # haproxy-ingress.github.io/proxy-protocol: "v2" + path: / + pathType: ImplementationSpecific + hosts: + - mqtt.emqx.local + tls: [] + ws: + enabled: false + # ingressClassName: haproxy + annotations: {} + # kubernetes.io/ingress.class: haproxy + # kubernetes.io/tls-acme: "true" + # haproxy-ingress.github.io/tcp-service-port: "8883" + # haproxy-ingress.github.io/proxy-protocol: "v2" + path: /mqtt + pathType: ImplementationSpecific + hosts: + - mqtt.emqx.local + tls: [] + +podSecurityContext: + enabled: true + fsGroup: 1000 + fsGroupChangePolicy: Always + runAsUser: 1000 + supplementalGroups: + - 1000 + +containerSecurityContext: + enabled: true + runAsNonRoot: true + runAsUser: 1000 + +metrics: + enabled: false + type: prometheus + +ssl: + enabled: false + useExisting: false + existingName: emqx-tls + dnsnames: [] + commonName: + issuer: + name: letsencrypt-dns + kind: ClusterIssuer + +## Setting PodDisruptionBudget. +## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb +## +pdb: + enabled: false + maxUnavailable: 1 diff --git a/backing-services/external-secrets/Chart.lock b/backing-services/external-secrets/Chart.lock new file mode 100644 index 0000000..1d198fe --- /dev/null +++ b/backing-services/external-secrets/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: bitwarden-sdk-server + repository: oci://ghcr.io/external-secrets/charts + version: v0.1.4 +digest: sha256:f60d5e4c6ad432fc7efdb0dad33774afaa88e02bd82eb9d5224372828f7d52be +generated: "2024-06-20T10:01:52.49841+02:00" diff --git a/backing-services/external-secrets/Chart.yaml b/backing-services/external-secrets/Chart.yaml new file mode 100644 index 0000000..ab74d82 --- /dev/null +++ b/backing-services/external-secrets/Chart.yaml @@ -0,0 +1,20 @@ +apiVersion: v2 +appVersion: v0.9.20 +dependencies: +- condition: bitwarden-sdk-server.enabled + name: bitwarden-sdk-server + repository: oci://ghcr.io/external-secrets/charts + version: v0.1.4 +description: External secret management for Kubernetes +home: https://github.com/external-secrets/external-secrets +icon: https://raw.githubusercontent.com/external-secrets/external-secrets/main/assets/eso-logo-large.png +keywords: +- kubernetes-external-secrets +- secrets +kubeVersion: '>= 1.19.0-0' +maintainers: +- email: kellinmcavoy@gmail.com + name: mcavoyk +name: external-secrets +type: application +version: 0.9.20 diff --git a/backing-services/external-secrets/README.md b/backing-services/external-secrets/README.md new file mode 100644 index 0000000..1ce3bb8 --- /dev/null +++ b/backing-services/external-secrets/README.md @@ -0,0 +1,225 @@ +# External Secrets + +

external-secrets

+ +[//]: # (README.md generated by gotmpl. DO NOT EDIT.) + +![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![Version: 0.9.20](https://img.shields.io/badge/Version-0.9.20-informational?style=flat-square) + +External secret management for Kubernetes + +## TL;DR +```bash +helm repo add external-secrets https://charts.external-secrets.io +helm install external-secrets external-secrets/external-secrets +``` + +## Installing the Chart +To install the chart with the release name `external-secrets`: +```bash +helm install external-secrets external-secrets/external-secrets +``` + +### Custom Resources +By default, the chart will install external-secrets CRDs, this can be controlled with `installCRDs` value. + +## Uninstalling the Chart +To uninstall the `external-secrets` deployment: +```bash +helm uninstall external-secrets +``` +The command removes all the Kubernetes components associated with the chart and deletes the release. + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | | +| bitwarden-sdk-server.enabled | bool | `false` | | +| certController.affinity | object | `{}` | | +| certController.create | bool | `true` | Specifies whether a certificate controller deployment be created. | +| certController.deploymentAnnotations | object | `{}` | Annotations to add to Deployment | +| certController.extraArgs | object | `{}` | | +| certController.extraEnv | list | `[]` | | +| certController.extraVolumeMounts | list | `[]` | | +| certController.extraVolumes | list | `[]` | | +| certController.fullnameOverride | string | `""` | | +| certController.hostNetwork | bool | `false` | Run the certController on the host network | +| certController.image.flavour | string | `""` | | +| certController.image.pullPolicy | string | `"IfNotPresent"` | | +| certController.image.repository | string | `"ghcr.io/external-secrets/external-secrets"` | | +| certController.image.tag | string | `""` | | +| certController.imagePullSecrets | list | `[]` | | +| certController.log | object | `{"level":"info","timeEncoding":"epoch"}` | Specifices Log Params to the Webhook | +| certController.metrics.listen.port | int | `8080` | | +| certController.metrics.service.annotations | object | `{}` | Additional service annotations | +| certController.metrics.service.enabled | bool | `false` | Enable if you use another monitoring tool than Prometheus to scrape the metrics | +| certController.metrics.service.port | int | `8080` | Metrics service port to scrape | +| certController.nameOverride | string | `""` | | +| certController.nodeSelector | object | `{}` | | +| certController.podAnnotations | object | `{}` | Annotations to add to Pod | +| certController.podDisruptionBudget | object | `{"enabled":false,"minAvailable":1}` | Pod disruption budget - for more details see https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ | +| certController.podLabels | object | `{}` | | +| certController.podSecurityContext.enabled | bool | `true` | | +| certController.priorityClassName | string | `""` | Pod priority class name. | +| certController.rbac.create | bool | `true` | Specifies whether role and rolebinding resources should be created. | +| certController.readinessProbe.address | string | `""` | Address for readiness probe | +| certController.readinessProbe.port | int | `8081` | ReadinessProbe port for kubelet | +| certController.replicaCount | int | `1` | | +| certController.requeueInterval | string | `"5m"` | | +| certController.resources | object | `{}` | | +| certController.revisionHistoryLimit | int | `10` | Specifies the amount of historic ReplicaSets k8s should keep (see https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#clean-up-policy) | +| certController.securityContext.allowPrivilegeEscalation | bool | `false` | | +| certController.securityContext.capabilities.drop[0] | string | `"ALL"` | | +| certController.securityContext.enabled | bool | `true` | | +| certController.securityContext.readOnlyRootFilesystem | bool | `true` | | +| certController.securityContext.runAsNonRoot | bool | `true` | | +| certController.securityContext.runAsUser | int | `1000` | | +| certController.securityContext.seccompProfile.type | string | `"RuntimeDefault"` | | +| certController.serviceAccount.annotations | object | `{}` | Annotations to add to the service account. | +| certController.serviceAccount.automount | bool | `true` | Automounts the service account token in all containers of the pod | +| certController.serviceAccount.create | bool | `true` | Specifies whether a service account should be created. | +| certController.serviceAccount.extraLabels | object | `{}` | Extra Labels to add to the service account. | +| certController.serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template. | +| certController.tolerations | list | `[]` | | +| certController.topologySpreadConstraints | list | `[]` | | +| commonLabels | object | `{}` | Additional labels added to all helm chart resources. | +| concurrent | int | `1` | Specifies the number of concurrent ExternalSecret Reconciles external-secret executes at a time. | +| controllerClass | string | `""` | If set external secrets will filter matching Secret Stores with the appropriate controller values. | +| crds.annotations | object | `{}` | | +| crds.conversion.enabled | bool | `true` | | +| crds.createClusterExternalSecret | bool | `true` | If true, create CRDs for Cluster External Secret. | +| crds.createClusterSecretStore | bool | `true` | If true, create CRDs for Cluster Secret Store. | +| crds.createPushSecret | bool | `true` | If true, create CRDs for Push Secret. | +| createOperator | bool | `true` | Specifies whether an external secret operator deployment be created. | +| deploymentAnnotations | object | `{}` | Annotations to add to Deployment | +| dnsConfig | object | `{}` | Specifies `dnsOptions` to deployment | +| dnsPolicy | string | `"ClusterFirst"` | Specifies `dnsPolicy` to deployment | +| extendedMetricLabels | bool | `false` | If true external secrets will use recommended kubernetes annotations as prometheus metric labels. | +| extraArgs | object | `{}` | | +| extraContainers | list | `[]` | | +| extraEnv | list | `[]` | | +| extraObjects | list | `[]` | | +| extraVolumeMounts | list | `[]` | | +| extraVolumes | list | `[]` | | +| fullnameOverride | string | `""` | | +| global.affinity | object | `{}` | | +| global.compatibility.openshift.adaptSecurityContext | string | `"auto"` | Manages the securityContext properties to make them compatible with OpenShift. Possible values: auto - Apply configurations if it is detected that OpenShift is the target platform. force - Always apply configurations. disabled - No modification applied. | +| global.nodeSelector | object | `{}` | | +| global.tolerations | list | `[]` | | +| global.topologySpreadConstraints | list | `[]` | | +| hostNetwork | bool | `false` | Run the controller on the host network | +| image.flavour | string | `""` | The flavour of tag you want to use There are different image flavours available, like distroless and ubi. Please see GitHub release notes for image tags for these flavors. By default, the distroless image is used. | +| image.pullPolicy | string | `"IfNotPresent"` | | +| image.repository | string | `"ghcr.io/external-secrets/external-secrets"` | | +| image.tag | string | `""` | The image tag to use. The default is the chart appVersion. | +| imagePullSecrets | list | `[]` | | +| installCRDs | bool | `true` | If set, install and upgrade CRDs through helm chart. | +| leaderElect | bool | `false` | If true, external-secrets will perform leader election between instances to ensure no more than one instance of external-secrets operates at a time. | +| log | object | `{"level":"info","timeEncoding":"epoch"}` | Specifices Log Params to the Webhook | +| metrics.listen.port | int | `8080` | | +| metrics.service.annotations | object | `{}` | Additional service annotations | +| metrics.service.enabled | bool | `false` | Enable if you use another monitoring tool than Prometheus to scrape the metrics | +| metrics.service.port | int | `8080` | Metrics service port to scrape | +| nameOverride | string | `""` | | +| namespaceOverride | string | `""` | | +| nodeSelector | object | `{}` | | +| podAnnotations | object | `{}` | Annotations to add to Pod | +| podDisruptionBudget | object | `{"enabled":false,"minAvailable":1}` | Pod disruption budget - for more details see https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ | +| podLabels | object | `{}` | | +| podSecurityContext.enabled | bool | `true` | | +| podSpecExtra | object | `{}` | Any extra pod spec on the deployment | +| priorityClassName | string | `""` | Pod priority class name. | +| processClusterExternalSecret | bool | `true` | if true, the operator will process cluster external secret. Else, it will ignore them. | +| processClusterStore | bool | `true` | if true, the operator will process cluster store. Else, it will ignore them. | +| processPushSecret | bool | `true` | if true, the operator will process push secret. Else, it will ignore them. | +| rbac.create | bool | `true` | Specifies whether role and rolebinding resources should be created. | +| rbac.servicebindings.create | bool | `true` | Specifies whether a clusterrole to give servicebindings read access should be created. | +| replicaCount | int | `1` | | +| resources | object | `{}` | | +| revisionHistoryLimit | int | `10` | Specifies the amount of historic ReplicaSets k8s should keep (see https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#clean-up-policy) | +| scopedNamespace | string | `""` | If set external secrets are only reconciled in the provided namespace | +| scopedRBAC | bool | `false` | Must be used with scopedNamespace. If true, create scoped RBAC roles under the scoped namespace and implicitly disable cluster stores and cluster external secrets | +| securityContext.allowPrivilegeEscalation | bool | `false` | | +| securityContext.capabilities.drop[0] | string | `"ALL"` | | +| securityContext.enabled | bool | `true` | | +| securityContext.readOnlyRootFilesystem | bool | `true` | | +| securityContext.runAsNonRoot | bool | `true` | | +| securityContext.runAsUser | int | `1000` | | +| securityContext.seccompProfile.type | string | `"RuntimeDefault"` | | +| service.ipFamilies | list | `[]` | Sets the families that should be supported and the order in which they should be applied to ClusterIP as well. Can be IPv4 and/or IPv6. | +| service.ipFamilyPolicy | string | `""` | Set the ip family policy to configure dual-stack see [Configure dual-stack](https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services) | +| serviceAccount.annotations | object | `{}` | Annotations to add to the service account. | +| serviceAccount.automount | bool | `true` | Automounts the service account token in all containers of the pod | +| serviceAccount.create | bool | `true` | Specifies whether a service account should be created. | +| serviceAccount.extraLabels | object | `{}` | Extra Labels to add to the service account. | +| serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template. | +| serviceMonitor.additionalLabels | object | `{}` | Additional labels | +| serviceMonitor.enabled | bool | `false` | Specifies whether to create a ServiceMonitor resource for collecting Prometheus metrics | +| serviceMonitor.honorLabels | bool | `false` | Let prometheus add an exported_ prefix to conflicting labels | +| serviceMonitor.interval | string | `"30s"` | Interval to scrape metrics | +| serviceMonitor.metricRelabelings | list | `[]` | Metric relabel configs to apply to samples before ingestion. [Metric Relabeling](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs) | +| serviceMonitor.namespace | string | `""` | namespace where you want to install ServiceMonitors | +| serviceMonitor.relabelings | list | `[]` | Relabel configs to apply to samples before ingestion. [Relabeling](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config) | +| serviceMonitor.scrapeTimeout | string | `"25s"` | Timeout if metrics can't be retrieved in given time interval | +| tolerations | list | `[]` | | +| topologySpreadConstraints | list | `[]` | | +| webhook.affinity | object | `{}` | | +| webhook.certCheckInterval | string | `"5m"` | Specifices the time to check if the cert is valid | +| webhook.certDir | string | `"/tmp/certs"` | | +| webhook.certManager.addInjectorAnnotations | bool | `true` | Automatically add the cert-manager.io/inject-ca-from annotation to the webhooks and CRDs. As long as you have the cert-manager CA Injector enabled, this will automatically setup your webhook's CA to the one used by cert-manager. See https://cert-manager.io/docs/concepts/ca-injector | +| webhook.certManager.cert.annotations | object | `{}` | Add extra annotations to the Certificate resource. | +| webhook.certManager.cert.create | bool | `true` | Create a certificate resource within this chart. See https://cert-manager.io/docs/usage/certificate/ | +| webhook.certManager.cert.duration | string | `"8760h"` | Set the requested duration (i.e. lifetime) of the Certificate. See https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificateSpec One year by default. | +| webhook.certManager.cert.issuerRef | object | `{"group":"cert-manager.io","kind":"Issuer","name":"my-issuer"}` | For the Certificate created by this chart, setup the issuer. See https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.IssuerSpec | +| webhook.certManager.cert.renewBefore | string | `""` | How long before the currently issued certificate’s expiry cert-manager should renew the certificate. See https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificateSpec Note that renewBefore should be greater than .webhook.lookaheadInterval since the webhook will check this far in advance that the certificate is valid. | +| webhook.certManager.enabled | bool | `false` | Enabling cert-manager support will disable the built in secret and switch to using cert-manager (installed separately) to automatically issue and renew the webhook certificate. This chart does not install cert-manager for you, See https://cert-manager.io/docs/ | +| webhook.create | bool | `true` | Specifies whether a webhook deployment be created. | +| webhook.deploymentAnnotations | object | `{}` | Annotations to add to Deployment | +| webhook.extraArgs | object | `{}` | | +| webhook.extraEnv | list | `[]` | | +| webhook.extraVolumeMounts | list | `[]` | | +| webhook.extraVolumes | list | `[]` | | +| webhook.failurePolicy | string | `"Fail"` | Specifies whether validating webhooks should be created with failurePolicy: Fail or Ignore | +| webhook.fullnameOverride | string | `""` | | +| webhook.hostNetwork | bool | `false` | Specifies if webhook pod should use hostNetwork or not. | +| webhook.image.flavour | string | `""` | The flavour of tag you want to use | +| webhook.image.pullPolicy | string | `"IfNotPresent"` | | +| webhook.image.repository | string | `"ghcr.io/external-secrets/external-secrets"` | | +| webhook.image.tag | string | `""` | The image tag to use. The default is the chart appVersion. | +| webhook.imagePullSecrets | list | `[]` | | +| webhook.log | object | `{"level":"info","timeEncoding":"epoch"}` | Specifices Log Params to the Webhook | +| webhook.lookaheadInterval | string | `""` | Specifices the lookaheadInterval for certificate validity | +| webhook.metrics.listen.port | int | `8080` | | +| webhook.metrics.service.annotations | object | `{}` | Additional service annotations | +| webhook.metrics.service.enabled | bool | `false` | Enable if you use another monitoring tool than Prometheus to scrape the metrics | +| webhook.metrics.service.port | int | `8080` | Metrics service port to scrape | +| webhook.nameOverride | string | `""` | | +| webhook.nodeSelector | object | `{}` | | +| webhook.podAnnotations | object | `{}` | Annotations to add to Pod | +| webhook.podDisruptionBudget | object | `{"enabled":false,"minAvailable":1}` | Pod disruption budget - for more details see https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ | +| webhook.podLabels | object | `{}` | | +| webhook.podSecurityContext.enabled | bool | `true` | | +| webhook.port | int | `10250` | The port the webhook will listen to | +| webhook.priorityClassName | string | `""` | Pod priority class name. | +| webhook.rbac.create | bool | `true` | Specifies whether role and rolebinding resources should be created. | +| webhook.readinessProbe.address | string | `""` | Address for readiness probe | +| webhook.readinessProbe.port | int | `8081` | ReadinessProbe port for kubelet | +| webhook.replicaCount | int | `1` | | +| webhook.resources | object | `{}` | | +| webhook.revisionHistoryLimit | int | `10` | Specifies the amount of historic ReplicaSets k8s should keep (see https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#clean-up-policy) | +| webhook.secretAnnotations | object | `{}` | Annotations to add to Secret | +| webhook.securityContext.allowPrivilegeEscalation | bool | `false` | | +| webhook.securityContext.capabilities.drop[0] | string | `"ALL"` | | +| webhook.securityContext.enabled | bool | `true` | | +| webhook.securityContext.readOnlyRootFilesystem | bool | `true` | | +| webhook.securityContext.runAsNonRoot | bool | `true` | | +| webhook.securityContext.runAsUser | int | `1000` | | +| webhook.securityContext.seccompProfile.type | string | `"RuntimeDefault"` | | +| webhook.serviceAccount.annotations | object | `{}` | Annotations to add to the service account. | +| webhook.serviceAccount.automount | bool | `true` | Automounts the service account token in all containers of the pod | +| webhook.serviceAccount.create | bool | `true` | Specifies whether a service account should be created. | +| webhook.serviceAccount.extraLabels | object | `{}` | Extra Labels to add to the service account. | +| webhook.serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template. | +| webhook.tolerations | list | `[]` | | +| webhook.topologySpreadConstraints | list | `[]` | | diff --git a/backing-services/external-secrets/auction-onsite-alpha.values.yaml b/backing-services/external-secrets/auction-onsite-alpha.values.yaml new file mode 100644 index 0000000..28d1884 --- /dev/null +++ b/backing-services/external-secrets/auction-onsite-alpha.values.yaml @@ -0,0 +1,3 @@ +global: + nodeSelector: {} + tolerations: [] \ No newline at end of file diff --git a/backing-services/external-secrets/charts/bitwarden-sdk-server/.helmignore b/backing-services/external-secrets/charts/bitwarden-sdk-server/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/backing-services/external-secrets/charts/bitwarden-sdk-server/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/backing-services/external-secrets/charts/bitwarden-sdk-server/Chart.yaml b/backing-services/external-secrets/charts/bitwarden-sdk-server/Chart.yaml new file mode 100644 index 0000000..00fdedd --- /dev/null +++ b/backing-services/external-secrets/charts/bitwarden-sdk-server/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +appVersion: v0.1.4 +description: A Helm chart for Kubernetes +name: bitwarden-sdk-server +type: application +version: v0.1.4 diff --git a/backing-services/external-secrets/charts/bitwarden-sdk-server/templates/NOTES.txt b/backing-services/external-secrets/charts/bitwarden-sdk-server/templates/NOTES.txt new file mode 100644 index 0000000..46b671c --- /dev/null +++ b/backing-services/external-secrets/charts/bitwarden-sdk-server/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "bitwarden-sdk-server.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "bitwarden-sdk-server.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "bitwarden-sdk-server.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "bitwarden-sdk-server.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/backing-services/external-secrets/charts/bitwarden-sdk-server/templates/_helpers.tpl b/backing-services/external-secrets/charts/bitwarden-sdk-server/templates/_helpers.tpl new file mode 100644 index 0000000..a5e0da3 --- /dev/null +++ b/backing-services/external-secrets/charts/bitwarden-sdk-server/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "bitwarden-sdk-server.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "bitwarden-sdk-server.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "bitwarden-sdk-server.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "bitwarden-sdk-server.labels" -}} +helm.sh/chart: {{ include "bitwarden-sdk-server.chart" . }} +{{ include "bitwarden-sdk-server.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "bitwarden-sdk-server.selectorLabels" -}} +app.kubernetes.io/name: {{ include "bitwarden-sdk-server.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "bitwarden-sdk-server.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "bitwarden-sdk-server.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/backing-services/external-secrets/charts/bitwarden-sdk-server/templates/deployment.yaml b/backing-services/external-secrets/charts/bitwarden-sdk-server/templates/deployment.yaml new file mode 100644 index 0000000..a247906 --- /dev/null +++ b/backing-services/external-secrets/charts/bitwarden-sdk-server/templates/deployment.yaml @@ -0,0 +1,75 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "bitwarden-sdk-server.fullname" . }} + labels: + {{- include "bitwarden-sdk-server.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "bitwarden-sdk-server.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "bitwarden-sdk-server.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "bitwarden-sdk-server.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + {{- if not .Values.image.tls.enabled }} + args: + - --insecure + {{- end }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.image.tls.enabled }} + volumeMounts: + {{- toYaml .Values.image.tls.volumeMounts | nindent 10 }} + {{- end}} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + {{- if not .Values.image.tls.enabled }} + livenessProbe: + httpGet: + path: /live + port: http + scheme: HTTPS + readinessProbe: + httpGet: + path: /ready + port: http + scheme: HTTPS + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.image.tls.enabled }} + volumes: + {{- toYaml .Values.image.tls.volumes | nindent 8 }} + {{- end}} diff --git a/backing-services/external-secrets/charts/bitwarden-sdk-server/templates/service.yaml b/backing-services/external-secrets/charts/bitwarden-sdk-server/templates/service.yaml new file mode 100644 index 0000000..88e2d66 --- /dev/null +++ b/backing-services/external-secrets/charts/bitwarden-sdk-server/templates/service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "bitwarden-sdk-server.fullname" . }} + labels: + {{- include "bitwarden-sdk-server.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + name: http + selector: + {{- include "bitwarden-sdk-server.selectorLabels" . | nindent 4 }} diff --git a/backing-services/external-secrets/charts/bitwarden-sdk-server/templates/serviceaccount.yaml b/backing-services/external-secrets/charts/bitwarden-sdk-server/templates/serviceaccount.yaml new file mode 100644 index 0000000..fef7bad --- /dev/null +++ b/backing-services/external-secrets/charts/bitwarden-sdk-server/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "bitwarden-sdk-server.serviceAccountName" . }} + labels: + {{- include "bitwarden-sdk-server.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/external-secrets/charts/bitwarden-sdk-server/templates/tests/test-connection.yaml b/backing-services/external-secrets/charts/bitwarden-sdk-server/templates/tests/test-connection.yaml new file mode 100644 index 0000000..9f5ca59 --- /dev/null +++ b/backing-services/external-secrets/charts/bitwarden-sdk-server/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "bitwarden-sdk-server.fullname" . }}-test-connection" + labels: + {{- include "bitwarden-sdk-server.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ include "bitwarden-sdk-server.fullname" . }}:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/backing-services/external-secrets/charts/bitwarden-sdk-server/values.yaml b/backing-services/external-secrets/charts/bitwarden-sdk-server/values.yaml new file mode 100644 index 0000000..f0424af --- /dev/null +++ b/backing-services/external-secrets/charts/bitwarden-sdk-server/values.yaml @@ -0,0 +1,98 @@ +# Default values for bitwarden-sdk-server. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: ghcr.io/external-secrets/bitwarden-sdk-server + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + tls: + enabled: true + volumeMounts: + - mountPath: "/certs" + name: "bitwarden-tls-certs" + volumes: + - name: "bitwarden-tls-certs" + secret: + secretName: "bitwarden-tls-certs" + items: + - key: "tls.crt" + path: "cert.pem" + - key: "tls.key" + path: "key.pem" + - key: "ca.crt" + path: "ca.pem" + +imagePullSecrets: [] +nameOverride: "bitwarden-sdk-server" +fullnameOverride: "bitwarden-sdk-server" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 9998 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/backing-services/external-secrets/hospital-bahman-production.values.yaml b/backing-services/external-secrets/hospital-bahman-production.values.yaml new file mode 100644 index 0000000..ab1d5d5 --- /dev/null +++ b/backing-services/external-secrets/hospital-bahman-production.values.yaml @@ -0,0 +1,21 @@ +image: + repository: 172.16.16.1:30516/external-secrets/external-secrets + pullPolicy: IfNotPresent + tag: "v0.9.20" + +certController: + image: + repository: 172.16.16.1:30516/external-secrets/external-secrets + pullPolicy: IfNotPresent + tag: "v0.9.20" + +webhook: + image: + repository: 172.16.16.1:30516/external-secrets/external-secrets + pullPolicy: IfNotPresent + tag: "v0.9.20" + +global: + nodeSelector: + node.name: node-01 + tolerations: [] \ No newline at end of file diff --git a/backing-services/external-secrets/hospital-bahman.values.yaml b/backing-services/external-secrets/hospital-bahman.values.yaml new file mode 100644 index 0000000..28d1884 --- /dev/null +++ b/backing-services/external-secrets/hospital-bahman.values.yaml @@ -0,0 +1,3 @@ +global: + nodeSelector: {} + tolerations: [] \ No newline at end of file diff --git a/backing-services/external-secrets/ride-stage-tavana.values.yaml b/backing-services/external-secrets/ride-stage-tavana.values.yaml new file mode 100644 index 0000000..28d1884 --- /dev/null +++ b/backing-services/external-secrets/ride-stage-tavana.values.yaml @@ -0,0 +1,3 @@ +global: + nodeSelector: {} + tolerations: [] \ No newline at end of file diff --git a/backing-services/external-secrets/schoobus-onsite.values.yaml b/backing-services/external-secrets/schoobus-onsite.values.yaml new file mode 100644 index 0000000..28d1884 --- /dev/null +++ b/backing-services/external-secrets/schoobus-onsite.values.yaml @@ -0,0 +1,3 @@ +global: + nodeSelector: {} + tolerations: [] \ No newline at end of file diff --git a/backing-services/external-secrets/school-stage-tavana.values.yaml b/backing-services/external-secrets/school-stage-tavana.values.yaml new file mode 100644 index 0000000..70d1e82 --- /dev/null +++ b/backing-services/external-secrets/school-stage-tavana.values.yaml @@ -0,0 +1,29 @@ +image: + repository: 172.16.16.1:30516/external-secrets/external-secrets + pullPolicy: IfNotPresent + tag: "v0.9.20" + +certController: + image: + repository: 172.16.16.1:30516/external-secrets/external-secrets + pullPolicy: IfNotPresent + tag: "v0.9.20" + +webhook: + image: + repository: 172.16.16.1:30516/external-secrets/external-secrets + pullPolicy: IfNotPresent + tag: "v0.9.20" + +resources: + requests: + cpu: 200m + memory: 300Mi + limits: + cpu: 200m + memory: 300Mi + +global: + nodeSelector: + node.name: node-01 + tolerations: [] \ No newline at end of file diff --git a/backing-services/external-secrets/schoolbus-demo.values.yaml b/backing-services/external-secrets/schoolbus-demo.values.yaml new file mode 100644 index 0000000..114da1d --- /dev/null +++ b/backing-services/external-secrets/schoolbus-demo.values.yaml @@ -0,0 +1,29 @@ +image: + repository: 172.16.16.2:30516/external-secrets/external-secrets + pullPolicy: IfNotPresent + tag: "v0.9.20" + +certController: + image: + repository: 172.16.16.2:30516/external-secrets/external-secrets + pullPolicy: IfNotPresent + tag: "v0.9.20" + +webhook: + image: + repository: 172.16.16.2:30516/external-secrets/external-secrets + pullPolicy: IfNotPresent + tag: "v0.9.20" + +resources: + requests: + cpu: 100m + memory: 200Mi + limits: + cpu: 100m + memory: 200Mi + +global: + nodeSelector: + node.name: node-1 + tolerations: [] \ No newline at end of file diff --git a/backing-services/external-secrets/schoolbuses.values.yaml b/backing-services/external-secrets/schoolbuses.values.yaml new file mode 100644 index 0000000..28d1884 --- /dev/null +++ b/backing-services/external-secrets/schoolbuses.values.yaml @@ -0,0 +1,3 @@ +global: + nodeSelector: {} + tolerations: [] \ No newline at end of file diff --git a/backing-services/external-secrets/templates/NOTES.txt b/backing-services/external-secrets/templates/NOTES.txt new file mode 100644 index 0000000..ffa0fc7 --- /dev/null +++ b/backing-services/external-secrets/templates/NOTES.txt @@ -0,0 +1,7 @@ +external-secrets has been deployed successfully in namespace {{ template "external-secrets.namespace" . }}! + +In order to begin using ExternalSecrets, you will need to set up a SecretStore +or ClusterSecretStore resource (for example, by creating a 'vault' SecretStore). + +More information on the different types of SecretStores and how to configure them +can be found in our Github: {{ .Chart.Home }} diff --git a/backing-services/external-secrets/templates/_helpers.tpl b/backing-services/external-secrets/templates/_helpers.tpl new file mode 100644 index 0000000..d5eea07 --- /dev/null +++ b/backing-services/external-secrets/templates/_helpers.tpl @@ -0,0 +1,198 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "external-secrets.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "external-secrets.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 }} + +{{/* +Define namespace of chart, useful for multi-namespace deployments +*/}} +{{- define "external-secrets.namespace" -}} +{{- if .Values.namespaceOverride }} +{{- .Values.namespaceOverride }} +{{- else }} +{{- .Release.Namespace }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "external-secrets.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "external-secrets.labels" -}} +helm.sh/chart: {{ include "external-secrets.chart" . }} +{{ include "external-secrets.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Values.commonLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{- define "external-secrets-webhook.labels" -}} +helm.sh/chart: {{ include "external-secrets.chart" . }} +{{ include "external-secrets-webhook.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Values.commonLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{- define "external-secrets-webhook-metrics.labels" -}} +{{ include "external-secrets-webhook.selectorLabels" . }} +app.kubernetes.io/metrics: "webhook" +{{- with .Values.commonLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{- define "external-secrets-cert-controller.labels" -}} +helm.sh/chart: {{ include "external-secrets.chart" . }} +{{ include "external-secrets-cert-controller.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Values.commonLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{- define "external-secrets-cert-controller-metrics.labels" -}} +{{ include "external-secrets-cert-controller.selectorLabels" . }} +app.kubernetes.io/metrics: "cert-controller" +{{- with .Values.commonLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "external-secrets.selectorLabels" -}} +app.kubernetes.io/name: {{ include "external-secrets.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} +{{- define "external-secrets-webhook.selectorLabels" -}} +app.kubernetes.io/name: {{ include "external-secrets.name" . }}-webhook +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} +{{- define "external-secrets-cert-controller.selectorLabels" -}} +app.kubernetes.io/name: {{ include "external-secrets.name" . }}-cert-controller +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} +{{/* +Create the name of the service account to use +*/}} +{{- define "external-secrets.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "external-secrets.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "external-secrets-webhook.serviceAccountName" -}} +{{- if .Values.webhook.serviceAccount.create }} +{{- default "external-secrets-webhook" .Values.webhook.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.webhook.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "external-secrets-cert-controller.serviceAccountName" -}} +{{- if .Values.certController.serviceAccount.create }} +{{- default "external-secrets-cert-controller" .Values.certController.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.certController.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Determine the image to use, including if using a flavour. +*/}} +{{- define "external-secrets.image" -}} +{{- if .image.flavour -}} +{{ printf "%s:%s-%s" .image.repository (.image.tag | default .chartAppVersion) .image.flavour }} +{{- else }} +{{ printf "%s:%s" .image.repository (.image.tag | default .chartAppVersion) }} +{{- end }} +{{- end }} + +{{/* +Renders a complete tree, even values that contains template. +*/}} +{{- define "external-secrets.render" -}} + {{- if typeIs "string" .value }} + {{- tpl .value .context }} + {{ else }} + {{- tpl (.value | toYaml) .context }} + {{- end }} +{{- end -}} + +{{/* +Return true if the OpenShift is the detected platform +Usage: +{{- include "external-secrets.isOpenShift" . -}} +*/}} +{{- define "external-secrets.isOpenShift" -}} +{{- if .Capabilities.APIVersions.Has "security.openshift.io/v1" -}} +{{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Render the securityContext based on the provided securityContext + {{- include "external-secrets.renderSecurityContext" (dict "securityContext" .Values.securityContext "context" $) -}} +*/}} +{{- define "external-secrets.renderSecurityContext" -}} +{{- $adaptedContext := .securityContext -}} +{{- if .context.Values.global.compatibility -}} + {{- if .context.Values.global.compatibility.openshift -}} + {{- if or (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "force") (and (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "auto") (include "external-secrets.isOpenShift" .context)) -}} + {{/* Remove OpenShift managed fields */}} + {{- $adaptedContext = omit $adaptedContext "fsGroup" "runAsUser" "runAsGroup" -}} + {{- if not .securityContext.seLinuxOptions -}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- omit $adaptedContext "enabled" | toYaml -}} +{{- end -}} diff --git a/backing-services/external-secrets/templates/cert-controller-deployment.yaml b/backing-services/external-secrets/templates/cert-controller-deployment.yaml new file mode 100644 index 0000000..a843f04 --- /dev/null +++ b/backing-services/external-secrets/templates/cert-controller-deployment.yaml @@ -0,0 +1,124 @@ +{{- if and .Values.certController.create (not .Values.webhook.certManager.enabled) }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "external-secrets.fullname" . }}-cert-controller + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets-cert-controller.labels" . | nindent 4 }} + {{- with .Values.certController.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.certController.replicaCount }} + revisionHistoryLimit: {{ .Values.certController.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "external-secrets-cert-controller.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.certController.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "external-secrets-cert-controller.labels" . | nindent 8 }} + {{- with .Values.certController.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.certController.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "external-secrets-cert-controller.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.certController.serviceAccount.automount }} + {{- with .Values.certController.podSecurityContext }} + {{- if and (.enabled) (gt (keys . | len) 1) }} + securityContext: + {{- include "external-secrets.renderSecurityContext" (dict "securityContext" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + hostNetwork: {{ .Values.certController.hostNetwork }} + containers: + - name: cert-controller + {{- with .Values.certController.securityContext }} + {{- if and (.enabled) (gt (keys . | len) 1) }} + securityContext: + {{- include "external-secrets.renderSecurityContext" (dict "securityContext" . "context" $) | nindent 12 }} + {{- end }} + {{- end }} + image: {{ include "external-secrets.image" (dict "chartAppVersion" .Chart.AppVersion "image" .Values.certController.image) | trim }} + imagePullPolicy: {{ .Values.certController.image.pullPolicy }} + args: + - certcontroller + - --crd-requeue-interval={{ .Values.certController.requeueInterval }} + - --service-name={{ include "external-secrets.fullname" . }}-webhook + - --service-namespace={{ template "external-secrets.namespace" . }} + - --secret-name={{ include "external-secrets.fullname" . }}-webhook + - --secret-namespace={{ template "external-secrets.namespace" . }} + - --metrics-addr=:{{ .Values.certController.metrics.listen.port }} + - --healthz-addr={{ .Values.certController.readinessProbe.address }}:{{ .Values.certController.readinessProbe.port }} + - --loglevel={{ .Values.certController.log.level }} + - --zap-time-encoding={{ .Values.certController.log.timeEncoding }} + {{- if not .Values.crds.createClusterSecretStore }} + - --crd-names=externalsecrets.external-secrets.io + - --crd-names=secretstores.external-secrets.io + {{- end }} + {{- if .Values.installCRDs }} + - --enable-partial-cache=true + {{- end }} + {{- range $key, $value := .Values.certController.extraArgs }} + {{- if $value }} + - --{{ $key }}={{ $value }} + {{- else }} + - --{{ $key }} + {{- end }} + {{- end }} + ports: + - containerPort: {{ .Values.certController.metrics.listen.port }} + protocol: TCP + name: metrics + readinessProbe: + httpGet: + port: {{ .Values.certController.readinessProbe.port }} + path: /readyz + initialDelaySeconds: 20 + periodSeconds: 5 + {{- with .Values.certController.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.certController.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.certController.extraVolumeMounts }} + volumeMounts: + {{- toYaml .Values.certController.extraVolumeMounts | nindent 12 }} + {{- end }} + {{- if .Values.certController.extraVolumes }} + volumes: + {{- toYaml .Values.certController.extraVolumes | nindent 8 }} + {{- end }} + {{- with .Values.certController.nodeSelector | default .Values.global.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.certController.affinity | default .Values.global.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.certController.tolerations | default .Values.global.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.certController.topologySpreadConstraints | default .Values.global.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.certController.priorityClassName }} + priorityClassName: {{ .Values.certController.priorityClassName }} + {{- end }} +{{- end }} diff --git a/backing-services/external-secrets/templates/cert-controller-poddisruptionbudget.yaml b/backing-services/external-secrets/templates/cert-controller-poddisruptionbudget.yaml new file mode 100644 index 0000000..e61cb8e --- /dev/null +++ b/backing-services/external-secrets/templates/cert-controller-poddisruptionbudget.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.certController.create .Values.certController.podDisruptionBudget.enabled (not .Values.webhook.certManager.enabled) }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "external-secrets.fullname" . }}-cert-controller-pdb + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets-cert-controller.labels" . | nindent 4 }} +spec: + {{- if .Values.certController.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.certController.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if .Values.certController.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.certController.podDisruptionBudget.maxUnavailable }} + {{- end }} + selector: + matchLabels: + {{- include "external-secrets-cert-controller.selectorLabels" . | nindent 6 }} +{{- end }} diff --git a/backing-services/external-secrets/templates/cert-controller-rbac.yaml b/backing-services/external-secrets/templates/cert-controller-rbac.yaml new file mode 100644 index 0000000..43c2306 --- /dev/null +++ b/backing-services/external-secrets/templates/cert-controller-rbac.yaml @@ -0,0 +1,78 @@ +{{- if and .Values.certController.create .Values.certController.rbac.create (not .Values.webhook.certManager.enabled) -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "external-secrets.fullname" . }}-cert-controller + labels: + {{- include "external-secrets-cert-controller.labels" . | nindent 4 }} +rules: + - apiGroups: + - "apiextensions.k8s.io" + resources: + - "customresourcedefinitions" + verbs: + - "get" + - "list" + - "watch" + - "update" + - "patch" + - apiGroups: + - "admissionregistration.k8s.io" + resources: + - "validatingwebhookconfigurations" + verbs: + - "get" + - "list" + - "watch" + - "update" + - "patch" + - apiGroups: + - "" + resources: + - "endpoints" + verbs: + - "list" + - "get" + - "watch" + - apiGroups: + - "" + resources: + - "events" + verbs: + - "create" + - "patch" + - apiGroups: + - "" + resources: + - "secrets" + verbs: + - "get" + - "list" + - "watch" + - "update" + - "patch" + - apiGroups: + - "coordination.k8s.io" + resources: + - "leases" + verbs: + - "get" + - "create" + - "update" + - "patch" +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "external-secrets.fullname" . }}-cert-controller + labels: + {{- include "external-secrets-cert-controller.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "external-secrets.fullname" . }}-cert-controller +subjects: + - name: {{ include "external-secrets-cert-controller.serviceAccountName" . }} + namespace: {{ template "external-secrets.namespace" . }} + kind: ServiceAccount +{{- end }} diff --git a/backing-services/external-secrets/templates/cert-controller-service.yaml b/backing-services/external-secrets/templates/cert-controller-service.yaml new file mode 100644 index 0000000..12cb4f4 --- /dev/null +++ b/backing-services/external-secrets/templates/cert-controller-service.yaml @@ -0,0 +1,28 @@ +{{- if and .Values.certController.create .Values.certController.metrics.service.enabled (not .Values.webhook.certManager.enabled) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "external-secrets.fullname" . }}-cert-controller-metrics + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} + {{- with .Values.metrics.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + {{- if .Values.service.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.service.ipFamilyPolicy }} + {{- end }} + {{- if .Values.service.ipFamilies }} + ipFamilies: {{ .Values.service.ipFamilies | toYaml | nindent 2 }} + {{- end }} + ports: + - port: {{ .Values.certController.metrics.service.port }} + protocol: TCP + targetPort: metrics + name: metrics + selector: + {{- include "external-secrets-cert-controller.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/backing-services/external-secrets/templates/cert-controller-serviceaccount.yaml b/backing-services/external-secrets/templates/cert-controller-serviceaccount.yaml new file mode 100644 index 0000000..6a36f9d --- /dev/null +++ b/backing-services/external-secrets/templates/cert-controller-serviceaccount.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.certController.create .Values.certController.serviceAccount.create (not .Values.webhook.certManager.enabled) -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "external-secrets-cert-controller.serviceAccountName" . }} + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets-cert-controller.labels" . | nindent 4 }} + {{- with .Values.certController.serviceAccount.extraLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.certController.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/external-secrets/templates/crds/acraccesstoken.yaml b/backing-services/external-secrets/templates/crds/acraccesstoken.yaml new file mode 100644 index 0000000..aea96d5 --- /dev/null +++ b/backing-services/external-secrets/templates/crds/acraccesstoken.yaml @@ -0,0 +1,206 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller + name: acraccesstokens.generators.external-secrets.io +spec: + group: generators.external-secrets.io + names: + categories: + - acraccesstoken + kind: ACRAccessToken + listKind: ACRAccessTokenList + plural: acraccesstokens + shortNames: + - acraccesstoken + singular: acraccesstoken + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + ACRAccessToken returns a Azure Container Registry token + that can be used for pushing/pulling images. + Note: by default it will return an ACR Refresh Token with full access + (depending on the identity). + This can be scoped down to the repository level using .spec.scope. + In case scope is defined it will return an ACR Access Token. + + + See docs: https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + ACRAccessTokenSpec defines how to generate the access token + e.g. how to authenticate and which registry to use. + see: https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md#overview + properties: + auth: + properties: + managedIdentity: + description: ManagedIdentity uses Azure Managed Identity to authenticate with Azure. + properties: + identityId: + description: If multiple Managed Identity is assigned to the pod, you can select the one to be used + type: string + type: object + servicePrincipal: + description: ServicePrincipal uses Azure Service Principal credentials to authenticate with Azure. + properties: + secretRef: + description: |- + Configuration used to authenticate with Azure using static + credentials stored in a Kind=Secret. + properties: + clientId: + description: The Azure clientId of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + clientSecret: + description: The Azure ClientSecret of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + workloadIdentity: + description: WorkloadIdentity uses Azure Workload Identity to authenticate with Azure. + properties: + serviceAccountRef: + description: |- + ServiceAccountRef specified the service account + that should be used when authenticating with WorkloadIdentity. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + type: object + type: object + environmentType: + default: PublicCloud + description: |- + EnvironmentType specifies the Azure cloud environment endpoints to use for + connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. + The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 + PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud + enum: + - PublicCloud + - USGovernmentCloud + - ChinaCloud + - GermanCloud + type: string + registry: + description: |- + the domain name of the ACR registry + e.g. foobarexample.azurecr.io + type: string + scope: + description: |- + Define the scope for the access token, e.g. pull/push access for a repository. + if not provided it will return a refresh token that has full scope. + Note: you need to pin it down to the repository level, there is no wildcard available. + + + examples: + repository:my-repository:pull,push + repository:my-repository:pull + + + see docs for details: https://docs.docker.com/registry/spec/auth/scope/ + type: string + tenantId: + description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. + type: string + required: + - auth + - registry + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/backing-services/external-secrets/templates/crds/clusterexternalsecret.yaml b/backing-services/external-secrets/templates/crds/clusterexternalsecret.yaml new file mode 100644 index 0000000..9b4103d --- /dev/null +++ b/backing-services/external-secrets/templates/crds/clusterexternalsecret.yaml @@ -0,0 +1,667 @@ +{{- if and (.Values.installCRDs) (.Values.crds.createClusterExternalSecret) }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller + name: clusterexternalsecrets.external-secrets.io +spec: + group: external-secrets.io + names: + categories: + - externalsecrets + kind: ClusterExternalSecret + listKind: ClusterExternalSecretList + plural: clusterexternalsecrets + shortNames: + - ces + singular: clusterexternalsecret + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.externalSecretSpec.secretStoreRef.name + name: Store + type: string + - jsonPath: .spec.refreshTime + name: Refresh Interval + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: ClusterExternalSecret is the Schema for the clusterexternalsecrets API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret. + properties: + externalSecretMetadata: + description: The metadata of the external secrets to be created + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + externalSecretName: + description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret + type: string + externalSecretSpec: + description: The spec for the ExternalSecrets to be created + properties: + data: + description: Data defines the connection between the Kubernetes Secret keys and the Provider data + items: + description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. + properties: + remoteRef: + description: |- + RemoteRef points to the remote secret and defines + which secret (version/property/..) to fetch. + properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + enum: + - Default + - Unicode + type: string + decodingStrategy: + default: None + description: Used to define a decoding Strategy + enum: + - Auto + - Base64 + - Base64URL + - None + type: string + key: + description: Key is the key used in the Provider, mandatory + type: string + metadataPolicy: + default: None + description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None + enum: + - None + - Fetch + type: string + property: + description: Used to select a specific property of the Provider value (if a map), if supported + type: string + version: + description: Used to select a specific version of the Provider value, if supported + type: string + required: + - key + type: object + secretKey: + description: |- + SecretKey defines the key in which the controller stores + the value. This is the key in the Kind=Secret + type: string + sourceRef: + description: |- + SourceRef allows you to override the source + from which the value will pulled from. + maxProperties: 1 + properties: + generatorRef: + description: |- + GeneratorRef points to a generator custom resource. + + + Deprecated: The generatorRef is not implemented in .data[]. + this will be removed with v1. + properties: + apiVersion: + default: generators.external-secrets.io/v1alpha1 + description: Specify the apiVersion of the generator resource + type: string + kind: + description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. + type: string + name: + description: Specify the name of the generator resource + type: string + required: + - kind + - name + type: object + storeRef: + description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. + properties: + kind: + description: |- + Kind of the SecretStore resource (SecretStore or ClusterSecretStore) + Defaults to `SecretStore` + type: string + name: + description: Name of the SecretStore resource + type: string + required: + - name + type: object + type: object + required: + - remoteRef + - secretKey + type: object + type: array + dataFrom: + description: |- + DataFrom is used to fetch all properties from a specific Provider data + If multiple entries are specified, the Secret keys are merged in the specified order + items: + properties: + extract: + description: |- + Used to extract multiple key/value pairs from one secret + Note: Extract does not support sourceRef.Generator or sourceRef.GeneratorRef. + properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + enum: + - Default + - Unicode + type: string + decodingStrategy: + default: None + description: Used to define a decoding Strategy + enum: + - Auto + - Base64 + - Base64URL + - None + type: string + key: + description: Key is the key used in the Provider, mandatory + type: string + metadataPolicy: + default: None + description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None + enum: + - None + - Fetch + type: string + property: + description: Used to select a specific property of the Provider value (if a map), if supported + type: string + version: + description: Used to select a specific version of the Provider value, if supported + type: string + required: + - key + type: object + find: + description: |- + Used to find secrets based on tags or regular expressions + Note: Find does not support sourceRef.Generator or sourceRef.GeneratorRef. + properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + enum: + - Default + - Unicode + type: string + decodingStrategy: + default: None + description: Used to define a decoding Strategy + enum: + - Auto + - Base64 + - Base64URL + - None + type: string + name: + description: Finds secrets based on the name. + properties: + regexp: + description: Finds secrets base + type: string + type: object + path: + description: A root path to start the find operations. + type: string + tags: + additionalProperties: + type: string + description: Find secrets based on tags. + type: object + type: object + rewrite: + description: |- + Used to rewrite secret Keys after getting them from the secret Provider + Multiple Rewrite operations can be provided. They are applied in a layered order (first to last) + items: + properties: + regexp: + description: |- + Used to rewrite with regular expressions. + The resulting key will be the output of a regexp.ReplaceAll operation. + properties: + source: + description: Used to define the regular expression of a re.Compiler. + type: string + target: + description: Used to define the target pattern of a ReplaceAll operation. + type: string + required: + - source + - target + type: object + transform: + description: |- + Used to apply string transformation on the secrets. + The resulting key will be the output of the template applied by the operation. + properties: + template: + description: |- + Used to define the template to apply on the secret name. + `.value ` will specify the secret name in the template. + type: string + required: + - template + type: object + type: object + type: array + sourceRef: + description: |- + SourceRef points to a store or generator + which contains secret values ready to use. + Use this in combination with Extract or Find pull values out of + a specific SecretStore. + When sourceRef points to a generator Extract or Find is not supported. + The generator returns a static map of values + maxProperties: 1 + properties: + generatorRef: + description: GeneratorRef points to a generator custom resource. + properties: + apiVersion: + default: generators.external-secrets.io/v1alpha1 + description: Specify the apiVersion of the generator resource + type: string + kind: + description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. + type: string + name: + description: Specify the name of the generator resource + type: string + required: + - kind + - name + type: object + storeRef: + description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. + properties: + kind: + description: |- + Kind of the SecretStore resource (SecretStore or ClusterSecretStore) + Defaults to `SecretStore` + type: string + name: + description: Name of the SecretStore resource + type: string + required: + - name + type: object + type: object + type: object + type: array + refreshInterval: + default: 1h + description: |- + RefreshInterval is the amount of time before the values are read again from the SecretStore provider + Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" + May be set to zero to fetch and create it once. Defaults to 1h. + type: string + secretStoreRef: + description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. + properties: + kind: + description: |- + Kind of the SecretStore resource (SecretStore or ClusterSecretStore) + Defaults to `SecretStore` + type: string + name: + description: Name of the SecretStore resource + type: string + required: + - name + type: object + target: + default: + creationPolicy: Owner + deletionPolicy: Retain + description: |- + ExternalSecretTarget defines the Kubernetes Secret to be created + There can be only one target per ExternalSecret. + properties: + creationPolicy: + default: Owner + description: |- + CreationPolicy defines rules on how to create the resulting Secret + Defaults to 'Owner' + enum: + - Owner + - Orphan + - Merge + - None + type: string + deletionPolicy: + default: Retain + description: |- + DeletionPolicy defines rules on how to delete the resulting Secret + Defaults to 'Retain' + enum: + - Delete + - Merge + - Retain + type: string + immutable: + description: Immutable defines if the final secret will be immutable + type: boolean + name: + description: |- + Name defines the name of the Secret resource to be managed + This field is immutable + Defaults to the .metadata.name of the ExternalSecret resource + type: string + template: + description: Template defines a blueprint for the created Secret resource. + properties: + data: + additionalProperties: + type: string + type: object + engineVersion: + default: v2 + description: |- + EngineVersion specifies the template engine version + that should be used to compile/execute the + template specified in .data and .templateFrom[]. + enum: + - v1 + - v2 + type: string + mergePolicy: + default: Replace + enum: + - Replace + - Merge + type: string + metadata: + description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + templateFrom: + items: + properties: + configMap: + properties: + items: + items: + properties: + key: + type: string + templateAs: + default: Values + enum: + - Values + - KeysAndValues + type: string + required: + - key + type: object + type: array + name: + type: string + required: + - items + - name + type: object + literal: + type: string + secret: + properties: + items: + items: + properties: + key: + type: string + templateAs: + default: Values + enum: + - Values + - KeysAndValues + type: string + required: + - key + type: object + type: array + name: + type: string + required: + - items + - name + type: object + target: + default: Data + enum: + - Data + - Annotations + - Labels + type: string + type: object + type: array + type: + type: string + type: object + type: object + type: object + namespaceSelector: + description: |- + The labels to select by to find the Namespaces to create the ExternalSecrets in. + Deprecated: Use NamespaceSelectors instead. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelectors: + description: A list of labels to select by to find the Namespaces to create the ExternalSecrets in. The selectors are ORed. + items: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + type: array + namespaces: + description: Choose namespaces by name. This field is ORed with anything that NamespaceSelectors ends up choosing. + items: + type: string + type: array + refreshTime: + description: The time in which the controller should reconcile its objects and recheck namespaces for labels. + type: string + required: + - externalSecretSpec + type: object + status: + description: ClusterExternalSecretStatus defines the observed state of ClusterExternalSecret. + properties: + conditions: + items: + properties: + message: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + externalSecretName: + description: ExternalSecretName is the name of the ExternalSecrets created by the ClusterExternalSecret + type: string + failedNamespaces: + description: Failed namespaces are the namespaces that failed to apply an ExternalSecret + items: + description: ClusterExternalSecretNamespaceFailure represents a failed namespace deployment and it's reason. + properties: + namespace: + description: Namespace is the namespace that failed when trying to apply an ExternalSecret + type: string + reason: + description: Reason is why the ExternalSecret failed to apply to the namespace + type: string + required: + - namespace + type: object + type: array + provisionedNamespaces: + description: ProvisionedNamespaces are the namespaces where the ClusterExternalSecret has secrets + items: + type: string + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/backing-services/external-secrets/templates/crds/clustersecretstore.yaml b/backing-services/external-secrets/templates/crds/clustersecretstore.yaml new file mode 100644 index 0000000..30760ca --- /dev/null +++ b/backing-services/external-secrets/templates/crds/clustersecretstore.yaml @@ -0,0 +1,4379 @@ +{{- if and (.Values.installCRDs) (.Values.crds.createClusterSecretStore) }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller + name: clustersecretstores.external-secrets.io +spec: + group: external-secrets.io + names: + categories: + - externalsecrets + kind: ClusterSecretStore + listKind: ClusterSecretStoreList + plural: clustersecretstores + shortNames: + - css + singular: clustersecretstore + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].reason + name: Status + type: string + deprecated: true + name: v1alpha1 + schema: + openAPIV3Schema: + description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: SecretStoreSpec defines the desired state of SecretStore. + properties: + controller: + description: |- + Used to select the correct ESO controller (think: ingress.ingressClassName) + The ESO controller is instantiated with a specific controller name and filters ES based on this property + type: string + provider: + description: Used to configure the provider. Only one provider may be set + maxProperties: 1 + minProperties: 1 + properties: + akeyless: + description: Akeyless configures this store to sync secrets using Akeyless Vault provider + properties: + akeylessGWApiURL: + description: Akeyless GW API Url from which the secrets to be fetched from. + type: string + authSecretRef: + description: Auth configures how the operator authenticates with Akeyless. + properties: + kubernetesAuth: + description: |- + Kubernetes authenticates with Akeyless by passing the ServiceAccount + token stored in the named Secret resource. + properties: + accessID: + description: the Akeyless Kubernetes auth-method access-id + type: string + k8sConfName: + description: Kubernetes-auth configuration name in Akeyless-Gateway + type: string + secretRef: + description: |- + Optional secret field containing a Kubernetes ServiceAccount JWT used + for authenticating with Akeyless. If a name is specified without a key, + `token` is the default. If one is not specified, the one bound to + the controller will be used. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + serviceAccountRef: + description: |- + Optional service account field containing the name of a kubernetes ServiceAccount. + If the service account is specified, the service account secret token JWT will be used + for authenticating with Akeyless. If the service account selector is not supplied, + the secretRef will be used instead. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + required: + - accessID + - k8sConfName + type: object + secretRef: + description: |- + Reference to a Secret that contains the details + to authenticate with Akeyless. + properties: + accessID: + description: The SecretAccessID is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + accessType: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + accessTypeParam: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + type: object + caBundle: + description: |- + PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used + if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates + are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + required: + - akeylessGWApiURL + - authSecretRef + type: object + alibaba: + description: Alibaba configures this store to sync secrets using Alibaba Cloud provider + properties: + auth: + description: AlibabaAuth contains a secretRef for credentials. + properties: + rrsa: + description: Authenticate against Alibaba using RRSA. + properties: + oidcProviderArn: + type: string + oidcTokenFilePath: + type: string + roleArn: + type: string + sessionName: + type: string + required: + - oidcProviderArn + - oidcTokenFilePath + - roleArn + - sessionName + type: object + secretRef: + description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + accessKeySecretSecretRef: + description: The AccessKeySecret is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - accessKeyIDSecretRef + - accessKeySecretSecretRef + type: object + type: object + regionID: + description: Alibaba Region to be used for the provider + type: string + required: + - auth + - regionID + type: object + aws: + description: AWS configures this store to sync secrets using AWS Secret Manager provider + properties: + auth: + description: |- + Auth defines the information necessary to authenticate against AWS + if not set aws sdk will infer credentials from your environment + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + properties: + jwt: + description: Authenticate against AWS using service account tokens. + properties: + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + type: object + secretRef: + description: |- + AWSAuthSecretRef holds secret references for AWS credentials + both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + type: object + region: + description: AWS Region to be used for the provider + type: string + role: + description: Role is a Role ARN which the SecretManager provider will assume + type: string + service: + description: Service defines which service should be used to fetch the secrets + enum: + - SecretsManager + - ParameterStore + type: string + required: + - region + - service + type: object + azurekv: + description: AzureKV configures this store to sync secrets using Azure Key Vault provider + properties: + authSecretRef: + description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. + properties: + clientId: + description: The Azure clientId of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + clientSecret: + description: The Azure ClientSecret of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + authType: + default: ServicePrincipal + description: |- + Auth type defines how to authenticate to the keyvault service. + Valid values are: + - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) + - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) + enum: + - ServicePrincipal + - ManagedIdentity + - WorkloadIdentity + type: string + identityId: + description: If multiple Managed Identity is assigned to the pod, you can select the one to be used + type: string + serviceAccountRef: + description: |- + ServiceAccountRef specified the service account + that should be used when authenticating with WorkloadIdentity. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + tenantId: + description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. + type: string + vaultUrl: + description: Vault Url from which the secrets to be fetched from. + type: string + required: + - vaultUrl + type: object + fake: + description: Fake configures a store with static key/value pairs + properties: + data: + items: + properties: + key: + type: string + value: + type: string + valueMap: + additionalProperties: + type: string + type: object + version: + type: string + required: + - key + type: object + type: array + required: + - data + type: object + gcpsm: + description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider + properties: + auth: + description: Auth defines the information necessary to authenticate against GCP + properties: + secretRef: + properties: + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + workloadIdentity: + properties: + clusterLocation: + type: string + clusterName: + type: string + clusterProjectID: + type: string + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + required: + - clusterLocation + - clusterName + - serviceAccountRef + type: object + type: object + projectID: + description: ProjectID project where secret is located + type: string + type: object + gitlab: + description: GitLab configures this store to sync secrets using GitLab Variables provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a GitLab instance. + properties: + SecretRef: + properties: + accessToken: + description: AccessToken is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - SecretRef + type: object + projectID: + description: ProjectID specifies a project where secrets are located. + type: string + url: + description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. + type: string + required: + - auth + type: object + ibm: + description: IBM configures this store to sync secrets using IBM Cloud provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the IBM secrets manager. + properties: + secretRef: + properties: + secretApiKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + serviceUrl: + description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance + type: string + required: + - auth + type: object + kubernetes: + description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a Kubernetes instance. + maxProperties: 1 + minProperties: 1 + properties: + cert: + description: has both clientCert and clientKey as secretKeySelector + properties: + clientCert: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + clientKey: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + serviceAccount: + description: points to a service account that should be used for authentication + properties: + serviceAccount: + description: A reference to a ServiceAccount resource. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + type: object + token: + description: use static token to authenticate with + properties: + bearerToken: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + type: object + remoteNamespace: + default: default + description: Remote namespace to fetch the secrets from + type: string + server: + description: configures the Kubernetes server Address. + properties: + caBundle: + description: CABundle is a base64-encoded CA certificate + format: byte + type: string + caProvider: + description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + url: + default: kubernetes.default + description: configures the Kubernetes server Address. + type: string + type: object + required: + - auth + type: object + oracle: + description: Oracle configures this store to sync secrets using Oracle Vault provider + properties: + auth: + description: |- + Auth configures how secret-manager authenticates with the Oracle Vault. + If empty, instance principal is used. Optionally, the authenticating principal type + and/or user data may be supplied for the use of workload identity and user principal. + properties: + secretRef: + description: SecretRef to pass through sensitive information. + properties: + fingerprint: + description: Fingerprint is the fingerprint of the API private key. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + privatekey: + description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - fingerprint + - privatekey + type: object + tenancy: + description: Tenancy is the tenancy OCID where user is located. + type: string + user: + description: User is an access OCID specific to the account. + type: string + required: + - secretRef + - tenancy + - user + type: object + compartment: + description: |- + Compartment is the vault compartment OCID. + Required for PushSecret + type: string + encryptionKey: + description: |- + EncryptionKey is the OCID of the encryption key within the vault. + Required for PushSecret + type: string + principalType: + description: |- + The type of principal to use for authentication. If left blank, the Auth struct will + determine the principal type. This optional field must be specified if using + workload identity. + enum: + - "" + - UserPrincipal + - InstancePrincipal + - Workload + type: string + region: + description: Region is the region where vault is located. + type: string + serviceAccountRef: + description: |- + ServiceAccountRef specified the service account + that should be used when authenticating with WorkloadIdentity. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + vault: + description: Vault is the vault's OCID of the specific vault where secret is located. + type: string + required: + - region + - vault + type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object + vault: + description: Vault configures this store to sync secrets using Hashi provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the Vault server. + properties: + appRole: + description: |- + AppRole authenticates with Vault using the App Role auth mechanism, + with the role and secret stored in a Kubernetes Secret resource. + properties: + path: + default: approle + description: |- + Path where the App Role authentication backend is mounted + in Vault, e.g: "approle" + type: string + roleId: + description: |- + RoleID configured in the App Role authentication backend when setting + up the authentication backend in Vault. + type: string + secretRef: + description: |- + Reference to a key in a Secret that contains the App Role secret used + to authenticate with Vault. + The `key` field must be specified and denotes which entry within the Secret + resource is used as the app role secret. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - path + - roleId + - secretRef + type: object + cert: + description: |- + Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate + Cert authentication method + properties: + clientCert: + description: |- + ClientCert is a certificate to authenticate using the Cert Vault + authentication method + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + secretRef: + description: |- + SecretRef to a key in a Secret resource containing client private key to + authenticate with Vault using the Cert authentication method + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + jwt: + description: |- + Jwt authenticates with Vault by passing role and JWT token using the + JWT/OIDC authentication method + properties: + kubernetesServiceAccountToken: + description: |- + Optional ServiceAccountToken specifies the Kubernetes service account for which to request + a token for with the `TokenRequest` API. + properties: + audiences: + description: |- + Optional audiences field that will be used to request a temporary Kubernetes service + account token for the service account referenced by `serviceAccountRef`. + Defaults to a single audience `vault` it not specified. + items: + type: string + type: array + expirationSeconds: + description: |- + Optional expiration time in seconds that will be used to request a temporary + Kubernetes service account token for the service account referenced by + `serviceAccountRef`. + Defaults to 10 minutes. + format: int64 + type: integer + serviceAccountRef: + description: Service account field containing the name of a kubernetes ServiceAccount. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + required: + - serviceAccountRef + type: object + path: + default: jwt + description: |- + Path where the JWT authentication backend is mounted + in Vault, e.g: "jwt" + type: string + role: + description: |- + Role is a JWT role to authenticate using the JWT/OIDC Vault + authentication method + type: string + secretRef: + description: |- + Optional SecretRef that refers to a key in a Secret resource containing JWT token to + authenticate with Vault using the JWT/OIDC authentication method. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - path + type: object + kubernetes: + description: |- + Kubernetes authenticates with Vault by passing the ServiceAccount + token stored in the named Secret resource to the Vault server. + properties: + mountPath: + default: kubernetes + description: |- + Path where the Kubernetes authentication backend is mounted in Vault, e.g: + "kubernetes" + type: string + role: + description: |- + A required field containing the Vault Role to assume. A Role binds a + Kubernetes ServiceAccount with a set of Vault policies. + type: string + secretRef: + description: |- + Optional secret field containing a Kubernetes ServiceAccount JWT used + for authenticating with Vault. If a name is specified without a key, + `token` is the default. If one is not specified, the one bound to + the controller will be used. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + serviceAccountRef: + description: |- + Optional service account field containing the name of a kubernetes ServiceAccount. + If the service account is specified, the service account secret token JWT will be used + for authenticating with Vault. If the service account selector is not supplied, + the secretRef will be used instead. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + required: + - mountPath + - role + type: object + ldap: + description: |- + Ldap authenticates with Vault by passing username/password pair using + the LDAP authentication method + properties: + path: + default: ldap + description: |- + Path where the LDAP authentication backend is mounted + in Vault, e.g: "ldap" + type: string + secretRef: + description: |- + SecretRef to a key in a Secret resource containing password for the LDAP + user used to authenticate with Vault using the LDAP authentication + method + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + username: + description: |- + Username is a LDAP user name used to authenticate using the LDAP Vault + authentication method + type: string + required: + - path + - username + type: object + tokenSecretRef: + description: TokenSecretRef authenticates with Vault by presenting a token. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + caBundle: + description: |- + PEM encoded CA bundle used to validate Vault server certificate. Only used + if the Server URL is using HTTPS protocol. This parameter is ignored for + plain HTTP protocol connection. If not set the system root certificates + are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate Vault server certificate. + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + forwardInconsistent: + description: |- + ForwardInconsistent tells Vault to forward read-after-write requests to the Vault + leader instead of simply retrying within a loop. This can increase performance if + the option is enabled serverside. + https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header + type: boolean + namespace: + description: |- + Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows + Vault environments to support Secure Multi-tenancy. e.g: "ns1". + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + type: string + path: + description: |- + Path is the mount path of the Vault KV backend endpoint, e.g: + "secret". The v2 KV secret engine version specific "/data" path suffix + for fetching secrets from Vault is optional and will be appended + if not present in specified path. + type: string + readYourWrites: + description: |- + ReadYourWrites ensures isolated read-after-write semantics by + providing discovered cluster replication states in each request. + More information about eventual consistency in Vault can be found here + https://www.vaultproject.io/docs/enterprise/consistency + type: boolean + server: + description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' + type: string + version: + default: v2 + description: |- + Version is the Vault KV secret engine version. This can be either "v1" or + "v2". Version defaults to "v2". + enum: + - v1 + - v2 + type: string + required: + - auth + - server + type: object + webhook: + description: Webhook configures this store to sync secrets using a generic templated webhook + properties: + body: + description: Body + type: string + caBundle: + description: |- + PEM encoded CA bundle used to validate webhook server certificate. Only used + if the Server URL is using HTTPS protocol. This parameter is ignored for + plain HTTP protocol connection. If not set the system root certificates + are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate webhook server certificate. + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + headers: + additionalProperties: + type: string + description: Headers + type: object + method: + description: Webhook Method + type: string + result: + description: Result formatting + properties: + jsonPath: + description: Json path of return value + type: string + type: object + secrets: + description: |- + Secrets to fill in templates + These secrets will be passed to the templating function as key value pairs under the given name + items: + properties: + name: + description: Name of this secret in templates + type: string + secretRef: + description: Secret ref to fill in credentials + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - name + - secretRef + type: object + type: array + timeout: + description: Timeout + type: string + url: + description: Webhook url to call + type: string + required: + - result + - url + type: object + yandexlockbox: + description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider + properties: + apiEndpoint: + description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') + type: string + auth: + description: Auth defines the information necessary to authenticate against Yandex Lockbox + properties: + authorizedKeySecretRef: + description: The authorized key used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + caProvider: + description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. + properties: + certSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - auth + type: object + type: object + retrySettings: + description: Used to configure http retries if failed + properties: + maxRetries: + format: int32 + type: integer + retryInterval: + type: string + type: object + required: + - provider + type: object + status: + description: SecretStoreStatus defines the observed state of the SecretStore. + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].reason + name: Status + type: string + - jsonPath: .status.capabilities + name: Capabilities + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: SecretStoreSpec defines the desired state of SecretStore. + properties: + conditions: + description: Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore + items: + description: |- + ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in + for a ClusterSecretStore instance. + properties: + namespaceRegexes: + description: Choose namespaces by using regex matching + items: + type: string + type: array + namespaceSelector: + description: Choose namespace using a labelSelector + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: Choose namespaces by name + items: + type: string + type: array + type: object + type: array + controller: + description: |- + Used to select the correct ESO controller (think: ingress.ingressClassName) + The ESO controller is instantiated with a specific controller name and filters ES based on this property + type: string + provider: + description: Used to configure the provider. Only one provider may be set + maxProperties: 1 + minProperties: 1 + properties: + akeyless: + description: Akeyless configures this store to sync secrets using Akeyless Vault provider + properties: + akeylessGWApiURL: + description: Akeyless GW API Url from which the secrets to be fetched from. + type: string + authSecretRef: + description: Auth configures how the operator authenticates with Akeyless. + properties: + kubernetesAuth: + description: |- + Kubernetes authenticates with Akeyless by passing the ServiceAccount + token stored in the named Secret resource. + properties: + accessID: + description: the Akeyless Kubernetes auth-method access-id + type: string + k8sConfName: + description: Kubernetes-auth configuration name in Akeyless-Gateway + type: string + secretRef: + description: |- + Optional secret field containing a Kubernetes ServiceAccount JWT used + for authenticating with Akeyless. If a name is specified without a key, + `token` is the default. If one is not specified, the one bound to + the controller will be used. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + serviceAccountRef: + description: |- + Optional service account field containing the name of a kubernetes ServiceAccount. + If the service account is specified, the service account secret token JWT will be used + for authenticating with Akeyless. If the service account selector is not supplied, + the secretRef will be used instead. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + required: + - accessID + - k8sConfName + type: object + secretRef: + description: |- + Reference to a Secret that contains the details + to authenticate with Akeyless. + properties: + accessID: + description: The SecretAccessID is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + accessType: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + accessTypeParam: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + type: object + caBundle: + description: |- + PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used + if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates + are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. + properties: + key: + description: The key where the CA certificate can be found in the Secret or ConfigMap. + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: |- + The namespace the Provider type is in. + Can only be defined when used in a ClusterSecretStore. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + required: + - akeylessGWApiURL + - authSecretRef + type: object + alibaba: + description: Alibaba configures this store to sync secrets using Alibaba Cloud provider + properties: + auth: + description: AlibabaAuth contains a secretRef for credentials. + properties: + rrsa: + description: Authenticate against Alibaba using RRSA. + properties: + oidcProviderArn: + type: string + oidcTokenFilePath: + type: string + roleArn: + type: string + sessionName: + type: string + required: + - oidcProviderArn + - oidcTokenFilePath + - roleArn + - sessionName + type: object + secretRef: + description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + accessKeySecretSecretRef: + description: The AccessKeySecret is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - accessKeyIDSecretRef + - accessKeySecretSecretRef + type: object + type: object + regionID: + description: Alibaba Region to be used for the provider + type: string + required: + - auth + - regionID + type: object + aws: + description: AWS configures this store to sync secrets using AWS Secret Manager provider + properties: + additionalRoles: + description: AdditionalRoles is a chained list of Role ARNs which the provider will sequentially assume before assuming the Role + items: + type: string + type: array + auth: + description: |- + Auth defines the information necessary to authenticate against AWS + if not set aws sdk will infer credentials from your environment + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + properties: + jwt: + description: Authenticate against AWS using service account tokens. + properties: + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + type: object + secretRef: + description: |- + AWSAuthSecretRef holds secret references for AWS credentials + both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + sessionTokenSecretRef: + description: |- + The SessionToken used for authentication + This must be defined if AccessKeyID and SecretAccessKey are temporary credentials + see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + type: object + externalID: + description: AWS External ID set on assumed IAM roles + type: string + region: + description: AWS Region to be used for the provider + type: string + role: + description: Role is a Role ARN which the provider will assume + type: string + secretsManager: + description: SecretsManager defines how the provider behaves when interacting with AWS SecretsManager + properties: + forceDeleteWithoutRecovery: + description: |- + Specifies whether to delete the secret without any recovery window. You + can't use both this parameter and RecoveryWindowInDays in the same call. + If you don't use either, then by default Secrets Manager uses a 30 day + recovery window. + see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-ForceDeleteWithoutRecovery + type: boolean + recoveryWindowInDays: + description: |- + The number of days from 7 to 30 that Secrets Manager waits before + permanently deleting the secret. You can't use both this parameter and + ForceDeleteWithoutRecovery in the same call. If you don't use either, + then by default Secrets Manager uses a 30 day recovery window. + see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-RecoveryWindowInDays + format: int64 + type: integer + type: object + service: + description: Service defines which service should be used to fetch the secrets + enum: + - SecretsManager + - ParameterStore + type: string + sessionTags: + description: AWS STS assume role session tags + items: + properties: + key: + type: string + value: + type: string + required: + - key + - value + type: object + type: array + transitiveTagKeys: + description: AWS STS assume role transitive session tags. Required when multiple rules are used with the provider + items: + type: string + type: array + required: + - region + - service + type: object + azurekv: + description: AzureKV configures this store to sync secrets using Azure Key Vault provider + properties: + authSecretRef: + description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. + properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + clientId: + description: The Azure clientId of the service principle or managed identity used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + clientSecret: + description: The Azure ClientSecret of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + tenantId: + description: The Azure tenantId of the managed identity used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + authType: + default: ServicePrincipal + description: |- + Auth type defines how to authenticate to the keyvault service. + Valid values are: + - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) + - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) + enum: + - ServicePrincipal + - ManagedIdentity + - WorkloadIdentity + type: string + environmentType: + default: PublicCloud + description: |- + EnvironmentType specifies the Azure cloud environment endpoints to use for + connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. + The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 + PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud + enum: + - PublicCloud + - USGovernmentCloud + - ChinaCloud + - GermanCloud + type: string + identityId: + description: If multiple Managed Identity is assigned to the pod, you can select the one to be used + type: string + serviceAccountRef: + description: |- + ServiceAccountRef specified the service account + that should be used when authenticating with WorkloadIdentity. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + tenantId: + description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. + type: string + vaultUrl: + description: Vault Url from which the secrets to be fetched from. + type: string + required: + - vaultUrl + type: object + bitwardensecretsmanager: + description: BitwardenSecretsManager configures this store to sync secrets using BitwardenSecretsManager provider + properties: + apiURL: + type: string + auth: + description: |- + Auth configures how secret-manager authenticates with a bitwarden machine account instance. + Make sure that the token being used has permissions on the given secret. + properties: + secretRef: + description: BitwardenSecretsManagerSecretRef contains the credential ref to the bitwarden instance. + properties: + credentials: + description: AccessToken used for the bitwarden instance. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - credentials + type: object + required: + - secretRef + type: object + bitwardenServerSDKURL: + type: string + caBundle: + description: |- + Base64 encoded certificate for the bitwarden server sdk. The sdk MUST run with HTTPS to make sure no MITM attack + can be performed. + type: string + identityURL: + type: string + organizationID: + description: OrganizationID determines which organization this secret store manages. + type: string + projectID: + description: ProjectID determines which project this secret store manages. + type: string + required: + - auth + - caBundle + - organizationID + - projectID + type: object + chef: + description: Chef configures this store to sync secrets with chef server + properties: + auth: + description: Auth defines the information necessary to authenticate against chef Server + properties: + secretRef: + description: ChefAuthSecretRef holds secret references for chef server login credentials. + properties: + privateKeySecretRef: + description: SecretKey is the Signing Key in PEM format, used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - privateKeySecretRef + type: object + required: + - secretRef + type: object + serverUrl: + description: ServerURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a "/" + type: string + username: + description: UserName should be the user ID on the chef server + type: string + required: + - auth + - serverUrl + - username + type: object + conjur: + description: Conjur configures this store to sync secrets using conjur provider + properties: + auth: + properties: + apikey: + properties: + account: + type: string + apiKeyRef: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + userRef: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - account + - apiKeyRef + - userRef + type: object + jwt: + properties: + account: + type: string + hostId: + description: |- + Optional HostID for JWT authentication. This may be used depending + on how the Conjur JWT authenticator policy is configured. + type: string + secretRef: + description: |- + Optional SecretRef that refers to a key in a Secret resource containing JWT token to + authenticate with Conjur using the JWT authentication method. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + serviceAccountRef: + description: |- + Optional ServiceAccountRef specifies the Kubernetes service account for which to request + a token for with the `TokenRequest` API. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + serviceID: + description: The conjur authn jwt webservice id + type: string + required: + - account + - serviceID + type: object + type: object + caBundle: + type: string + caProvider: + description: |- + Used to provide custom certificate authority (CA) certificates + for a secret store. The CAProvider points to a Secret or ConfigMap resource + that contains a PEM-encoded certificate. + properties: + key: + description: The key where the CA certificate can be found in the Secret or ConfigMap. + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: |- + The namespace the Provider type is in. + Can only be defined when used in a ClusterSecretStore. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + url: + type: string + required: + - auth + - url + type: object + delinea: + description: |- + Delinea DevOps Secrets Vault + https://docs.delinea.com/online-help/products/devops-secrets-vault/current + properties: + clientId: + description: ClientID is the non-secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + clientSecret: + description: ClientSecret is the secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + tenant: + description: Tenant is the chosen hostname / site name. + type: string + tld: + description: |- + TLD is based on the server location that was chosen during provisioning. + If unset, defaults to "com". + type: string + urlTemplate: + description: |- + URLTemplate + If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". + type: string + required: + - clientId + - clientSecret + - tenant + type: object + device42: + description: Device42 configures this store to sync secrets using the Device42 provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a Device42 instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + host: + description: URL configures the Device42 instance URL. + type: string + required: + - auth + - host + type: object + doppler: + description: Doppler configures this store to sync secrets using the Doppler provider + properties: + auth: + description: Auth configures how the Operator authenticates with the Doppler API + properties: + secretRef: + properties: + dopplerToken: + description: |- + The DopplerToken is used for authentication. + See https://docs.doppler.com/reference/api#authentication for auth token types. + The Key attribute defaults to dopplerToken if not specified. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - dopplerToken + type: object + required: + - secretRef + type: object + config: + description: Doppler config (required if not using a Service Token) + type: string + format: + description: Format enables the downloading of secrets as a file (string) + enum: + - json + - dotnet-json + - env + - yaml + - docker + type: string + nameTransformer: + description: Environment variable compatible name transforms that change secret names to a different format + enum: + - upper-camel + - camel + - lower-snake + - tf-var + - dotnet-env + - lower-kebab + type: string + project: + description: Doppler project (required if not using a Service Token) + type: string + required: + - auth + type: object + fake: + description: Fake configures a store with static key/value pairs + properties: + data: + items: + properties: + key: + type: string + value: + type: string + valueMap: + additionalProperties: + type: string + description: 'Deprecated: ValueMap is deprecated and is intended to be removed in the future, use the `value` field instead.' + type: object + version: + type: string + required: + - key + type: object + type: array + required: + - data + type: object + fortanix: + description: Fortanix configures this store to sync secrets using the Fortanix provider + properties: + apiKey: + description: APIKey is the API token to access SDKMS Applications. + properties: + secretRef: + description: SecretRef is a reference to a secret containing the SDKMS API Key. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + apiUrl: + description: APIURL is the URL of SDKMS API. Defaults to `sdkms.fortanix.com`. + type: string + type: object + gcpsm: + description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider + properties: + auth: + description: Auth defines the information necessary to authenticate against GCP + properties: + secretRef: + properties: + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + workloadIdentity: + properties: + clusterLocation: + type: string + clusterName: + type: string + clusterProjectID: + type: string + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + required: + - clusterLocation + - clusterName + - serviceAccountRef + type: object + type: object + location: + description: Location optionally defines a location for a secret + type: string + projectID: + description: ProjectID project where secret is located + type: string + type: object + gitlab: + description: GitLab configures this store to sync secrets using GitLab Variables provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a GitLab instance. + properties: + SecretRef: + properties: + accessToken: + description: AccessToken is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - SecretRef + type: object + environment: + description: Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments) + type: string + groupIDs: + description: GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables. + items: + type: string + type: array + inheritFromGroups: + description: InheritFromGroups specifies whether parent groups should be discovered and checked for secrets. + type: boolean + projectID: + description: ProjectID specifies a project where secrets are located. + type: string + url: + description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. + type: string + required: + - auth + type: object + ibm: + description: IBM configures this store to sync secrets using IBM Cloud provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the IBM secrets manager. + maxProperties: 1 + minProperties: 1 + properties: + containerAuth: + description: IBM Container-based auth with IAM Trusted Profile. + properties: + iamEndpoint: + type: string + profile: + description: the IBM Trusted Profile + type: string + tokenLocation: + description: Location the token is mounted on the pod + type: string + required: + - profile + type: object + secretRef: + properties: + secretApiKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + type: object + serviceUrl: + description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance + type: string + required: + - auth + type: object + infisical: + description: Infisical configures this store to sync secrets using the Infisical provider + properties: + auth: + description: Auth configures how the Operator authenticates with the Infisical API + properties: + universalAuthCredentials: + properties: + clientId: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + clientSecret: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - clientId + - clientSecret + type: object + type: object + hostAPI: + default: https://app.infisical.com/api + type: string + secretsScope: + properties: + environmentSlug: + type: string + projectSlug: + type: string + secretsPath: + default: / + type: string + required: + - environmentSlug + - projectSlug + type: object + required: + - auth + - secretsScope + type: object + keepersecurity: + description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider + properties: + authRef: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + folderID: + type: string + required: + - authRef + - folderID + type: object + kubernetes: + description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a Kubernetes instance. + maxProperties: 1 + minProperties: 1 + properties: + cert: + description: has both clientCert and clientKey as secretKeySelector + properties: + clientCert: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + clientKey: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + serviceAccount: + description: points to a service account that should be used for authentication + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + token: + description: use static token to authenticate with + properties: + bearerToken: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + type: object + authRef: + description: A reference to a secret that contains the auth information. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + remoteNamespace: + default: default + description: Remote namespace to fetch the secrets from + type: string + server: + description: configures the Kubernetes server Address. + properties: + caBundle: + description: CABundle is a base64-encoded CA certificate + format: byte + type: string + caProvider: + description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' + properties: + key: + description: The key where the CA certificate can be found in the Secret or ConfigMap. + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: |- + The namespace the Provider type is in. + Can only be defined when used in a ClusterSecretStore. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + url: + default: kubernetes.default + description: configures the Kubernetes server Address. + type: string + type: object + type: object + onboardbase: + description: Onboardbase configures this store to sync secrets using the Onboardbase provider + properties: + apiHost: + default: https://public.onboardbase.com/api/v1/ + description: APIHost use this to configure the host url for the API for selfhosted installation, default is https://public.onboardbase.com/api/v1/ + type: string + auth: + description: Auth configures how the Operator authenticates with the Onboardbase API + properties: + apiKeyRef: + description: |- + OnboardbaseAPIKey is the APIKey generated by an admin account. + It is used to recognize and authorize access to a project and environment within onboardbase + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + passcodeRef: + description: OnboardbasePasscode is the passcode attached to the API Key + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - apiKeyRef + - passcodeRef + type: object + environment: + default: development + description: Environment is the name of an environmnent within a project to pull the secrets from + type: string + project: + default: development + description: Project is an onboardbase project that the secrets should be pulled from + type: string + required: + - apiHost + - auth + - environment + - project + type: object + onepassword: + description: OnePassword configures this store to sync secrets using the 1Password Cloud provider + properties: + auth: + description: Auth defines the information necessary to authenticate against OnePassword Connect Server + properties: + secretRef: + description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. + properties: + connectTokenSecretRef: + description: The ConnectToken is used for authentication to a 1Password Connect Server. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - connectTokenSecretRef + type: object + required: + - secretRef + type: object + connectHost: + description: ConnectHost defines the OnePassword Connect Server to connect to + type: string + vaults: + additionalProperties: + type: integer + description: Vaults defines which OnePassword vaults to search in which order + type: object + required: + - auth + - connectHost + - vaults + type: object + oracle: + description: Oracle configures this store to sync secrets using Oracle Vault provider + properties: + auth: + description: |- + Auth configures how secret-manager authenticates with the Oracle Vault. + If empty, use the instance principal, otherwise the user credentials specified in Auth. + properties: + secretRef: + description: SecretRef to pass through sensitive information. + properties: + fingerprint: + description: Fingerprint is the fingerprint of the API private key. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + privatekey: + description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - fingerprint + - privatekey + type: object + tenancy: + description: Tenancy is the tenancy OCID where user is located. + type: string + user: + description: User is an access OCID specific to the account. + type: string + required: + - secretRef + - tenancy + - user + type: object + compartment: + description: |- + Compartment is the vault compartment OCID. + Required for PushSecret + type: string + encryptionKey: + description: |- + EncryptionKey is the OCID of the encryption key within the vault. + Required for PushSecret + type: string + principalType: + description: |- + The type of principal to use for authentication. If left blank, the Auth struct will + determine the principal type. This optional field must be specified if using + workload identity. + enum: + - "" + - UserPrincipal + - InstancePrincipal + - Workload + type: string + region: + description: Region is the region where vault is located. + type: string + serviceAccountRef: + description: |- + ServiceAccountRef specified the service account + that should be used when authenticating with WorkloadIdentity. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + vault: + description: Vault is the vault's OCID of the specific vault where secret is located. + type: string + required: + - region + - vault + type: object + passbolt: + properties: + auth: + description: Auth defines the information necessary to authenticate against Passbolt Server + properties: + passwordSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + privateKeySecretRef: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - passwordSecretRef + - privateKeySecretRef + type: object + host: + description: Host defines the Passbolt Server to connect to + type: string + required: + - auth + - host + type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object + pulumi: + description: Pulumi configures this store to sync secrets using the Pulumi provider + properties: + accessToken: + description: AccessToken is the access tokens to sign in to the Pulumi Cloud Console. + properties: + secretRef: + description: SecretRef is a reference to a secret containing the Pulumi API token. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + apiUrl: + default: https://api.pulumi.com + description: APIURL is the URL of the Pulumi API. + type: string + environment: + description: |- + Environment are YAML documents composed of static key-value pairs, programmatic expressions, + dynamically retrieved values from supported providers including all major clouds, + and other Pulumi ESC environments. + To create a new environment, visit https://www.pulumi.com/docs/esc/environments/ for more information. + type: string + organization: + description: |- + Organization are a space to collaborate on shared projects and stacks. + To create a new organization, visit https://app.pulumi.com/ and click "New Organization". + type: string + required: + - accessToken + - environment + - organization + type: object + scaleway: + description: Scaleway + properties: + accessKey: + description: AccessKey is the non-secret part of the api key. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + apiUrl: + description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com + type: string + projectId: + description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' + type: string + region: + description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' + type: string + secretKey: + description: SecretKey is the non-secret part of the api key. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + required: + - accessKey + - projectId + - region + - secretKey + type: object + senhasegura: + description: Senhasegura configures this store to sync secrets using senhasegura provider + properties: + auth: + description: Auth defines parameters to authenticate in senhasegura + properties: + clientId: + type: string + clientSecretSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - clientId + - clientSecretSecretRef + type: object + ignoreSslCertificate: + default: false + description: IgnoreSslCertificate defines if SSL certificate must be ignored + type: boolean + module: + description: Module defines which senhasegura module should be used to get secrets + type: string + url: + description: URL of senhasegura + type: string + required: + - auth + - module + - url + type: object + vault: + description: Vault configures this store to sync secrets using Hashi provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the Vault server. + properties: + appRole: + description: |- + AppRole authenticates with Vault using the App Role auth mechanism, + with the role and secret stored in a Kubernetes Secret resource. + properties: + path: + default: approle + description: |- + Path where the App Role authentication backend is mounted + in Vault, e.g: "approle" + type: string + roleId: + description: |- + RoleID configured in the App Role authentication backend when setting + up the authentication backend in Vault. + type: string + roleRef: + description: |- + Reference to a key in a Secret that contains the App Role ID used + to authenticate with Vault. + The `key` field must be specified and denotes which entry within the Secret + resource is used as the app role id. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + secretRef: + description: |- + Reference to a key in a Secret that contains the App Role secret used + to authenticate with Vault. + The `key` field must be specified and denotes which entry within the Secret + resource is used as the app role secret. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - path + - secretRef + type: object + cert: + description: |- + Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate + Cert authentication method + properties: + clientCert: + description: |- + ClientCert is a certificate to authenticate using the Cert Vault + authentication method + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + secretRef: + description: |- + SecretRef to a key in a Secret resource containing client private key to + authenticate with Vault using the Cert authentication method + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + iam: + description: |- + Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials + AWS IAM authentication method + properties: + externalID: + description: AWS External ID set on assumed IAM roles + type: string + jwt: + description: Specify a service account with IRSA enabled + properties: + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + type: object + path: + description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' + type: string + region: + description: AWS region + type: string + role: + description: This is the AWS role to be assumed before talking to vault + type: string + secretRef: + description: Specify credentials in a Secret object + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + sessionTokenSecretRef: + description: |- + The SessionToken used for authentication + This must be defined if AccessKeyID and SecretAccessKey are temporary credentials + see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + vaultAwsIamServerID: + description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' + type: string + vaultRole: + description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine + type: string + required: + - vaultRole + type: object + jwt: + description: |- + Jwt authenticates with Vault by passing role and JWT token using the + JWT/OIDC authentication method + properties: + kubernetesServiceAccountToken: + description: |- + Optional ServiceAccountToken specifies the Kubernetes service account for which to request + a token for with the `TokenRequest` API. + properties: + audiences: + description: |- + Optional audiences field that will be used to request a temporary Kubernetes service + account token for the service account referenced by `serviceAccountRef`. + Defaults to a single audience `vault` it not specified. + Deprecated: use serviceAccountRef.Audiences instead + items: + type: string + type: array + expirationSeconds: + description: |- + Optional expiration time in seconds that will be used to request a temporary + Kubernetes service account token for the service account referenced by + `serviceAccountRef`. + Deprecated: this will be removed in the future. + Defaults to 10 minutes. + format: int64 + type: integer + serviceAccountRef: + description: Service account field containing the name of a kubernetes ServiceAccount. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + required: + - serviceAccountRef + type: object + path: + default: jwt + description: |- + Path where the JWT authentication backend is mounted + in Vault, e.g: "jwt" + type: string + role: + description: |- + Role is a JWT role to authenticate using the JWT/OIDC Vault + authentication method + type: string + secretRef: + description: |- + Optional SecretRef that refers to a key in a Secret resource containing JWT token to + authenticate with Vault using the JWT/OIDC authentication method. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - path + type: object + kubernetes: + description: |- + Kubernetes authenticates with Vault by passing the ServiceAccount + token stored in the named Secret resource to the Vault server. + properties: + mountPath: + default: kubernetes + description: |- + Path where the Kubernetes authentication backend is mounted in Vault, e.g: + "kubernetes" + type: string + role: + description: |- + A required field containing the Vault Role to assume. A Role binds a + Kubernetes ServiceAccount with a set of Vault policies. + type: string + secretRef: + description: |- + Optional secret field containing a Kubernetes ServiceAccount JWT used + for authenticating with Vault. If a name is specified without a key, + `token` is the default. If one is not specified, the one bound to + the controller will be used. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + serviceAccountRef: + description: |- + Optional service account field containing the name of a kubernetes ServiceAccount. + If the service account is specified, the service account secret token JWT will be used + for authenticating with Vault. If the service account selector is not supplied, + the secretRef will be used instead. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + required: + - mountPath + - role + type: object + ldap: + description: |- + Ldap authenticates with Vault by passing username/password pair using + the LDAP authentication method + properties: + path: + default: ldap + description: |- + Path where the LDAP authentication backend is mounted + in Vault, e.g: "ldap" + type: string + secretRef: + description: |- + SecretRef to a key in a Secret resource containing password for the LDAP + user used to authenticate with Vault using the LDAP authentication + method + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + username: + description: |- + Username is a LDAP user name used to authenticate using the LDAP Vault + authentication method + type: string + required: + - path + - username + type: object + namespace: + description: |- + Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. + Namespaces is a set of features within Vault Enterprise that allows + Vault environments to support Secure Multi-tenancy. e.g: "ns1". + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + This will default to Vault.Namespace field if set, or empty otherwise + type: string + tokenSecretRef: + description: TokenSecretRef authenticates with Vault by presenting a token. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: |- + Path where the UserPassword authentication backend is mounted + in Vault, e.g: "user" + type: string + secretRef: + description: |- + SecretRef to a key in a Secret resource containing password for the + user used to authenticate with Vault using the UserPass authentication + method + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + username: + description: |- + Username is a user name used to authenticate using the UserPass Vault + authentication method + type: string + required: + - path + - username + type: object + type: object + caBundle: + description: |- + PEM encoded CA bundle used to validate Vault server certificate. Only used + if the Server URL is using HTTPS protocol. This parameter is ignored for + plain HTTP protocol connection. If not set the system root certificates + are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate Vault server certificate. + properties: + key: + description: The key where the CA certificate can be found in the Secret or ConfigMap. + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: |- + The namespace the Provider type is in. + Can only be defined when used in a ClusterSecretStore. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + forwardInconsistent: + description: |- + ForwardInconsistent tells Vault to forward read-after-write requests to the Vault + leader instead of simply retrying within a loop. This can increase performance if + the option is enabled serverside. + https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header + type: boolean + namespace: + description: |- + Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows + Vault environments to support Secure Multi-tenancy. e.g: "ns1". + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + type: string + path: + description: |- + Path is the mount path of the Vault KV backend endpoint, e.g: + "secret". The v2 KV secret engine version specific "/data" path suffix + for fetching secrets from Vault is optional and will be appended + if not present in specified path. + type: string + readYourWrites: + description: |- + ReadYourWrites ensures isolated read-after-write semantics by + providing discovered cluster replication states in each request. + More information about eventual consistency in Vault can be found here + https://www.vaultproject.io/docs/enterprise/consistency + type: boolean + server: + description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' + type: string + tls: + description: |- + The configuration used for client side related TLS communication, when the Vault server + requires mutual authentication. Only used if the Server URL is using HTTPS protocol. + This parameter is ignored for plain HTTP protocol connection. + It's worth noting this configuration is different from the "TLS certificates auth method", + which is available under the `auth.cert` section. + properties: + certSecretRef: + description: |- + CertSecretRef is a certificate added to the transport layer + when communicating with the Vault server. + If no key for the Secret is specified, external-secret will default to 'tls.crt'. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + keySecretRef: + description: |- + KeySecretRef to a key in a Secret resource containing client private key + added to the transport layer when communicating with the Vault server. + If no key for the Secret is specified, external-secret will default to 'tls.key'. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + version: + default: v2 + description: |- + Version is the Vault KV secret engine version. This can be either "v1" or + "v2". Version defaults to "v2". + enum: + - v1 + - v2 + type: string + required: + - auth + - server + type: object + webhook: + description: Webhook configures this store to sync secrets using a generic templated webhook + properties: + body: + description: Body + type: string + caBundle: + description: |- + PEM encoded CA bundle used to validate webhook server certificate. Only used + if the Server URL is using HTTPS protocol. This parameter is ignored for + plain HTTP protocol connection. If not set the system root certificates + are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate webhook server certificate. + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + headers: + additionalProperties: + type: string + description: Headers + type: object + method: + description: Webhook Method + type: string + result: + description: Result formatting + properties: + jsonPath: + description: Json path of return value + type: string + type: object + secrets: + description: |- + Secrets to fill in templates + These secrets will be passed to the templating function as key value pairs under the given name + items: + properties: + name: + description: Name of this secret in templates + type: string + secretRef: + description: Secret ref to fill in credentials + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - name + - secretRef + type: object + type: array + timeout: + description: Timeout + type: string + url: + description: Webhook url to call + type: string + required: + - result + - url + type: object + yandexcertificatemanager: + description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider + properties: + apiEndpoint: + description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') + type: string + auth: + description: Auth defines the information necessary to authenticate against Yandex Certificate Manager + properties: + authorizedKeySecretRef: + description: The authorized key used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + caProvider: + description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. + properties: + certSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - auth + type: object + yandexlockbox: + description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider + properties: + apiEndpoint: + description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') + type: string + auth: + description: Auth defines the information necessary to authenticate against Yandex Lockbox + properties: + authorizedKeySecretRef: + description: The authorized key used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + caProvider: + description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. + properties: + certSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - auth + type: object + type: object + refreshInterval: + description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. + type: integer + retrySettings: + description: Used to configure http retries if failed + properties: + maxRetries: + format: int32 + type: integer + retryInterval: + type: string + type: object + required: + - provider + type: object + status: + description: SecretStoreStatus defines the observed state of the SecretStore. + properties: + capabilities: + description: SecretStoreCapabilities defines the possible operations a SecretStore can do. + type: string + conditions: + items: + properties: + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/backing-services/external-secrets/templates/crds/ecrauthorizationtoken.yaml b/backing-services/external-secrets/templates/crds/ecrauthorizationtoken.yaml new file mode 100644 index 0000000..0a7a6ef --- /dev/null +++ b/backing-services/external-secrets/templates/crds/ecrauthorizationtoken.yaml @@ -0,0 +1,177 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller + name: ecrauthorizationtokens.generators.external-secrets.io +spec: + group: generators.external-secrets.io + names: + categories: + - ecrauthorizationtoken + kind: ECRAuthorizationToken + listKind: ECRAuthorizationTokenList + plural: ecrauthorizationtokens + shortNames: + - ecrauthorizationtoken + singular: ecrauthorizationtoken + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + ECRAuthorizationTokenSpec uses the GetAuthorizationToken API to retrieve an + authorization token. + The authorization token is valid for 12 hours. + The authorizationToken returned is a base64 encoded string that can be decoded + and used in a docker login command to authenticate to a registry. + For more information, see Registry authentication (https://docs.aws.amazon.com/AmazonECR/latest/userguide/Registries.html#registry_auth) in the Amazon Elastic Container Registry User Guide. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + properties: + auth: + description: Auth defines how to authenticate with AWS + properties: + jwt: + description: Authenticate against AWS using service account tokens. + properties: + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + type: object + secretRef: + description: |- + AWSAuthSecretRef holds secret references for AWS credentials + both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + sessionTokenSecretRef: + description: |- + The SessionToken used for authentication + This must be defined if AccessKeyID and SecretAccessKey are temporary credentials + see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + type: object + region: + description: Region specifies the region to operate in. + type: string + role: + description: |- + You can assume a role before making calls to the + desired AWS service. + type: string + required: + - region + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/backing-services/external-secrets/templates/crds/externalsecret.yaml b/backing-services/external-secrets/templates/crds/externalsecret.yaml new file mode 100644 index 0000000..3420325 --- /dev/null +++ b/backing-services/external-secrets/templates/crds/externalsecret.yaml @@ -0,0 +1,825 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller + name: externalsecrets.external-secrets.io +spec: + group: external-secrets.io + names: + categories: + - externalsecrets + kind: ExternalSecret + listKind: ExternalSecretList + plural: externalsecrets + shortNames: + - es + singular: externalsecret + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.secretStoreRef.name + name: Store + type: string + - jsonPath: .spec.refreshInterval + name: Refresh Interval + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].reason + name: Status + type: string + deprecated: true + name: v1alpha1 + schema: + openAPIV3Schema: + description: ExternalSecret is the Schema for the external-secrets API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: ExternalSecretSpec defines the desired state of ExternalSecret. + properties: + data: + description: Data defines the connection between the Kubernetes Secret keys and the Provider data + items: + description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. + properties: + remoteRef: + description: ExternalSecretDataRemoteRef defines Provider data location. + properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + enum: + - Default + - Unicode + type: string + key: + description: Key is the key used in the Provider, mandatory + type: string + property: + description: Used to select a specific property of the Provider value (if a map), if supported + type: string + version: + description: Used to select a specific version of the Provider value, if supported + type: string + required: + - key + type: object + secretKey: + type: string + required: + - remoteRef + - secretKey + type: object + type: array + dataFrom: + description: |- + DataFrom is used to fetch all properties from a specific Provider data + If multiple entries are specified, the Secret keys are merged in the specified order + items: + description: ExternalSecretDataRemoteRef defines Provider data location. + properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + enum: + - Default + - Unicode + type: string + key: + description: Key is the key used in the Provider, mandatory + type: string + property: + description: Used to select a specific property of the Provider value (if a map), if supported + type: string + version: + description: Used to select a specific version of the Provider value, if supported + type: string + required: + - key + type: object + type: array + refreshInterval: + default: 1h + description: |- + RefreshInterval is the amount of time before the values are read again from the SecretStore provider + Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" + May be set to zero to fetch and create it once. Defaults to 1h. + type: string + secretStoreRef: + description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. + properties: + kind: + description: |- + Kind of the SecretStore resource (SecretStore or ClusterSecretStore) + Defaults to `SecretStore` + type: string + name: + description: Name of the SecretStore resource + type: string + required: + - name + type: object + target: + description: |- + ExternalSecretTarget defines the Kubernetes Secret to be created + There can be only one target per ExternalSecret. + properties: + creationPolicy: + default: Owner + description: |- + CreationPolicy defines rules on how to create the resulting Secret + Defaults to 'Owner' + enum: + - Owner + - Merge + - None + type: string + immutable: + description: Immutable defines if the final secret will be immutable + type: boolean + name: + description: |- + Name defines the name of the Secret resource to be managed + This field is immutable + Defaults to the .metadata.name of the ExternalSecret resource + type: string + template: + description: Template defines a blueprint for the created Secret resource. + properties: + data: + additionalProperties: + type: string + type: object + engineVersion: + default: v1 + description: |- + EngineVersion specifies the template engine version + that should be used to compile/execute the + template specified in .data and .templateFrom[]. + enum: + - v1 + - v2 + type: string + metadata: + description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + templateFrom: + items: + maxProperties: 1 + minProperties: 1 + properties: + configMap: + properties: + items: + items: + properties: + key: + type: string + required: + - key + type: object + type: array + name: + type: string + required: + - items + - name + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + required: + - key + type: object + type: array + name: + type: string + required: + - items + - name + type: object + type: object + type: array + type: + type: string + type: object + type: object + required: + - secretStoreRef + - target + type: object + status: + properties: + binding: + description: Binding represents a servicebinding.io Provisioned Service reference to the secret + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + type: object + x-kubernetes-map-type: atomic + conditions: + items: + properties: + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + refreshTime: + description: |- + refreshTime is the time and date the external secret was fetched and + the target secret updated + format: date-time + nullable: true + type: string + syncedResourceVersion: + description: SyncedResourceVersion keeps track of the last synced version + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.secretStoreRef.name + name: Store + type: string + - jsonPath: .spec.refreshInterval + name: Refresh Interval + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].reason + name: Status + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: ExternalSecret is the Schema for the external-secrets API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: ExternalSecretSpec defines the desired state of ExternalSecret. + properties: + data: + description: Data defines the connection between the Kubernetes Secret keys and the Provider data + items: + description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. + properties: + remoteRef: + description: |- + RemoteRef points to the remote secret and defines + which secret (version/property/..) to fetch. + properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + enum: + - Default + - Unicode + type: string + decodingStrategy: + default: None + description: Used to define a decoding Strategy + enum: + - Auto + - Base64 + - Base64URL + - None + type: string + key: + description: Key is the key used in the Provider, mandatory + type: string + metadataPolicy: + default: None + description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None + enum: + - None + - Fetch + type: string + property: + description: Used to select a specific property of the Provider value (if a map), if supported + type: string + version: + description: Used to select a specific version of the Provider value, if supported + type: string + required: + - key + type: object + secretKey: + description: |- + SecretKey defines the key in which the controller stores + the value. This is the key in the Kind=Secret + type: string + sourceRef: + description: |- + SourceRef allows you to override the source + from which the value will pulled from. + maxProperties: 1 + properties: + generatorRef: + description: |- + GeneratorRef points to a generator custom resource. + + + Deprecated: The generatorRef is not implemented in .data[]. + this will be removed with v1. + properties: + apiVersion: + default: generators.external-secrets.io/v1alpha1 + description: Specify the apiVersion of the generator resource + type: string + kind: + description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. + type: string + name: + description: Specify the name of the generator resource + type: string + required: + - kind + - name + type: object + storeRef: + description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. + properties: + kind: + description: |- + Kind of the SecretStore resource (SecretStore or ClusterSecretStore) + Defaults to `SecretStore` + type: string + name: + description: Name of the SecretStore resource + type: string + required: + - name + type: object + type: object + required: + - remoteRef + - secretKey + type: object + type: array + dataFrom: + description: |- + DataFrom is used to fetch all properties from a specific Provider data + If multiple entries are specified, the Secret keys are merged in the specified order + items: + properties: + extract: + description: |- + Used to extract multiple key/value pairs from one secret + Note: Extract does not support sourceRef.Generator or sourceRef.GeneratorRef. + properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + enum: + - Default + - Unicode + type: string + decodingStrategy: + default: None + description: Used to define a decoding Strategy + enum: + - Auto + - Base64 + - Base64URL + - None + type: string + key: + description: Key is the key used in the Provider, mandatory + type: string + metadataPolicy: + default: None + description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None + enum: + - None + - Fetch + type: string + property: + description: Used to select a specific property of the Provider value (if a map), if supported + type: string + version: + description: Used to select a specific version of the Provider value, if supported + type: string + required: + - key + type: object + find: + description: |- + Used to find secrets based on tags or regular expressions + Note: Find does not support sourceRef.Generator or sourceRef.GeneratorRef. + properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + enum: + - Default + - Unicode + type: string + decodingStrategy: + default: None + description: Used to define a decoding Strategy + enum: + - Auto + - Base64 + - Base64URL + - None + type: string + name: + description: Finds secrets based on the name. + properties: + regexp: + description: Finds secrets base + type: string + type: object + path: + description: A root path to start the find operations. + type: string + tags: + additionalProperties: + type: string + description: Find secrets based on tags. + type: object + type: object + rewrite: + description: |- + Used to rewrite secret Keys after getting them from the secret Provider + Multiple Rewrite operations can be provided. They are applied in a layered order (first to last) + items: + properties: + regexp: + description: |- + Used to rewrite with regular expressions. + The resulting key will be the output of a regexp.ReplaceAll operation. + properties: + source: + description: Used to define the regular expression of a re.Compiler. + type: string + target: + description: Used to define the target pattern of a ReplaceAll operation. + type: string + required: + - source + - target + type: object + transform: + description: |- + Used to apply string transformation on the secrets. + The resulting key will be the output of the template applied by the operation. + properties: + template: + description: |- + Used to define the template to apply on the secret name. + `.value ` will specify the secret name in the template. + type: string + required: + - template + type: object + type: object + type: array + sourceRef: + description: |- + SourceRef points to a store or generator + which contains secret values ready to use. + Use this in combination with Extract or Find pull values out of + a specific SecretStore. + When sourceRef points to a generator Extract or Find is not supported. + The generator returns a static map of values + maxProperties: 1 + properties: + generatorRef: + description: GeneratorRef points to a generator custom resource. + properties: + apiVersion: + default: generators.external-secrets.io/v1alpha1 + description: Specify the apiVersion of the generator resource + type: string + kind: + description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. + type: string + name: + description: Specify the name of the generator resource + type: string + required: + - kind + - name + type: object + storeRef: + description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. + properties: + kind: + description: |- + Kind of the SecretStore resource (SecretStore or ClusterSecretStore) + Defaults to `SecretStore` + type: string + name: + description: Name of the SecretStore resource + type: string + required: + - name + type: object + type: object + type: object + type: array + refreshInterval: + default: 1h + description: |- + RefreshInterval is the amount of time before the values are read again from the SecretStore provider + Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" + May be set to zero to fetch and create it once. Defaults to 1h. + type: string + secretStoreRef: + description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. + properties: + kind: + description: |- + Kind of the SecretStore resource (SecretStore or ClusterSecretStore) + Defaults to `SecretStore` + type: string + name: + description: Name of the SecretStore resource + type: string + required: + - name + type: object + target: + default: + creationPolicy: Owner + deletionPolicy: Retain + description: |- + ExternalSecretTarget defines the Kubernetes Secret to be created + There can be only one target per ExternalSecret. + properties: + creationPolicy: + default: Owner + description: |- + CreationPolicy defines rules on how to create the resulting Secret + Defaults to 'Owner' + enum: + - Owner + - Orphan + - Merge + - None + type: string + deletionPolicy: + default: Retain + description: |- + DeletionPolicy defines rules on how to delete the resulting Secret + Defaults to 'Retain' + enum: + - Delete + - Merge + - Retain + type: string + immutable: + description: Immutable defines if the final secret will be immutable + type: boolean + name: + description: |- + Name defines the name of the Secret resource to be managed + This field is immutable + Defaults to the .metadata.name of the ExternalSecret resource + type: string + template: + description: Template defines a blueprint for the created Secret resource. + properties: + data: + additionalProperties: + type: string + type: object + engineVersion: + default: v2 + description: |- + EngineVersion specifies the template engine version + that should be used to compile/execute the + template specified in .data and .templateFrom[]. + enum: + - v1 + - v2 + type: string + mergePolicy: + default: Replace + enum: + - Replace + - Merge + type: string + metadata: + description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + templateFrom: + items: + properties: + configMap: + properties: + items: + items: + properties: + key: + type: string + templateAs: + default: Values + enum: + - Values + - KeysAndValues + type: string + required: + - key + type: object + type: array + name: + type: string + required: + - items + - name + type: object + literal: + type: string + secret: + properties: + items: + items: + properties: + key: + type: string + templateAs: + default: Values + enum: + - Values + - KeysAndValues + type: string + required: + - key + type: object + type: array + name: + type: string + required: + - items + - name + type: object + target: + default: Data + enum: + - Data + - Annotations + - Labels + type: string + type: object + type: array + type: + type: string + type: object + type: object + type: object + status: + properties: + binding: + description: Binding represents a servicebinding.io Provisioned Service reference to the secret + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + type: object + x-kubernetes-map-type: atomic + conditions: + items: + properties: + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + refreshTime: + description: |- + refreshTime is the time and date the external secret was fetched and + the target secret updated + format: date-time + nullable: true + type: string + syncedResourceVersion: + description: SyncedResourceVersion keeps track of the last synced version + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/backing-services/external-secrets/templates/crds/fake.yaml b/backing-services/external-secrets/templates/crds/fake.yaml new file mode 100644 index 0000000..c18f0e4 --- /dev/null +++ b/backing-services/external-secrets/templates/crds/fake.yaml @@ -0,0 +1,86 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller + name: fakes.generators.external-secrets.io +spec: + group: generators.external-secrets.io + names: + categories: + - fake + kind: Fake + listKind: FakeList + plural: fakes + shortNames: + - fake + singular: fake + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + Fake generator is used for testing. It lets you define + a static set of credentials that is always returned. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: FakeSpec contains the static data. + properties: + controller: + description: |- + Used to select the correct ESO controller (think: ingress.ingressClassName) + The ESO controller is instantiated with a specific controller name and filters VDS based on this property + type: string + data: + additionalProperties: + type: string + description: |- + Data defines the static data returned + by this generator. + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/backing-services/external-secrets/templates/crds/gcraccesstoken.yaml b/backing-services/external-secrets/templates/crds/gcraccesstoken.yaml new file mode 100644 index 0000000..c5e743c --- /dev/null +++ b/backing-services/external-secrets/templates/crds/gcraccesstoken.yaml @@ -0,0 +1,138 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller + name: gcraccesstokens.generators.external-secrets.io +spec: + group: generators.external-secrets.io + names: + categories: + - gcraccesstoken + kind: GCRAccessToken + listKind: GCRAccessTokenList + plural: gcraccesstokens + shortNames: + - gcraccesstoken + singular: gcraccesstoken + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + GCRAccessToken generates an GCP access token + that can be used to authenticate with GCR. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + properties: + auth: + description: Auth defines the means for authenticating with GCP + properties: + secretRef: + properties: + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + workloadIdentity: + properties: + clusterLocation: + type: string + clusterName: + type: string + clusterProjectID: + type: string + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + required: + - clusterLocation + - clusterName + - serviceAccountRef + type: object + type: object + projectID: + description: ProjectID defines which project to use to authenticate with + type: string + required: + - auth + - projectID + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/backing-services/external-secrets/templates/crds/githubaccesstoken.yaml b/backing-services/external-secrets/templates/crds/githubaccesstoken.yaml new file mode 100644 index 0000000..d125b35 --- /dev/null +++ b/backing-services/external-secrets/templates/crds/githubaccesstoken.yaml @@ -0,0 +1,112 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller + name: githubaccesstokens.generators.external-secrets.io +spec: + group: generators.external-secrets.io + names: + categories: + - githubaccesstoken + kind: GithubAccessToken + listKind: GithubAccessTokenList + plural: githubaccesstokens + shortNames: + - githubaccesstoken + singular: githubaccesstoken + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: GithubAccessToken generates ghs_ accessToken + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + properties: + appID: + type: string + auth: + description: Auth configures how ESO authenticates with a Github instance. + properties: + privateKey: + properties: + secretRef: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - secretRef + type: object + required: + - privateKey + type: object + installID: + type: string + url: + description: URL configures the Github instance URL. Defaults to https://github.com/. + type: string + required: + - appID + - auth + - installID + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/backing-services/external-secrets/templates/crds/password.yaml b/backing-services/external-secrets/templates/crds/password.yaml new file mode 100644 index 0000000..ddf71f9 --- /dev/null +++ b/backing-services/external-secrets/templates/crds/password.yaml @@ -0,0 +1,108 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller + name: passwords.generators.external-secrets.io +spec: + group: generators.external-secrets.io + names: + categories: + - password + kind: Password + listKind: PasswordList + plural: passwords + shortNames: + - password + singular: password + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + Password generates a random password based on the + configuration parameters in spec. + You can specify the length, characterset and other attributes. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: PasswordSpec controls the behavior of the password generator. + properties: + allowRepeat: + default: false + description: set AllowRepeat to true to allow repeating characters. + type: boolean + digits: + description: |- + Digits specifies the number of digits in the generated + password. If omitted it defaults to 25% of the length of the password + type: integer + length: + default: 24 + description: |- + Length of the password to be generated. + Defaults to 24 + type: integer + noUpper: + default: false + description: Set NoUpper to disable uppercase characters + type: boolean + symbolCharacters: + description: |- + SymbolCharacters specifies the special characters that should be used + in the generated password. + type: string + symbols: + description: |- + Symbols specifies the number of symbol characters in the generated + password. If omitted it defaults to 25% of the length of the password + type: integer + required: + - allowRepeat + - length + - noUpper + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/backing-services/external-secrets/templates/crds/pushsecret.yaml b/backing-services/external-secrets/templates/crds/pushsecret.yaml new file mode 100644 index 0000000..04080be --- /dev/null +++ b/backing-services/external-secrets/templates/crds/pushsecret.yaml @@ -0,0 +1,386 @@ +{{- if and (.Values.installCRDs) (.Values.crds.createPushSecret) }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.15.0 + name: pushsecrets.external-secrets.io +spec: + group: external-secrets.io + names: + categories: + - pushsecrets + kind: PushSecret + listKind: PushSecretList + plural: pushsecrets + singular: pushsecret + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].reason + name: Status + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: PushSecretSpec configures the behavior of the PushSecret. + properties: + data: + description: Secret Data that should be pushed to providers + items: + properties: + conversionStrategy: + default: None + description: Used to define a conversion Strategy for the secret keys + enum: + - None + - ReverseUnicode + type: string + match: + description: Match a given Secret Key to be pushed to the provider. + properties: + remoteRef: + description: Remote Refs to push to providers. + properties: + property: + description: Name of the property in the resulting secret + type: string + remoteKey: + description: Name of the resulting provider secret. + type: string + required: + - remoteKey + type: object + secretKey: + description: Secret Key to be pushed + type: string + required: + - remoteRef + type: object + metadata: + description: |- + Metadata is metadata attached to the secret. + The structure of metadata is provider specific, please look it up in the provider documentation. + x-kubernetes-preserve-unknown-fields: true + required: + - match + type: object + type: array + deletionPolicy: + default: None + description: 'Deletion Policy to handle Secrets in the provider. Possible Values: "Delete/None". Defaults to "None".' + enum: + - Delete + - None + type: string + refreshInterval: + description: The Interval to which External Secrets will try to push a secret definition + type: string + secretStoreRefs: + items: + properties: + kind: + default: SecretStore + description: |- + Kind of the SecretStore resource (SecretStore or ClusterSecretStore) + Defaults to `SecretStore` + type: string + labelSelector: + description: Optionally, sync to secret stores with label selector + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: Optionally, sync to the SecretStore of the given name + type: string + type: object + type: array + selector: + description: The Secret Selector (k8s source) for the Push Secret + properties: + secret: + description: Select a Secret to Push. + properties: + name: + description: Name of the Secret. The Secret must exist in the same namespace as the PushSecret manifest. + type: string + required: + - name + type: object + required: + - secret + type: object + template: + description: Template defines a blueprint for the created Secret resource. + properties: + data: + additionalProperties: + type: string + type: object + engineVersion: + default: v2 + description: |- + EngineVersion specifies the template engine version + that should be used to compile/execute the + template specified in .data and .templateFrom[]. + enum: + - v1 + - v2 + type: string + mergePolicy: + default: Replace + enum: + - Replace + - Merge + type: string + metadata: + description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + templateFrom: + items: + properties: + configMap: + properties: + items: + items: + properties: + key: + type: string + templateAs: + default: Values + enum: + - Values + - KeysAndValues + type: string + required: + - key + type: object + type: array + name: + type: string + required: + - items + - name + type: object + literal: + type: string + secret: + properties: + items: + items: + properties: + key: + type: string + templateAs: + default: Values + enum: + - Values + - KeysAndValues + type: string + required: + - key + type: object + type: array + name: + type: string + required: + - items + - name + type: object + target: + default: Data + enum: + - Data + - Annotations + - Labels + type: string + type: object + type: array + type: + type: string + type: object + updatePolicy: + default: Replace + description: 'UpdatePolicy to handle Secrets in the provider. Possible Values: "Replace/IfNotExists". Defaults to "Replace".' + enum: + - Replace + - IfNotExists + type: string + required: + - secretStoreRefs + - selector + type: object + status: + description: PushSecretStatus indicates the history of the status of PushSecret. + properties: + conditions: + items: + description: PushSecretStatusCondition indicates the status of the PushSecret. + properties: + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + description: PushSecretConditionType indicates the condition of the PushSecret. + type: string + required: + - status + - type + type: object + type: array + refreshTime: + description: |- + refreshTime is the time and date the external secret was fetched and + the target secret updated + format: date-time + nullable: true + type: string + syncedPushSecrets: + additionalProperties: + additionalProperties: + properties: + conversionStrategy: + default: None + description: Used to define a conversion Strategy for the secret keys + enum: + - None + - ReverseUnicode + type: string + match: + description: Match a given Secret Key to be pushed to the provider. + properties: + remoteRef: + description: Remote Refs to push to providers. + properties: + property: + description: Name of the property in the resulting secret + type: string + remoteKey: + description: Name of the resulting provider secret. + type: string + required: + - remoteKey + type: object + secretKey: + description: Secret Key to be pushed + type: string + required: + - remoteRef + type: object + metadata: + description: |- + Metadata is metadata attached to the secret. + The structure of metadata is provider specific, please look it up in the provider documentation. + x-kubernetes-preserve-unknown-fields: true + required: + - match + type: object + type: object + description: |- + Synced PushSecrets, including secrets that already exist in provider. + Matches secret stores to PushSecretData that was stored to that secret store. + type: object + syncedResourceVersion: + description: SyncedResourceVersion keeps track of the last synced version. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/backing-services/external-secrets/templates/crds/secretstore.yaml b/backing-services/external-secrets/templates/crds/secretstore.yaml new file mode 100644 index 0000000..7fcf115 --- /dev/null +++ b/backing-services/external-secrets/templates/crds/secretstore.yaml @@ -0,0 +1,4379 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller + name: secretstores.external-secrets.io +spec: + group: external-secrets.io + names: + categories: + - externalsecrets + kind: SecretStore + listKind: SecretStoreList + plural: secretstores + shortNames: + - ss + singular: secretstore + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].reason + name: Status + type: string + deprecated: true + name: v1alpha1 + schema: + openAPIV3Schema: + description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: SecretStoreSpec defines the desired state of SecretStore. + properties: + controller: + description: |- + Used to select the correct ESO controller (think: ingress.ingressClassName) + The ESO controller is instantiated with a specific controller name and filters ES based on this property + type: string + provider: + description: Used to configure the provider. Only one provider may be set + maxProperties: 1 + minProperties: 1 + properties: + akeyless: + description: Akeyless configures this store to sync secrets using Akeyless Vault provider + properties: + akeylessGWApiURL: + description: Akeyless GW API Url from which the secrets to be fetched from. + type: string + authSecretRef: + description: Auth configures how the operator authenticates with Akeyless. + properties: + kubernetesAuth: + description: |- + Kubernetes authenticates with Akeyless by passing the ServiceAccount + token stored in the named Secret resource. + properties: + accessID: + description: the Akeyless Kubernetes auth-method access-id + type: string + k8sConfName: + description: Kubernetes-auth configuration name in Akeyless-Gateway + type: string + secretRef: + description: |- + Optional secret field containing a Kubernetes ServiceAccount JWT used + for authenticating with Akeyless. If a name is specified without a key, + `token` is the default. If one is not specified, the one bound to + the controller will be used. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + serviceAccountRef: + description: |- + Optional service account field containing the name of a kubernetes ServiceAccount. + If the service account is specified, the service account secret token JWT will be used + for authenticating with Akeyless. If the service account selector is not supplied, + the secretRef will be used instead. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + required: + - accessID + - k8sConfName + type: object + secretRef: + description: |- + Reference to a Secret that contains the details + to authenticate with Akeyless. + properties: + accessID: + description: The SecretAccessID is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + accessType: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + accessTypeParam: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + type: object + caBundle: + description: |- + PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used + if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates + are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + required: + - akeylessGWApiURL + - authSecretRef + type: object + alibaba: + description: Alibaba configures this store to sync secrets using Alibaba Cloud provider + properties: + auth: + description: AlibabaAuth contains a secretRef for credentials. + properties: + rrsa: + description: Authenticate against Alibaba using RRSA. + properties: + oidcProviderArn: + type: string + oidcTokenFilePath: + type: string + roleArn: + type: string + sessionName: + type: string + required: + - oidcProviderArn + - oidcTokenFilePath + - roleArn + - sessionName + type: object + secretRef: + description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + accessKeySecretSecretRef: + description: The AccessKeySecret is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - accessKeyIDSecretRef + - accessKeySecretSecretRef + type: object + type: object + regionID: + description: Alibaba Region to be used for the provider + type: string + required: + - auth + - regionID + type: object + aws: + description: AWS configures this store to sync secrets using AWS Secret Manager provider + properties: + auth: + description: |- + Auth defines the information necessary to authenticate against AWS + if not set aws sdk will infer credentials from your environment + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + properties: + jwt: + description: Authenticate against AWS using service account tokens. + properties: + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + type: object + secretRef: + description: |- + AWSAuthSecretRef holds secret references for AWS credentials + both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + type: object + region: + description: AWS Region to be used for the provider + type: string + role: + description: Role is a Role ARN which the SecretManager provider will assume + type: string + service: + description: Service defines which service should be used to fetch the secrets + enum: + - SecretsManager + - ParameterStore + type: string + required: + - region + - service + type: object + azurekv: + description: AzureKV configures this store to sync secrets using Azure Key Vault provider + properties: + authSecretRef: + description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. + properties: + clientId: + description: The Azure clientId of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + clientSecret: + description: The Azure ClientSecret of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + authType: + default: ServicePrincipal + description: |- + Auth type defines how to authenticate to the keyvault service. + Valid values are: + - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) + - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) + enum: + - ServicePrincipal + - ManagedIdentity + - WorkloadIdentity + type: string + identityId: + description: If multiple Managed Identity is assigned to the pod, you can select the one to be used + type: string + serviceAccountRef: + description: |- + ServiceAccountRef specified the service account + that should be used when authenticating with WorkloadIdentity. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + tenantId: + description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. + type: string + vaultUrl: + description: Vault Url from which the secrets to be fetched from. + type: string + required: + - vaultUrl + type: object + fake: + description: Fake configures a store with static key/value pairs + properties: + data: + items: + properties: + key: + type: string + value: + type: string + valueMap: + additionalProperties: + type: string + type: object + version: + type: string + required: + - key + type: object + type: array + required: + - data + type: object + gcpsm: + description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider + properties: + auth: + description: Auth defines the information necessary to authenticate against GCP + properties: + secretRef: + properties: + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + workloadIdentity: + properties: + clusterLocation: + type: string + clusterName: + type: string + clusterProjectID: + type: string + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + required: + - clusterLocation + - clusterName + - serviceAccountRef + type: object + type: object + projectID: + description: ProjectID project where secret is located + type: string + type: object + gitlab: + description: GitLab configures this store to sync secrets using GitLab Variables provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a GitLab instance. + properties: + SecretRef: + properties: + accessToken: + description: AccessToken is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - SecretRef + type: object + projectID: + description: ProjectID specifies a project where secrets are located. + type: string + url: + description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. + type: string + required: + - auth + type: object + ibm: + description: IBM configures this store to sync secrets using IBM Cloud provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the IBM secrets manager. + properties: + secretRef: + properties: + secretApiKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + serviceUrl: + description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance + type: string + required: + - auth + type: object + kubernetes: + description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a Kubernetes instance. + maxProperties: 1 + minProperties: 1 + properties: + cert: + description: has both clientCert and clientKey as secretKeySelector + properties: + clientCert: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + clientKey: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + serviceAccount: + description: points to a service account that should be used for authentication + properties: + serviceAccount: + description: A reference to a ServiceAccount resource. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + type: object + token: + description: use static token to authenticate with + properties: + bearerToken: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + type: object + remoteNamespace: + default: default + description: Remote namespace to fetch the secrets from + type: string + server: + description: configures the Kubernetes server Address. + properties: + caBundle: + description: CABundle is a base64-encoded CA certificate + format: byte + type: string + caProvider: + description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + url: + default: kubernetes.default + description: configures the Kubernetes server Address. + type: string + type: object + required: + - auth + type: object + oracle: + description: Oracle configures this store to sync secrets using Oracle Vault provider + properties: + auth: + description: |- + Auth configures how secret-manager authenticates with the Oracle Vault. + If empty, instance principal is used. Optionally, the authenticating principal type + and/or user data may be supplied for the use of workload identity and user principal. + properties: + secretRef: + description: SecretRef to pass through sensitive information. + properties: + fingerprint: + description: Fingerprint is the fingerprint of the API private key. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + privatekey: + description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - fingerprint + - privatekey + type: object + tenancy: + description: Tenancy is the tenancy OCID where user is located. + type: string + user: + description: User is an access OCID specific to the account. + type: string + required: + - secretRef + - tenancy + - user + type: object + compartment: + description: |- + Compartment is the vault compartment OCID. + Required for PushSecret + type: string + encryptionKey: + description: |- + EncryptionKey is the OCID of the encryption key within the vault. + Required for PushSecret + type: string + principalType: + description: |- + The type of principal to use for authentication. If left blank, the Auth struct will + determine the principal type. This optional field must be specified if using + workload identity. + enum: + - "" + - UserPrincipal + - InstancePrincipal + - Workload + type: string + region: + description: Region is the region where vault is located. + type: string + serviceAccountRef: + description: |- + ServiceAccountRef specified the service account + that should be used when authenticating with WorkloadIdentity. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + vault: + description: Vault is the vault's OCID of the specific vault where secret is located. + type: string + required: + - region + - vault + type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object + vault: + description: Vault configures this store to sync secrets using Hashi provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the Vault server. + properties: + appRole: + description: |- + AppRole authenticates with Vault using the App Role auth mechanism, + with the role and secret stored in a Kubernetes Secret resource. + properties: + path: + default: approle + description: |- + Path where the App Role authentication backend is mounted + in Vault, e.g: "approle" + type: string + roleId: + description: |- + RoleID configured in the App Role authentication backend when setting + up the authentication backend in Vault. + type: string + secretRef: + description: |- + Reference to a key in a Secret that contains the App Role secret used + to authenticate with Vault. + The `key` field must be specified and denotes which entry within the Secret + resource is used as the app role secret. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - path + - roleId + - secretRef + type: object + cert: + description: |- + Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate + Cert authentication method + properties: + clientCert: + description: |- + ClientCert is a certificate to authenticate using the Cert Vault + authentication method + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + secretRef: + description: |- + SecretRef to a key in a Secret resource containing client private key to + authenticate with Vault using the Cert authentication method + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + jwt: + description: |- + Jwt authenticates with Vault by passing role and JWT token using the + JWT/OIDC authentication method + properties: + kubernetesServiceAccountToken: + description: |- + Optional ServiceAccountToken specifies the Kubernetes service account for which to request + a token for with the `TokenRequest` API. + properties: + audiences: + description: |- + Optional audiences field that will be used to request a temporary Kubernetes service + account token for the service account referenced by `serviceAccountRef`. + Defaults to a single audience `vault` it not specified. + items: + type: string + type: array + expirationSeconds: + description: |- + Optional expiration time in seconds that will be used to request a temporary + Kubernetes service account token for the service account referenced by + `serviceAccountRef`. + Defaults to 10 minutes. + format: int64 + type: integer + serviceAccountRef: + description: Service account field containing the name of a kubernetes ServiceAccount. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + required: + - serviceAccountRef + type: object + path: + default: jwt + description: |- + Path where the JWT authentication backend is mounted + in Vault, e.g: "jwt" + type: string + role: + description: |- + Role is a JWT role to authenticate using the JWT/OIDC Vault + authentication method + type: string + secretRef: + description: |- + Optional SecretRef that refers to a key in a Secret resource containing JWT token to + authenticate with Vault using the JWT/OIDC authentication method. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - path + type: object + kubernetes: + description: |- + Kubernetes authenticates with Vault by passing the ServiceAccount + token stored in the named Secret resource to the Vault server. + properties: + mountPath: + default: kubernetes + description: |- + Path where the Kubernetes authentication backend is mounted in Vault, e.g: + "kubernetes" + type: string + role: + description: |- + A required field containing the Vault Role to assume. A Role binds a + Kubernetes ServiceAccount with a set of Vault policies. + type: string + secretRef: + description: |- + Optional secret field containing a Kubernetes ServiceAccount JWT used + for authenticating with Vault. If a name is specified without a key, + `token` is the default. If one is not specified, the one bound to + the controller will be used. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + serviceAccountRef: + description: |- + Optional service account field containing the name of a kubernetes ServiceAccount. + If the service account is specified, the service account secret token JWT will be used + for authenticating with Vault. If the service account selector is not supplied, + the secretRef will be used instead. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + required: + - mountPath + - role + type: object + ldap: + description: |- + Ldap authenticates with Vault by passing username/password pair using + the LDAP authentication method + properties: + path: + default: ldap + description: |- + Path where the LDAP authentication backend is mounted + in Vault, e.g: "ldap" + type: string + secretRef: + description: |- + SecretRef to a key in a Secret resource containing password for the LDAP + user used to authenticate with Vault using the LDAP authentication + method + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + username: + description: |- + Username is a LDAP user name used to authenticate using the LDAP Vault + authentication method + type: string + required: + - path + - username + type: object + tokenSecretRef: + description: TokenSecretRef authenticates with Vault by presenting a token. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + caBundle: + description: |- + PEM encoded CA bundle used to validate Vault server certificate. Only used + if the Server URL is using HTTPS protocol. This parameter is ignored for + plain HTTP protocol connection. If not set the system root certificates + are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate Vault server certificate. + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + forwardInconsistent: + description: |- + ForwardInconsistent tells Vault to forward read-after-write requests to the Vault + leader instead of simply retrying within a loop. This can increase performance if + the option is enabled serverside. + https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header + type: boolean + namespace: + description: |- + Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows + Vault environments to support Secure Multi-tenancy. e.g: "ns1". + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + type: string + path: + description: |- + Path is the mount path of the Vault KV backend endpoint, e.g: + "secret". The v2 KV secret engine version specific "/data" path suffix + for fetching secrets from Vault is optional and will be appended + if not present in specified path. + type: string + readYourWrites: + description: |- + ReadYourWrites ensures isolated read-after-write semantics by + providing discovered cluster replication states in each request. + More information about eventual consistency in Vault can be found here + https://www.vaultproject.io/docs/enterprise/consistency + type: boolean + server: + description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' + type: string + version: + default: v2 + description: |- + Version is the Vault KV secret engine version. This can be either "v1" or + "v2". Version defaults to "v2". + enum: + - v1 + - v2 + type: string + required: + - auth + - server + type: object + webhook: + description: Webhook configures this store to sync secrets using a generic templated webhook + properties: + body: + description: Body + type: string + caBundle: + description: |- + PEM encoded CA bundle used to validate webhook server certificate. Only used + if the Server URL is using HTTPS protocol. This parameter is ignored for + plain HTTP protocol connection. If not set the system root certificates + are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate webhook server certificate. + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + headers: + additionalProperties: + type: string + description: Headers + type: object + method: + description: Webhook Method + type: string + result: + description: Result formatting + properties: + jsonPath: + description: Json path of return value + type: string + type: object + secrets: + description: |- + Secrets to fill in templates + These secrets will be passed to the templating function as key value pairs under the given name + items: + properties: + name: + description: Name of this secret in templates + type: string + secretRef: + description: Secret ref to fill in credentials + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - name + - secretRef + type: object + type: array + timeout: + description: Timeout + type: string + url: + description: Webhook url to call + type: string + required: + - result + - url + type: object + yandexlockbox: + description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider + properties: + apiEndpoint: + description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') + type: string + auth: + description: Auth defines the information necessary to authenticate against Yandex Lockbox + properties: + authorizedKeySecretRef: + description: The authorized key used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + caProvider: + description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. + properties: + certSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - auth + type: object + type: object + retrySettings: + description: Used to configure http retries if failed + properties: + maxRetries: + format: int32 + type: integer + retryInterval: + type: string + type: object + required: + - provider + type: object + status: + description: SecretStoreStatus defines the observed state of the SecretStore. + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].reason + name: Status + type: string + - jsonPath: .status.capabilities + name: Capabilities + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: SecretStoreSpec defines the desired state of SecretStore. + properties: + conditions: + description: Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore + items: + description: |- + ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in + for a ClusterSecretStore instance. + properties: + namespaceRegexes: + description: Choose namespaces by using regex matching + items: + type: string + type: array + namespaceSelector: + description: Choose namespace using a labelSelector + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: Choose namespaces by name + items: + type: string + type: array + type: object + type: array + controller: + description: |- + Used to select the correct ESO controller (think: ingress.ingressClassName) + The ESO controller is instantiated with a specific controller name and filters ES based on this property + type: string + provider: + description: Used to configure the provider. Only one provider may be set + maxProperties: 1 + minProperties: 1 + properties: + akeyless: + description: Akeyless configures this store to sync secrets using Akeyless Vault provider + properties: + akeylessGWApiURL: + description: Akeyless GW API Url from which the secrets to be fetched from. + type: string + authSecretRef: + description: Auth configures how the operator authenticates with Akeyless. + properties: + kubernetesAuth: + description: |- + Kubernetes authenticates with Akeyless by passing the ServiceAccount + token stored in the named Secret resource. + properties: + accessID: + description: the Akeyless Kubernetes auth-method access-id + type: string + k8sConfName: + description: Kubernetes-auth configuration name in Akeyless-Gateway + type: string + secretRef: + description: |- + Optional secret field containing a Kubernetes ServiceAccount JWT used + for authenticating with Akeyless. If a name is specified without a key, + `token` is the default. If one is not specified, the one bound to + the controller will be used. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + serviceAccountRef: + description: |- + Optional service account field containing the name of a kubernetes ServiceAccount. + If the service account is specified, the service account secret token JWT will be used + for authenticating with Akeyless. If the service account selector is not supplied, + the secretRef will be used instead. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + required: + - accessID + - k8sConfName + type: object + secretRef: + description: |- + Reference to a Secret that contains the details + to authenticate with Akeyless. + properties: + accessID: + description: The SecretAccessID is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + accessType: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + accessTypeParam: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + type: object + caBundle: + description: |- + PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used + if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates + are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. + properties: + key: + description: The key where the CA certificate can be found in the Secret or ConfigMap. + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: |- + The namespace the Provider type is in. + Can only be defined when used in a ClusterSecretStore. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + required: + - akeylessGWApiURL + - authSecretRef + type: object + alibaba: + description: Alibaba configures this store to sync secrets using Alibaba Cloud provider + properties: + auth: + description: AlibabaAuth contains a secretRef for credentials. + properties: + rrsa: + description: Authenticate against Alibaba using RRSA. + properties: + oidcProviderArn: + type: string + oidcTokenFilePath: + type: string + roleArn: + type: string + sessionName: + type: string + required: + - oidcProviderArn + - oidcTokenFilePath + - roleArn + - sessionName + type: object + secretRef: + description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + accessKeySecretSecretRef: + description: The AccessKeySecret is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - accessKeyIDSecretRef + - accessKeySecretSecretRef + type: object + type: object + regionID: + description: Alibaba Region to be used for the provider + type: string + required: + - auth + - regionID + type: object + aws: + description: AWS configures this store to sync secrets using AWS Secret Manager provider + properties: + additionalRoles: + description: AdditionalRoles is a chained list of Role ARNs which the provider will sequentially assume before assuming the Role + items: + type: string + type: array + auth: + description: |- + Auth defines the information necessary to authenticate against AWS + if not set aws sdk will infer credentials from your environment + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + properties: + jwt: + description: Authenticate against AWS using service account tokens. + properties: + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + type: object + secretRef: + description: |- + AWSAuthSecretRef holds secret references for AWS credentials + both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + sessionTokenSecretRef: + description: |- + The SessionToken used for authentication + This must be defined if AccessKeyID and SecretAccessKey are temporary credentials + see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + type: object + externalID: + description: AWS External ID set on assumed IAM roles + type: string + region: + description: AWS Region to be used for the provider + type: string + role: + description: Role is a Role ARN which the provider will assume + type: string + secretsManager: + description: SecretsManager defines how the provider behaves when interacting with AWS SecretsManager + properties: + forceDeleteWithoutRecovery: + description: |- + Specifies whether to delete the secret without any recovery window. You + can't use both this parameter and RecoveryWindowInDays in the same call. + If you don't use either, then by default Secrets Manager uses a 30 day + recovery window. + see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-ForceDeleteWithoutRecovery + type: boolean + recoveryWindowInDays: + description: |- + The number of days from 7 to 30 that Secrets Manager waits before + permanently deleting the secret. You can't use both this parameter and + ForceDeleteWithoutRecovery in the same call. If you don't use either, + then by default Secrets Manager uses a 30 day recovery window. + see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-RecoveryWindowInDays + format: int64 + type: integer + type: object + service: + description: Service defines which service should be used to fetch the secrets + enum: + - SecretsManager + - ParameterStore + type: string + sessionTags: + description: AWS STS assume role session tags + items: + properties: + key: + type: string + value: + type: string + required: + - key + - value + type: object + type: array + transitiveTagKeys: + description: AWS STS assume role transitive session tags. Required when multiple rules are used with the provider + items: + type: string + type: array + required: + - region + - service + type: object + azurekv: + description: AzureKV configures this store to sync secrets using Azure Key Vault provider + properties: + authSecretRef: + description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. + properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + clientId: + description: The Azure clientId of the service principle or managed identity used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + clientSecret: + description: The Azure ClientSecret of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + tenantId: + description: The Azure tenantId of the managed identity used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + authType: + default: ServicePrincipal + description: |- + Auth type defines how to authenticate to the keyvault service. + Valid values are: + - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) + - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) + enum: + - ServicePrincipal + - ManagedIdentity + - WorkloadIdentity + type: string + environmentType: + default: PublicCloud + description: |- + EnvironmentType specifies the Azure cloud environment endpoints to use for + connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. + The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 + PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud + enum: + - PublicCloud + - USGovernmentCloud + - ChinaCloud + - GermanCloud + type: string + identityId: + description: If multiple Managed Identity is assigned to the pod, you can select the one to be used + type: string + serviceAccountRef: + description: |- + ServiceAccountRef specified the service account + that should be used when authenticating with WorkloadIdentity. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + tenantId: + description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. + type: string + vaultUrl: + description: Vault Url from which the secrets to be fetched from. + type: string + required: + - vaultUrl + type: object + bitwardensecretsmanager: + description: BitwardenSecretsManager configures this store to sync secrets using BitwardenSecretsManager provider + properties: + apiURL: + type: string + auth: + description: |- + Auth configures how secret-manager authenticates with a bitwarden machine account instance. + Make sure that the token being used has permissions on the given secret. + properties: + secretRef: + description: BitwardenSecretsManagerSecretRef contains the credential ref to the bitwarden instance. + properties: + credentials: + description: AccessToken used for the bitwarden instance. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - credentials + type: object + required: + - secretRef + type: object + bitwardenServerSDKURL: + type: string + caBundle: + description: |- + Base64 encoded certificate for the bitwarden server sdk. The sdk MUST run with HTTPS to make sure no MITM attack + can be performed. + type: string + identityURL: + type: string + organizationID: + description: OrganizationID determines which organization this secret store manages. + type: string + projectID: + description: ProjectID determines which project this secret store manages. + type: string + required: + - auth + - caBundle + - organizationID + - projectID + type: object + chef: + description: Chef configures this store to sync secrets with chef server + properties: + auth: + description: Auth defines the information necessary to authenticate against chef Server + properties: + secretRef: + description: ChefAuthSecretRef holds secret references for chef server login credentials. + properties: + privateKeySecretRef: + description: SecretKey is the Signing Key in PEM format, used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - privateKeySecretRef + type: object + required: + - secretRef + type: object + serverUrl: + description: ServerURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a "/" + type: string + username: + description: UserName should be the user ID on the chef server + type: string + required: + - auth + - serverUrl + - username + type: object + conjur: + description: Conjur configures this store to sync secrets using conjur provider + properties: + auth: + properties: + apikey: + properties: + account: + type: string + apiKeyRef: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + userRef: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - account + - apiKeyRef + - userRef + type: object + jwt: + properties: + account: + type: string + hostId: + description: |- + Optional HostID for JWT authentication. This may be used depending + on how the Conjur JWT authenticator policy is configured. + type: string + secretRef: + description: |- + Optional SecretRef that refers to a key in a Secret resource containing JWT token to + authenticate with Conjur using the JWT authentication method. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + serviceAccountRef: + description: |- + Optional ServiceAccountRef specifies the Kubernetes service account for which to request + a token for with the `TokenRequest` API. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + serviceID: + description: The conjur authn jwt webservice id + type: string + required: + - account + - serviceID + type: object + type: object + caBundle: + type: string + caProvider: + description: |- + Used to provide custom certificate authority (CA) certificates + for a secret store. The CAProvider points to a Secret or ConfigMap resource + that contains a PEM-encoded certificate. + properties: + key: + description: The key where the CA certificate can be found in the Secret or ConfigMap. + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: |- + The namespace the Provider type is in. + Can only be defined when used in a ClusterSecretStore. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + url: + type: string + required: + - auth + - url + type: object + delinea: + description: |- + Delinea DevOps Secrets Vault + https://docs.delinea.com/online-help/products/devops-secrets-vault/current + properties: + clientId: + description: ClientID is the non-secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + clientSecret: + description: ClientSecret is the secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + tenant: + description: Tenant is the chosen hostname / site name. + type: string + tld: + description: |- + TLD is based on the server location that was chosen during provisioning. + If unset, defaults to "com". + type: string + urlTemplate: + description: |- + URLTemplate + If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". + type: string + required: + - clientId + - clientSecret + - tenant + type: object + device42: + description: Device42 configures this store to sync secrets using the Device42 provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a Device42 instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + host: + description: URL configures the Device42 instance URL. + type: string + required: + - auth + - host + type: object + doppler: + description: Doppler configures this store to sync secrets using the Doppler provider + properties: + auth: + description: Auth configures how the Operator authenticates with the Doppler API + properties: + secretRef: + properties: + dopplerToken: + description: |- + The DopplerToken is used for authentication. + See https://docs.doppler.com/reference/api#authentication for auth token types. + The Key attribute defaults to dopplerToken if not specified. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - dopplerToken + type: object + required: + - secretRef + type: object + config: + description: Doppler config (required if not using a Service Token) + type: string + format: + description: Format enables the downloading of secrets as a file (string) + enum: + - json + - dotnet-json + - env + - yaml + - docker + type: string + nameTransformer: + description: Environment variable compatible name transforms that change secret names to a different format + enum: + - upper-camel + - camel + - lower-snake + - tf-var + - dotnet-env + - lower-kebab + type: string + project: + description: Doppler project (required if not using a Service Token) + type: string + required: + - auth + type: object + fake: + description: Fake configures a store with static key/value pairs + properties: + data: + items: + properties: + key: + type: string + value: + type: string + valueMap: + additionalProperties: + type: string + description: 'Deprecated: ValueMap is deprecated and is intended to be removed in the future, use the `value` field instead.' + type: object + version: + type: string + required: + - key + type: object + type: array + required: + - data + type: object + fortanix: + description: Fortanix configures this store to sync secrets using the Fortanix provider + properties: + apiKey: + description: APIKey is the API token to access SDKMS Applications. + properties: + secretRef: + description: SecretRef is a reference to a secret containing the SDKMS API Key. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + apiUrl: + description: APIURL is the URL of SDKMS API. Defaults to `sdkms.fortanix.com`. + type: string + type: object + gcpsm: + description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider + properties: + auth: + description: Auth defines the information necessary to authenticate against GCP + properties: + secretRef: + properties: + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + workloadIdentity: + properties: + clusterLocation: + type: string + clusterName: + type: string + clusterProjectID: + type: string + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + required: + - clusterLocation + - clusterName + - serviceAccountRef + type: object + type: object + location: + description: Location optionally defines a location for a secret + type: string + projectID: + description: ProjectID project where secret is located + type: string + type: object + gitlab: + description: GitLab configures this store to sync secrets using GitLab Variables provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a GitLab instance. + properties: + SecretRef: + properties: + accessToken: + description: AccessToken is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - SecretRef + type: object + environment: + description: Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments) + type: string + groupIDs: + description: GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables. + items: + type: string + type: array + inheritFromGroups: + description: InheritFromGroups specifies whether parent groups should be discovered and checked for secrets. + type: boolean + projectID: + description: ProjectID specifies a project where secrets are located. + type: string + url: + description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. + type: string + required: + - auth + type: object + ibm: + description: IBM configures this store to sync secrets using IBM Cloud provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the IBM secrets manager. + maxProperties: 1 + minProperties: 1 + properties: + containerAuth: + description: IBM Container-based auth with IAM Trusted Profile. + properties: + iamEndpoint: + type: string + profile: + description: the IBM Trusted Profile + type: string + tokenLocation: + description: Location the token is mounted on the pod + type: string + required: + - profile + type: object + secretRef: + properties: + secretApiKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + type: object + serviceUrl: + description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance + type: string + required: + - auth + type: object + infisical: + description: Infisical configures this store to sync secrets using the Infisical provider + properties: + auth: + description: Auth configures how the Operator authenticates with the Infisical API + properties: + universalAuthCredentials: + properties: + clientId: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + clientSecret: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - clientId + - clientSecret + type: object + type: object + hostAPI: + default: https://app.infisical.com/api + type: string + secretsScope: + properties: + environmentSlug: + type: string + projectSlug: + type: string + secretsPath: + default: / + type: string + required: + - environmentSlug + - projectSlug + type: object + required: + - auth + - secretsScope + type: object + keepersecurity: + description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider + properties: + authRef: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + folderID: + type: string + required: + - authRef + - folderID + type: object + kubernetes: + description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a Kubernetes instance. + maxProperties: 1 + minProperties: 1 + properties: + cert: + description: has both clientCert and clientKey as secretKeySelector + properties: + clientCert: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + clientKey: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + serviceAccount: + description: points to a service account that should be used for authentication + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + token: + description: use static token to authenticate with + properties: + bearerToken: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + type: object + authRef: + description: A reference to a secret that contains the auth information. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + remoteNamespace: + default: default + description: Remote namespace to fetch the secrets from + type: string + server: + description: configures the Kubernetes server Address. + properties: + caBundle: + description: CABundle is a base64-encoded CA certificate + format: byte + type: string + caProvider: + description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' + properties: + key: + description: The key where the CA certificate can be found in the Secret or ConfigMap. + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: |- + The namespace the Provider type is in. + Can only be defined when used in a ClusterSecretStore. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + url: + default: kubernetes.default + description: configures the Kubernetes server Address. + type: string + type: object + type: object + onboardbase: + description: Onboardbase configures this store to sync secrets using the Onboardbase provider + properties: + apiHost: + default: https://public.onboardbase.com/api/v1/ + description: APIHost use this to configure the host url for the API for selfhosted installation, default is https://public.onboardbase.com/api/v1/ + type: string + auth: + description: Auth configures how the Operator authenticates with the Onboardbase API + properties: + apiKeyRef: + description: |- + OnboardbaseAPIKey is the APIKey generated by an admin account. + It is used to recognize and authorize access to a project and environment within onboardbase + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + passcodeRef: + description: OnboardbasePasscode is the passcode attached to the API Key + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - apiKeyRef + - passcodeRef + type: object + environment: + default: development + description: Environment is the name of an environmnent within a project to pull the secrets from + type: string + project: + default: development + description: Project is an onboardbase project that the secrets should be pulled from + type: string + required: + - apiHost + - auth + - environment + - project + type: object + onepassword: + description: OnePassword configures this store to sync secrets using the 1Password Cloud provider + properties: + auth: + description: Auth defines the information necessary to authenticate against OnePassword Connect Server + properties: + secretRef: + description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. + properties: + connectTokenSecretRef: + description: The ConnectToken is used for authentication to a 1Password Connect Server. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - connectTokenSecretRef + type: object + required: + - secretRef + type: object + connectHost: + description: ConnectHost defines the OnePassword Connect Server to connect to + type: string + vaults: + additionalProperties: + type: integer + description: Vaults defines which OnePassword vaults to search in which order + type: object + required: + - auth + - connectHost + - vaults + type: object + oracle: + description: Oracle configures this store to sync secrets using Oracle Vault provider + properties: + auth: + description: |- + Auth configures how secret-manager authenticates with the Oracle Vault. + If empty, use the instance principal, otherwise the user credentials specified in Auth. + properties: + secretRef: + description: SecretRef to pass through sensitive information. + properties: + fingerprint: + description: Fingerprint is the fingerprint of the API private key. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + privatekey: + description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - fingerprint + - privatekey + type: object + tenancy: + description: Tenancy is the tenancy OCID where user is located. + type: string + user: + description: User is an access OCID specific to the account. + type: string + required: + - secretRef + - tenancy + - user + type: object + compartment: + description: |- + Compartment is the vault compartment OCID. + Required for PushSecret + type: string + encryptionKey: + description: |- + EncryptionKey is the OCID of the encryption key within the vault. + Required for PushSecret + type: string + principalType: + description: |- + The type of principal to use for authentication. If left blank, the Auth struct will + determine the principal type. This optional field must be specified if using + workload identity. + enum: + - "" + - UserPrincipal + - InstancePrincipal + - Workload + type: string + region: + description: Region is the region where vault is located. + type: string + serviceAccountRef: + description: |- + ServiceAccountRef specified the service account + that should be used when authenticating with WorkloadIdentity. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + vault: + description: Vault is the vault's OCID of the specific vault where secret is located. + type: string + required: + - region + - vault + type: object + passbolt: + properties: + auth: + description: Auth defines the information necessary to authenticate against Passbolt Server + properties: + passwordSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + privateKeySecretRef: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - passwordSecretRef + - privateKeySecretRef + type: object + host: + description: Host defines the Passbolt Server to connect to + type: string + required: + - auth + - host + type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object + pulumi: + description: Pulumi configures this store to sync secrets using the Pulumi provider + properties: + accessToken: + description: AccessToken is the access tokens to sign in to the Pulumi Cloud Console. + properties: + secretRef: + description: SecretRef is a reference to a secret containing the Pulumi API token. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + apiUrl: + default: https://api.pulumi.com + description: APIURL is the URL of the Pulumi API. + type: string + environment: + description: |- + Environment are YAML documents composed of static key-value pairs, programmatic expressions, + dynamically retrieved values from supported providers including all major clouds, + and other Pulumi ESC environments. + To create a new environment, visit https://www.pulumi.com/docs/esc/environments/ for more information. + type: string + organization: + description: |- + Organization are a space to collaborate on shared projects and stacks. + To create a new organization, visit https://app.pulumi.com/ and click "New Organization". + type: string + required: + - accessToken + - environment + - organization + type: object + scaleway: + description: Scaleway + properties: + accessKey: + description: AccessKey is the non-secret part of the api key. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + apiUrl: + description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com + type: string + projectId: + description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' + type: string + region: + description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' + type: string + secretKey: + description: SecretKey is the non-secret part of the api key. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + required: + - accessKey + - projectId + - region + - secretKey + type: object + senhasegura: + description: Senhasegura configures this store to sync secrets using senhasegura provider + properties: + auth: + description: Auth defines parameters to authenticate in senhasegura + properties: + clientId: + type: string + clientSecretSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - clientId + - clientSecretSecretRef + type: object + ignoreSslCertificate: + default: false + description: IgnoreSslCertificate defines if SSL certificate must be ignored + type: boolean + module: + description: Module defines which senhasegura module should be used to get secrets + type: string + url: + description: URL of senhasegura + type: string + required: + - auth + - module + - url + type: object + vault: + description: Vault configures this store to sync secrets using Hashi provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the Vault server. + properties: + appRole: + description: |- + AppRole authenticates with Vault using the App Role auth mechanism, + with the role and secret stored in a Kubernetes Secret resource. + properties: + path: + default: approle + description: |- + Path where the App Role authentication backend is mounted + in Vault, e.g: "approle" + type: string + roleId: + description: |- + RoleID configured in the App Role authentication backend when setting + up the authentication backend in Vault. + type: string + roleRef: + description: |- + Reference to a key in a Secret that contains the App Role ID used + to authenticate with Vault. + The `key` field must be specified and denotes which entry within the Secret + resource is used as the app role id. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + secretRef: + description: |- + Reference to a key in a Secret that contains the App Role secret used + to authenticate with Vault. + The `key` field must be specified and denotes which entry within the Secret + resource is used as the app role secret. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - path + - secretRef + type: object + cert: + description: |- + Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate + Cert authentication method + properties: + clientCert: + description: |- + ClientCert is a certificate to authenticate using the Cert Vault + authentication method + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + secretRef: + description: |- + SecretRef to a key in a Secret resource containing client private key to + authenticate with Vault using the Cert authentication method + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + iam: + description: |- + Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials + AWS IAM authentication method + properties: + externalID: + description: AWS External ID set on assumed IAM roles + type: string + jwt: + description: Specify a service account with IRSA enabled + properties: + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + type: object + path: + description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' + type: string + region: + description: AWS region + type: string + role: + description: This is the AWS role to be assumed before talking to vault + type: string + secretRef: + description: Specify credentials in a Secret object + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + sessionTokenSecretRef: + description: |- + The SessionToken used for authentication + This must be defined if AccessKeyID and SecretAccessKey are temporary credentials + see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + vaultAwsIamServerID: + description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' + type: string + vaultRole: + description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine + type: string + required: + - vaultRole + type: object + jwt: + description: |- + Jwt authenticates with Vault by passing role and JWT token using the + JWT/OIDC authentication method + properties: + kubernetesServiceAccountToken: + description: |- + Optional ServiceAccountToken specifies the Kubernetes service account for which to request + a token for with the `TokenRequest` API. + properties: + audiences: + description: |- + Optional audiences field that will be used to request a temporary Kubernetes service + account token for the service account referenced by `serviceAccountRef`. + Defaults to a single audience `vault` it not specified. + Deprecated: use serviceAccountRef.Audiences instead + items: + type: string + type: array + expirationSeconds: + description: |- + Optional expiration time in seconds that will be used to request a temporary + Kubernetes service account token for the service account referenced by + `serviceAccountRef`. + Deprecated: this will be removed in the future. + Defaults to 10 minutes. + format: int64 + type: integer + serviceAccountRef: + description: Service account field containing the name of a kubernetes ServiceAccount. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + required: + - serviceAccountRef + type: object + path: + default: jwt + description: |- + Path where the JWT authentication backend is mounted + in Vault, e.g: "jwt" + type: string + role: + description: |- + Role is a JWT role to authenticate using the JWT/OIDC Vault + authentication method + type: string + secretRef: + description: |- + Optional SecretRef that refers to a key in a Secret resource containing JWT token to + authenticate with Vault using the JWT/OIDC authentication method. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - path + type: object + kubernetes: + description: |- + Kubernetes authenticates with Vault by passing the ServiceAccount + token stored in the named Secret resource to the Vault server. + properties: + mountPath: + default: kubernetes + description: |- + Path where the Kubernetes authentication backend is mounted in Vault, e.g: + "kubernetes" + type: string + role: + description: |- + A required field containing the Vault Role to assume. A Role binds a + Kubernetes ServiceAccount with a set of Vault policies. + type: string + secretRef: + description: |- + Optional secret field containing a Kubernetes ServiceAccount JWT used + for authenticating with Vault. If a name is specified without a key, + `token` is the default. If one is not specified, the one bound to + the controller will be used. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + serviceAccountRef: + description: |- + Optional service account field containing the name of a kubernetes ServiceAccount. + If the service account is specified, the service account secret token JWT will be used + for authenticating with Vault. If the service account selector is not supplied, + the secretRef will be used instead. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + required: + - mountPath + - role + type: object + ldap: + description: |- + Ldap authenticates with Vault by passing username/password pair using + the LDAP authentication method + properties: + path: + default: ldap + description: |- + Path where the LDAP authentication backend is mounted + in Vault, e.g: "ldap" + type: string + secretRef: + description: |- + SecretRef to a key in a Secret resource containing password for the LDAP + user used to authenticate with Vault using the LDAP authentication + method + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + username: + description: |- + Username is a LDAP user name used to authenticate using the LDAP Vault + authentication method + type: string + required: + - path + - username + type: object + namespace: + description: |- + Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. + Namespaces is a set of features within Vault Enterprise that allows + Vault environments to support Secure Multi-tenancy. e.g: "ns1". + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + This will default to Vault.Namespace field if set, or empty otherwise + type: string + tokenSecretRef: + description: TokenSecretRef authenticates with Vault by presenting a token. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: |- + Path where the UserPassword authentication backend is mounted + in Vault, e.g: "user" + type: string + secretRef: + description: |- + SecretRef to a key in a Secret resource containing password for the + user used to authenticate with Vault using the UserPass authentication + method + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + username: + description: |- + Username is a user name used to authenticate using the UserPass Vault + authentication method + type: string + required: + - path + - username + type: object + type: object + caBundle: + description: |- + PEM encoded CA bundle used to validate Vault server certificate. Only used + if the Server URL is using HTTPS protocol. This parameter is ignored for + plain HTTP protocol connection. If not set the system root certificates + are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate Vault server certificate. + properties: + key: + description: The key where the CA certificate can be found in the Secret or ConfigMap. + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: |- + The namespace the Provider type is in. + Can only be defined when used in a ClusterSecretStore. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + forwardInconsistent: + description: |- + ForwardInconsistent tells Vault to forward read-after-write requests to the Vault + leader instead of simply retrying within a loop. This can increase performance if + the option is enabled serverside. + https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header + type: boolean + namespace: + description: |- + Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows + Vault environments to support Secure Multi-tenancy. e.g: "ns1". + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + type: string + path: + description: |- + Path is the mount path of the Vault KV backend endpoint, e.g: + "secret". The v2 KV secret engine version specific "/data" path suffix + for fetching secrets from Vault is optional and will be appended + if not present in specified path. + type: string + readYourWrites: + description: |- + ReadYourWrites ensures isolated read-after-write semantics by + providing discovered cluster replication states in each request. + More information about eventual consistency in Vault can be found here + https://www.vaultproject.io/docs/enterprise/consistency + type: boolean + server: + description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' + type: string + tls: + description: |- + The configuration used for client side related TLS communication, when the Vault server + requires mutual authentication. Only used if the Server URL is using HTTPS protocol. + This parameter is ignored for plain HTTP protocol connection. + It's worth noting this configuration is different from the "TLS certificates auth method", + which is available under the `auth.cert` section. + properties: + certSecretRef: + description: |- + CertSecretRef is a certificate added to the transport layer + when communicating with the Vault server. + If no key for the Secret is specified, external-secret will default to 'tls.crt'. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + keySecretRef: + description: |- + KeySecretRef to a key in a Secret resource containing client private key + added to the transport layer when communicating with the Vault server. + If no key for the Secret is specified, external-secret will default to 'tls.key'. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + version: + default: v2 + description: |- + Version is the Vault KV secret engine version. This can be either "v1" or + "v2". Version defaults to "v2". + enum: + - v1 + - v2 + type: string + required: + - auth + - server + type: object + webhook: + description: Webhook configures this store to sync secrets using a generic templated webhook + properties: + body: + description: Body + type: string + caBundle: + description: |- + PEM encoded CA bundle used to validate webhook server certificate. Only used + if the Server URL is using HTTPS protocol. This parameter is ignored for + plain HTTP protocol connection. If not set the system root certificates + are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate webhook server certificate. + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + headers: + additionalProperties: + type: string + description: Headers + type: object + method: + description: Webhook Method + type: string + result: + description: Result formatting + properties: + jsonPath: + description: Json path of return value + type: string + type: object + secrets: + description: |- + Secrets to fill in templates + These secrets will be passed to the templating function as key value pairs under the given name + items: + properties: + name: + description: Name of this secret in templates + type: string + secretRef: + description: Secret ref to fill in credentials + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - name + - secretRef + type: object + type: array + timeout: + description: Timeout + type: string + url: + description: Webhook url to call + type: string + required: + - result + - url + type: object + yandexcertificatemanager: + description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider + properties: + apiEndpoint: + description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') + type: string + auth: + description: Auth defines the information necessary to authenticate against Yandex Certificate Manager + properties: + authorizedKeySecretRef: + description: The authorized key used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + caProvider: + description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. + properties: + certSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - auth + type: object + yandexlockbox: + description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider + properties: + apiEndpoint: + description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') + type: string + auth: + description: Auth defines the information necessary to authenticate against Yandex Lockbox + properties: + authorizedKeySecretRef: + description: The authorized key used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + caProvider: + description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. + properties: + certSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - auth + type: object + type: object + refreshInterval: + description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. + type: integer + retrySettings: + description: Used to configure http retries if failed + properties: + maxRetries: + format: int32 + type: integer + retryInterval: + type: string + type: object + required: + - provider + type: object + status: + description: SecretStoreStatus defines the observed state of the SecretStore. + properties: + capabilities: + description: SecretStoreCapabilities defines the possible operations a SecretStore can do. + type: string + conditions: + items: + properties: + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/backing-services/external-secrets/templates/crds/vaultdynamicsecret.yaml b/backing-services/external-secrets/templates/crds/vaultdynamicsecret.yaml new file mode 100644 index 0000000..ab03c5b --- /dev/null +++ b/backing-services/external-secrets/templates/crds/vaultdynamicsecret.yaml @@ -0,0 +1,702 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller + name: vaultdynamicsecrets.generators.external-secrets.io +spec: + group: generators.external-secrets.io + names: + categories: + - vaultdynamicsecret + kind: VaultDynamicSecret + listKind: VaultDynamicSecretList + plural: vaultdynamicsecrets + shortNames: + - vaultdynamicsecret + singular: vaultdynamicsecret + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + properties: + controller: + description: |- + Used to select the correct ESO controller (think: ingress.ingressClassName) + The ESO controller is instantiated with a specific controller name and filters VDS based on this property + type: string + method: + description: Vault API method to use (GET/POST/other) + type: string + parameters: + description: Parameters to pass to Vault write (for non-GET methods) + x-kubernetes-preserve-unknown-fields: true + path: + description: Vault path to obtain the dynamic secret from + type: string + provider: + description: Vault provider common spec + properties: + auth: + description: Auth configures how secret-manager authenticates with the Vault server. + properties: + appRole: + description: |- + AppRole authenticates with Vault using the App Role auth mechanism, + with the role and secret stored in a Kubernetes Secret resource. + properties: + path: + default: approle + description: |- + Path where the App Role authentication backend is mounted + in Vault, e.g: "approle" + type: string + roleId: + description: |- + RoleID configured in the App Role authentication backend when setting + up the authentication backend in Vault. + type: string + roleRef: + description: |- + Reference to a key in a Secret that contains the App Role ID used + to authenticate with Vault. + The `key` field must be specified and denotes which entry within the Secret + resource is used as the app role id. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + secretRef: + description: |- + Reference to a key in a Secret that contains the App Role secret used + to authenticate with Vault. + The `key` field must be specified and denotes which entry within the Secret + resource is used as the app role secret. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - path + - secretRef + type: object + cert: + description: |- + Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate + Cert authentication method + properties: + clientCert: + description: |- + ClientCert is a certificate to authenticate using the Cert Vault + authentication method + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + secretRef: + description: |- + SecretRef to a key in a Secret resource containing client private key to + authenticate with Vault using the Cert authentication method + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + iam: + description: |- + Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials + AWS IAM authentication method + properties: + externalID: + description: AWS External ID set on assumed IAM roles + type: string + jwt: + description: Specify a service account with IRSA enabled + properties: + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + type: object + path: + description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' + type: string + region: + description: AWS region + type: string + role: + description: This is the AWS role to be assumed before talking to vault + type: string + secretRef: + description: Specify credentials in a Secret object + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + sessionTokenSecretRef: + description: |- + The SessionToken used for authentication + This must be defined if AccessKeyID and SecretAccessKey are temporary credentials + see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + vaultAwsIamServerID: + description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' + type: string + vaultRole: + description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine + type: string + required: + - vaultRole + type: object + jwt: + description: |- + Jwt authenticates with Vault by passing role and JWT token using the + JWT/OIDC authentication method + properties: + kubernetesServiceAccountToken: + description: |- + Optional ServiceAccountToken specifies the Kubernetes service account for which to request + a token for with the `TokenRequest` API. + properties: + audiences: + description: |- + Optional audiences field that will be used to request a temporary Kubernetes service + account token for the service account referenced by `serviceAccountRef`. + Defaults to a single audience `vault` it not specified. + Deprecated: use serviceAccountRef.Audiences instead + items: + type: string + type: array + expirationSeconds: + description: |- + Optional expiration time in seconds that will be used to request a temporary + Kubernetes service account token for the service account referenced by + `serviceAccountRef`. + Deprecated: this will be removed in the future. + Defaults to 10 minutes. + format: int64 + type: integer + serviceAccountRef: + description: Service account field containing the name of a kubernetes ServiceAccount. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + required: + - serviceAccountRef + type: object + path: + default: jwt + description: |- + Path where the JWT authentication backend is mounted + in Vault, e.g: "jwt" + type: string + role: + description: |- + Role is a JWT role to authenticate using the JWT/OIDC Vault + authentication method + type: string + secretRef: + description: |- + Optional SecretRef that refers to a key in a Secret resource containing JWT token to + authenticate with Vault using the JWT/OIDC authentication method. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - path + type: object + kubernetes: + description: |- + Kubernetes authenticates with Vault by passing the ServiceAccount + token stored in the named Secret resource to the Vault server. + properties: + mountPath: + default: kubernetes + description: |- + Path where the Kubernetes authentication backend is mounted in Vault, e.g: + "kubernetes" + type: string + role: + description: |- + A required field containing the Vault Role to assume. A Role binds a + Kubernetes ServiceAccount with a set of Vault policies. + type: string + secretRef: + description: |- + Optional secret field containing a Kubernetes ServiceAccount JWT used + for authenticating with Vault. If a name is specified without a key, + `token` is the default. If one is not specified, the one bound to + the controller will be used. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + serviceAccountRef: + description: |- + Optional service account field containing the name of a kubernetes ServiceAccount. + If the service account is specified, the service account secret token JWT will be used + for authenticating with Vault. If the service account selector is not supplied, + the secretRef will be used instead. + properties: + audiences: + description: |- + Audience specifies the `aud` claim for the service account token + If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity + then this audiences will be appended to the list + items: + type: string + type: array + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + required: + - name + type: object + required: + - mountPath + - role + type: object + ldap: + description: |- + Ldap authenticates with Vault by passing username/password pair using + the LDAP authentication method + properties: + path: + default: ldap + description: |- + Path where the LDAP authentication backend is mounted + in Vault, e.g: "ldap" + type: string + secretRef: + description: |- + SecretRef to a key in a Secret resource containing password for the LDAP + user used to authenticate with Vault using the LDAP authentication + method + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + username: + description: |- + Username is a LDAP user name used to authenticate using the LDAP Vault + authentication method + type: string + required: + - path + - username + type: object + namespace: + description: |- + Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. + Namespaces is a set of features within Vault Enterprise that allows + Vault environments to support Secure Multi-tenancy. e.g: "ns1". + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + This will default to Vault.Namespace field if set, or empty otherwise + type: string + tokenSecretRef: + description: TokenSecretRef authenticates with Vault by presenting a token. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: |- + Path where the UserPassword authentication backend is mounted + in Vault, e.g: "user" + type: string + secretRef: + description: |- + SecretRef to a key in a Secret resource containing password for the + user used to authenticate with Vault using the UserPass authentication + method + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + username: + description: |- + Username is a user name used to authenticate using the UserPass Vault + authentication method + type: string + required: + - path + - username + type: object + type: object + caBundle: + description: |- + PEM encoded CA bundle used to validate Vault server certificate. Only used + if the Server URL is using HTTPS protocol. This parameter is ignored for + plain HTTP protocol connection. If not set the system root certificates + are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate Vault server certificate. + properties: + key: + description: The key where the CA certificate can be found in the Secret or ConfigMap. + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: |- + The namespace the Provider type is in. + Can only be defined when used in a ClusterSecretStore. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + forwardInconsistent: + description: |- + ForwardInconsistent tells Vault to forward read-after-write requests to the Vault + leader instead of simply retrying within a loop. This can increase performance if + the option is enabled serverside. + https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header + type: boolean + namespace: + description: |- + Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows + Vault environments to support Secure Multi-tenancy. e.g: "ns1". + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + type: string + path: + description: |- + Path is the mount path of the Vault KV backend endpoint, e.g: + "secret". The v2 KV secret engine version specific "/data" path suffix + for fetching secrets from Vault is optional and will be appended + if not present in specified path. + type: string + readYourWrites: + description: |- + ReadYourWrites ensures isolated read-after-write semantics by + providing discovered cluster replication states in each request. + More information about eventual consistency in Vault can be found here + https://www.vaultproject.io/docs/enterprise/consistency + type: boolean + server: + description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' + type: string + tls: + description: |- + The configuration used for client side related TLS communication, when the Vault server + requires mutual authentication. Only used if the Server URL is using HTTPS protocol. + This parameter is ignored for plain HTTP protocol connection. + It's worth noting this configuration is different from the "TLS certificates auth method", + which is available under the `auth.cert` section. + properties: + certSecretRef: + description: |- + CertSecretRef is a certificate added to the transport layer + when communicating with the Vault server. + If no key for the Secret is specified, external-secret will default to 'tls.crt'. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + keySecretRef: + description: |- + KeySecretRef to a key in a Secret resource containing client private key + added to the transport layer when communicating with the Vault server. + If no key for the Secret is specified, external-secret will default to 'tls.key'. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + version: + default: v2 + description: |- + Version is the Vault KV secret engine version. This can be either "v1" or + "v2". Version defaults to "v2". + enum: + - v1 + - v2 + type: string + required: + - auth + - server + type: object + resultType: + default: Data + description: |- + Result type defines which data is returned from the generator. + By default it is the "data" section of the Vault API response. + When using e.g. /auth/token/create the "data" section is empty but + the "auth" section contains the generated token. + Please refer to the vault docs regarding the result data structure. + enum: + - Data + - Auth + type: string + required: + - path + - provider + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/backing-services/external-secrets/templates/crds/webhook.yaml b/backing-services/external-secrets/templates/crds/webhook.yaml new file mode 100644 index 0000000..ee7c806 --- /dev/null +++ b/backing-services/external-secrets/templates/crds/webhook.yaml @@ -0,0 +1,157 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller + name: webhooks.generators.external-secrets.io +spec: + group: generators.external-secrets.io + names: + categories: + - webhook + kind: Webhook + listKind: WebhookList + plural: webhooks + shortNames: + - webhookl + singular: webhook + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + Webhook connects to a third party API server to handle the secrets generation + configuration parameters in spec. + You can specify the server, the token, and additional body parameters. + See documentation for the full API specification for requests and responses. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: WebhookSpec controls the behavior of the external generator. Any body parameters should be passed to the server through the parameters field. + properties: + body: + description: Body + type: string + caBundle: + description: |- + PEM encoded CA bundle used to validate webhook server certificate. Only used + if the Server URL is using HTTPS protocol. This parameter is ignored for + plain HTTP protocol connection. If not set the system root certificates + are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate webhook server certificate. + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + headers: + additionalProperties: + type: string + description: Headers + type: object + method: + description: Webhook Method + type: string + result: + description: Result formatting + properties: + jsonPath: + description: Json path of return value + type: string + type: object + secrets: + description: |- + Secrets to fill in templates + These secrets will be passed to the templating function as key value pairs under the given name + items: + properties: + name: + description: Name of this secret in templates + type: string + secretRef: + description: Secret ref to fill in credentials + properties: + key: + description: The key where the token is found. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + type: object + required: + - name + - secretRef + type: object + type: array + timeout: + description: Timeout + type: string + url: + description: Webhook url to call + type: string + required: + - result + - url + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/backing-services/external-secrets/templates/deployment.yaml b/backing-services/external-secrets/templates/deployment.yaml new file mode 100644 index 0000000..75a908e --- /dev/null +++ b/backing-services/external-secrets/templates/deployment.yaml @@ -0,0 +1,146 @@ +{{- if .Values.createOperator }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "external-secrets.fullname" . }} + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} + {{- with .Values.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.replicaCount }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "external-secrets.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "external-secrets.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "external-secrets.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.serviceAccount.automount }} + {{- with .Values.podSecurityContext }} + {{- if and (.enabled) (gt (keys . | len) 1) }} + securityContext: + {{- include "external-secrets.renderSecurityContext" (dict "securityContext" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + hostNetwork: {{ .Values.hostNetwork }} + containers: + - name: {{ .Chart.Name }} + {{- with .Values.securityContext }} + {{- if and (.enabled) (gt (keys . | len) 1) }} + securityContext: + {{- include "external-secrets.renderSecurityContext" (dict "securityContext" . "context" $) | nindent 12 }} + {{- end }} + {{- end }} + image: {{ include "external-secrets.image" (dict "chartAppVersion" .Chart.AppVersion "image" .Values.image) | trim }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if or (.Values.leaderElect) (.Values.scopedNamespace) (.Values.processClusterStore) (.Values.processClusterExternalSecret) (.Values.concurrent) (.Values.extraArgs) }} + args: + {{- if .Values.leaderElect }} + - --enable-leader-election=true + {{- end }} + {{- if .Values.scopedNamespace }} + - --namespace={{ .Values.scopedNamespace }} + {{- end }} + {{- if and .Values.scopedNamespace .Values.scopedRBAC }} + - --enable-cluster-store-reconciler=false + - --enable-cluster-external-secret-reconciler=false + {{- else }} + {{- if not .Values.processClusterStore }} + - --enable-cluster-store-reconciler=false + {{- end }} + {{- if not .Values.processClusterExternalSecret }} + - --enable-cluster-external-secret-reconciler=false + {{- end }} + {{- end }} + {{- if not .Values.processPushSecret }} + - --enable-push-secret-reconciler=false + {{- end }} + {{- if .Values.controllerClass }} + - --controller-class={{ .Values.controllerClass }} + {{- end }} + {{- if .Values.extendedMetricLabels }} + - --enable-extended-metric-labels={{ .Values.extendedMetricLabels }} + {{- end }} + {{- if .Values.concurrent }} + - --concurrent={{ .Values.concurrent }} + {{- end }} + {{- range $key, $value := .Values.extraArgs }} + {{- if $value }} + - --{{ $key }}={{ $value }} + {{- else }} + - --{{ $key }} + {{- end }} + {{- end }} + {{- end }} + - --metrics-addr=:{{ .Values.metrics.listen.port }} + - --loglevel={{ .Values.log.level }} + - --zap-time-encoding={{ .Values.log.timeEncoding }} + ports: + - containerPort: {{ .Values.metrics.listen.port }} + protocol: TCP + name: metrics + {{- with .Values.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.extraVolumeMounts }} + volumeMounts: + {{- toYaml .Values.extraVolumeMounts | nindent 12 }} + {{- end }} + {{- if .Values.extraContainers }} + {{ toYaml .Values.extraContainers | nindent 8}} + {{- end }} + dnsPolicy: {{ .Values.dnsPolicy }} + {{- if .Values.dnsConfig }} + dnsConfig: + {{- toYaml .Values.dnsConfig | nindent 8 }} + {{- end }} + {{- if .Values.extraVolumes }} + volumes: + {{- toYaml .Values.extraVolumes | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector | default .Values.global.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity | default .Values.global.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations | default .Values.global.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.topologySpreadConstraints | default .Values.global.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + {{- if .Values.podSpecExtra }} + {{- toYaml .Values.podSpecExtra | nindent 6 }} + {{- end }} +{{- end }} diff --git a/backing-services/external-secrets/templates/extra-manifests.yaml b/backing-services/external-secrets/templates/extra-manifests.yaml new file mode 100644 index 0000000..1dfe8f4 --- /dev/null +++ b/backing-services/external-secrets/templates/extra-manifests.yaml @@ -0,0 +1,4 @@ +{{- range .Values.extraObjects }} +--- +{{ include "external-secrets.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/backing-services/external-secrets/templates/poddisruptionbudget.yaml b/backing-services/external-secrets/templates/poddisruptionbudget.yaml new file mode 100644 index 0000000..7b75ca3 --- /dev/null +++ b/backing-services/external-secrets/templates/poddisruptionbudget.yaml @@ -0,0 +1,19 @@ +{{- if .Values.podDisruptionBudget.enabled }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "external-secrets.fullname" . }}-pdb + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} +spec: + {{- if .Values.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if .Values.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} + {{- end }} + selector: + matchLabels: + {{- include "external-secrets.selectorLabels" . | nindent 6 }} +{{- end }} diff --git a/backing-services/external-secrets/templates/rbac.yaml b/backing-services/external-secrets/templates/rbac.yaml new file mode 100644 index 0000000..4f4ab48 --- /dev/null +++ b/backing-services/external-secrets/templates/rbac.yaml @@ -0,0 +1,301 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +{{- if and .Values.scopedNamespace .Values.scopedRBAC }} +kind: Role +{{- else }} +kind: ClusterRole +{{- end }} +metadata: + name: {{ include "external-secrets.fullname" . }}-controller + {{- if and .Values.scopedNamespace .Values.scopedRBAC }} + namespace: {{ .Values.scopedNamespace | quote }} + {{- end }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} +rules: + - apiGroups: + - "external-secrets.io" + resources: + - "secretstores" + - "clustersecretstores" + - "externalsecrets" + - "clusterexternalsecrets" + - "pushsecrets" + verbs: + - "get" + - "list" + - "watch" + - apiGroups: + - "external-secrets.io" + resources: + - "externalsecrets" + - "externalsecrets/status" + - "externalsecrets/finalizers" + - "secretstores" + - "secretstores/status" + - "secretstores/finalizers" + - "clustersecretstores" + - "clustersecretstores/status" + - "clustersecretstores/finalizers" + - "clusterexternalsecrets" + - "clusterexternalsecrets/status" + - "clusterexternalsecrets/finalizers" + - "pushsecrets" + - "pushsecrets/status" + - "pushsecrets/finalizers" + verbs: + - "get" + - "update" + - "patch" + - apiGroups: + - "generators.external-secrets.io" + resources: + - "acraccesstokens" + - "ecrauthorizationtokens" + - "fakes" + - "gcraccesstokens" + - "githubaccesstokens" + - "passwords" + - "vaultdynamicsecrets" + - "webhooks" + verbs: + - "get" + - "list" + - "watch" + - apiGroups: + - "" + resources: + - "serviceaccounts" + - "namespaces" + verbs: + - "get" + - "list" + - "watch" + - apiGroups: + - "" + resources: + - "configmaps" + verbs: + - "get" + - "list" + - "watch" + - apiGroups: + - "" + resources: + - "secrets" + verbs: + - "get" + - "list" + - "watch" + - "create" + - "update" + - "delete" + - "patch" + - apiGroups: + - "" + resources: + - "serviceaccounts/token" + verbs: + - "create" + - apiGroups: + - "" + resources: + - "events" + verbs: + - "create" + - "patch" + - apiGroups: + - "external-secrets.io" + resources: + - "externalsecrets" + verbs: + - "create" + - "update" + - "delete" +--- +apiVersion: rbac.authorization.k8s.io/v1 +{{- if and .Values.scopedNamespace .Values.scopedRBAC }} +kind: Role +{{- else }} +kind: ClusterRole +{{- end }} +metadata: + name: {{ include "external-secrets.fullname" . }}-view + {{- if and .Values.scopedNamespace .Values.scopedRBAC }} + namespace: {{ .Values.scopedNamespace | quote }} + {{- end }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} + rbac.authorization.k8s.io/aggregate-to-view: "true" + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-admin: "true" +rules: + - apiGroups: + - "external-secrets.io" + resources: + - "externalsecrets" + - "secretstores" + - "clustersecretstores" + - "pushsecrets" + verbs: + - "get" + - "watch" + - "list" + - apiGroups: + - "generators.external-secrets.io" + resources: + - "acraccesstokens" + - "ecrauthorizationtokens" + - "fakes" + - "gcraccesstokens" + - "githubaccesstokens" + - "passwords" + - "vaultdynamicsecrets" + - "webhooks" + verbs: + - "get" + - "watch" + - "list" +--- +apiVersion: rbac.authorization.k8s.io/v1 +{{- if and .Values.scopedNamespace .Values.scopedRBAC }} +kind: Role +{{- else }} +kind: ClusterRole +{{- end }} +metadata: + name: {{ include "external-secrets.fullname" . }}-edit + {{- if and .Values.scopedNamespace .Values.scopedRBAC }} + namespace: {{ .Values.scopedNamespace | quote }} + {{- end }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-admin: "true" +rules: + - apiGroups: + - "external-secrets.io" + resources: + - "externalsecrets" + - "secretstores" + - "clustersecretstores" + - "pushsecrets" + verbs: + - "create" + - "delete" + - "deletecollection" + - "patch" + - "update" + - apiGroups: + - "generators.external-secrets.io" + resources: + - "acraccesstokens" + - "ecrauthorizationtokens" + - "fakes" + - "gcraccesstokens" + - "githubaccesstokens" + - "passwords" + - "vaultdynamicsecrets" + - "webhooks" + verbs: + - "create" + - "delete" + - "deletecollection" + - "patch" + - "update" +--- +apiVersion: rbac.authorization.k8s.io/v1 +{{- if and .Values.scopedNamespace .Values.scopedRBAC }} +kind: RoleBinding +{{- else }} +kind: ClusterRoleBinding +{{- end }} +metadata: + name: {{ include "external-secrets.fullname" . }}-controller + {{- if and .Values.scopedNamespace .Values.scopedRBAC }} + namespace: {{ .Values.scopedNamespace | quote }} + {{- end }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + {{- if and .Values.scopedNamespace .Values.scopedRBAC }} + kind: Role + {{- else }} + kind: ClusterRole + {{- end }} + name: {{ include "external-secrets.fullname" . }}-controller +subjects: + - name: {{ include "external-secrets.serviceAccountName" . }} + namespace: {{ template "external-secrets.namespace" . }} + kind: ServiceAccount +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "external-secrets.fullname" . }}-leaderelection + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} +rules: + - apiGroups: + - "" + resources: + - "configmaps" + resourceNames: + - "external-secrets-controller" + verbs: + - "get" + - "update" + - "patch" + - apiGroups: + - "" + resources: + - "configmaps" + verbs: + - "create" + - apiGroups: + - "coordination.k8s.io" + resources: + - "leases" + verbs: + - "get" + - "create" + - "update" + - "patch" +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "external-secrets.fullname" . }}-leaderelection + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "external-secrets.fullname" . }}-leaderelection +subjects: + - kind: ServiceAccount + name: {{ include "external-secrets.serviceAccountName" . }} + namespace: {{ template "external-secrets.namespace" . }} +{{- if .Values.rbac.servicebindings.create }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "external-secrets.fullname" . }}-servicebindings + labels: + servicebinding.io/controller: "true" + {{- include "external-secrets.labels" . | nindent 4 }} +rules: + - apiGroups: + - "external-secrets.io" + resources: + - "externalsecrets" + verbs: + - "get" + - "list" + - "watch" +{{- end }} +{{- end }} diff --git a/backing-services/external-secrets/templates/service.yaml b/backing-services/external-secrets/templates/service.yaml new file mode 100644 index 0000000..94859a3 --- /dev/null +++ b/backing-services/external-secrets/templates/service.yaml @@ -0,0 +1,28 @@ +{{- if .Values.metrics.service.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "external-secrets.fullname" . }}-metrics + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} + {{- with .Values.metrics.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + {{- if .Values.service.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.service.ipFamilyPolicy }} + {{- end }} + {{- if .Values.service.ipFamilies }} + ipFamilies: {{ .Values.service.ipFamilies | toYaml | nindent 2 }} + {{- end }} + ports: + - port: {{ .Values.metrics.service.port }} + protocol: TCP + targetPort: metrics + name: metrics + selector: + {{- include "external-secrets.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/backing-services/external-secrets/templates/serviceaccount.yaml b/backing-services/external-secrets/templates/serviceaccount.yaml new file mode 100644 index 0000000..ceaa98e --- /dev/null +++ b/backing-services/external-secrets/templates/serviceaccount.yaml @@ -0,0 +1,16 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "external-secrets.serviceAccountName" . }} + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.extraLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/external-secrets/templates/servicemonitor.yaml b/backing-services/external-secrets/templates/servicemonitor.yaml new file mode 100644 index 0000000..3145179 --- /dev/null +++ b/backing-services/external-secrets/templates/servicemonitor.yaml @@ -0,0 +1,164 @@ +{{- if and ( .Capabilities.APIVersions.Has "monitoring.coreos.com/v1" ) .Values.serviceMonitor.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "external-secrets.fullname" . }}-metrics + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} +spec: + type: ClusterIP + {{- if .Values.service.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.service.ipFamilyPolicy }} + {{- end }} + {{- if .Values.service.ipFamilies }} + ipFamilies: {{ .Values.service.ipFamilies | toYaml | nindent 2 }} + {{- end }} + ports: + - port: {{ .Values.metrics.service.port }} + protocol: TCP + name: metrics + selector: + {{- include "external-secrets.selectorLabels" . | nindent 4 }} +--- +apiVersion: "monitoring.coreos.com/v1" +kind: ServiceMonitor +metadata: + labels: + {{- include "external-secrets.labels" . | nindent 4 }} +{{- if .Values.serviceMonitor.additionalLabels }} +{{ toYaml .Values.serviceMonitor.additionalLabels | indent 4 }} +{{- end }} + name: {{ include "external-secrets.fullname" . }}-metrics + namespace: {{ .Values.serviceMonitor.namespace | default (include "external-secrets.namespace" .) | quote }} +spec: + selector: + matchLabels: + {{- include "external-secrets.selectorLabels" . | nindent 6 }} + namespaceSelector: + matchNames: + - {{ template "external-secrets.namespace" . }} + endpoints: + - port: metrics + interval: {{ .Values.serviceMonitor.interval }} + scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} + honorLabels: {{ .Values.serviceMonitor.honorLabels }} + {{- with .Values.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 6 }} + {{- end }} +--- +{{- if .Values.webhook.create }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "external-secrets.fullname" . }}-webhook-metrics + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets-webhook-metrics.labels" . | nindent 4 }} +spec: + type: ClusterIP + {{- if .Values.service.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.service.ipFamilyPolicy }} + {{- end }} + {{- if .Values.service.ipFamilies }} + ipFamilies: {{ .Values.service.ipFamilies | toYaml | nindent 2 }} + {{- end }} + ports: + - port: {{ .Values.webhook.metrics.service.port }} + protocol: TCP + name: metrics + selector: + {{- include "external-secrets-webhook.selectorLabels" . | nindent 4 }} +--- +apiVersion: "monitoring.coreos.com/v1" +kind: ServiceMonitor +metadata: + labels: + {{- include "external-secrets-webhook.labels" . | nindent 4 }} +{{- if .Values.serviceMonitor.additionalLabels }} +{{ toYaml .Values.serviceMonitor.additionalLabels | indent 4 }} +{{- end }} + name: {{ include "external-secrets.fullname" . }}-webhook-metrics + namespace: {{ .Values.serviceMonitor.namespace | default (include "external-secrets.namespace" .) | quote }} +spec: + selector: + matchLabels: + {{- include "external-secrets-webhook-metrics.labels" . | nindent 6 }} + namespaceSelector: + matchNames: + - {{ template "external-secrets.namespace" . }} + endpoints: + - port: metrics + interval: {{ .Values.serviceMonitor.interval }} + scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} + honorLabels: {{ .Values.serviceMonitor.honorLabels }} + {{- with .Values.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 6 }} + {{- end }} +{{- end }} +--- +{{- if .Values.certController.create }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "external-secrets.fullname" . }}-cert-controller-metrics + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets-cert-controller-metrics.labels" . | nindent 4 }} +spec: + type: ClusterIP + {{- if .Values.service.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.service.ipFamilyPolicy }} + {{- end }} + {{- if .Values.service.ipFamilies }} + ipFamilies: {{ .Values.service.ipFamilies | toYaml | nindent 2 }} + {{- end }} + ports: + - port: {{ .Values.certController.metrics.listen.port }} + protocol: TCP + name: metrics + selector: + {{- include "external-secrets-cert-controller.selectorLabels" . | nindent 4 }} +--- +apiVersion: "monitoring.coreos.com/v1" +kind: ServiceMonitor +metadata: + labels: + {{- include "external-secrets-cert-controller.labels" . | nindent 4 }} +{{- if .Values.serviceMonitor.additionalLabels }} +{{ toYaml .Values.serviceMonitor.additionalLabels | indent 4 }} +{{- end }} + name: {{ include "external-secrets.fullname" . }}-cert-controller-metrics + namespace: {{ .Values.serviceMonitor.namespace | default (include "external-secrets.namespace" .) | quote }} +spec: + selector: + matchLabels: + {{- include "external-secrets-cert-controller-metrics.labels" . | nindent 6 }} + namespaceSelector: + matchNames: + - {{ template "external-secrets.namespace" . }} + endpoints: + - port: metrics + interval: {{ .Values.serviceMonitor.interval }} + scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} + honorLabels: {{ .Values.serviceMonitor.honorLabels }} + {{- with .Values.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 6 }} + {{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/external-secrets/templates/validatingwebhook.yaml b/backing-services/external-secrets/templates/validatingwebhook.yaml new file mode 100644 index 0000000..63b3976 --- /dev/null +++ b/backing-services/external-secrets/templates/validatingwebhook.yaml @@ -0,0 +1,78 @@ +{{- if .Values.webhook.create }} +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: secretstore-validate + labels: + external-secrets.io/component: webhook + {{- with .Values.commonLabels }} + {{ toYaml . | nindent 4 }} + {{- end }} + {{- if and .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + annotations: + cert-manager.io/inject-ca-from: {{ template "external-secrets.namespace" . }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} +webhooks: +- name: "validate.secretstore.external-secrets.io" + rules: + - apiGroups: ["external-secrets.io"] + apiVersions: ["v1beta1"] + operations: ["CREATE", "UPDATE", "DELETE"] + resources: ["secretstores"] + scope: "Namespaced" + clientConfig: + service: + namespace: {{ template "external-secrets.namespace" . }} + name: {{ include "external-secrets.fullname" . }}-webhook + path: /validate-external-secrets-io-v1beta1-secretstore + admissionReviewVersions: ["v1", "v1beta1"] + sideEffects: None + timeoutSeconds: 5 + +- name: "validate.clustersecretstore.external-secrets.io" + rules: + - apiGroups: ["external-secrets.io"] + apiVersions: ["v1beta1"] + operations: ["CREATE", "UPDATE", "DELETE"] + resources: ["clustersecretstores"] + scope: "Cluster" + clientConfig: + service: + namespace: {{ template "external-secrets.namespace" . }} + name: {{ include "external-secrets.fullname" . }}-webhook + path: /validate-external-secrets-io-v1beta1-clustersecretstore + admissionReviewVersions: ["v1", "v1beta1"] + sideEffects: None + timeoutSeconds: 5 +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: externalsecret-validate + labels: + external-secrets.io/component: webhook + {{- with .Values.commonLabels }} + {{ toYaml . | nindent 4 }} + {{- end }} + {{- if and .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + annotations: + cert-manager.io/inject-ca-from: {{ template "external-secrets.namespace" . }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} +webhooks: +- name: "validate.externalsecret.external-secrets.io" + rules: + - apiGroups: ["external-secrets.io"] + apiVersions: ["v1beta1"] + operations: ["CREATE", "UPDATE", "DELETE"] + resources: ["externalsecrets"] + scope: "Namespaced" + clientConfig: + service: + namespace: {{ template "external-secrets.namespace" . }} + name: {{ include "external-secrets.fullname" . }}-webhook + path: /validate-external-secrets-io-v1beta1-externalsecret + admissionReviewVersions: ["v1", "v1beta1"] + sideEffects: None + timeoutSeconds: 5 + failurePolicy: {{ .Values.webhook.failurePolicy}} +{{- end }} diff --git a/backing-services/external-secrets/templates/webhook-certificate.yaml b/backing-services/external-secrets/templates/webhook-certificate.yaml new file mode 100644 index 0000000..adb19fd --- /dev/null +++ b/backing-services/external-secrets/templates/webhook-certificate.yaml @@ -0,0 +1,30 @@ +{{- if and .Values.webhook.create .Values.webhook.certManager.enabled .Values.webhook.certManager.cert.create }} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets-webhook.labels" . | nindent 4 }} + external-secrets.io/component: webhook + {{- with .Values.webhook.certManager.cert.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + commonName: {{ include "external-secrets.fullname" . }}-webhook + dnsNames: + - {{ include "external-secrets.fullname" . }}-webhook + - {{ include "external-secrets.fullname" . }}-webhook.{{ template "external-secrets.namespace" . }} + - {{ include "external-secrets.fullname" . }}-webhook.{{ template "external-secrets.namespace" . }}.svc + issuerRef: + {{- toYaml .Values.webhook.certManager.cert.issuerRef | nindent 4 }} + {{- with .Values.webhook.certManager.cert.duration }} + duration: {{ . | quote }} + {{- end }} + {{- with .Values.webhook.certManager.cert.renewBefore }} + renewBefore: {{ . | quote }} + {{- end }} + secretName: {{ include "external-secrets.fullname" . }}-webhook +{{- end }} diff --git a/backing-services/external-secrets/templates/webhook-deployment.yaml b/backing-services/external-secrets/templates/webhook-deployment.yaml new file mode 100644 index 0000000..7419a42 --- /dev/null +++ b/backing-services/external-secrets/templates/webhook-deployment.yaml @@ -0,0 +1,128 @@ +{{- if .Values.webhook.create }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets-webhook.labels" . | nindent 4 }} + {{- with .Values.webhook.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.webhook.replicaCount }} + revisionHistoryLimit: {{ .Values.webhook.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "external-secrets-webhook.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.webhook.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "external-secrets-webhook.labels" . | nindent 8 }} + {{- with .Values.webhook.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.webhook.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + hostNetwork: {{ .Values.webhook.hostNetwork}} + serviceAccountName: {{ include "external-secrets-webhook.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.webhook.serviceAccount.automount }} + {{- with .Values.webhook.podSecurityContext }} + {{- if and (.enabled) (gt (keys . | len) 1) }} + securityContext: + {{- include "external-secrets.renderSecurityContext" (dict "securityContext" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + containers: + - name: webhook + {{- with .Values.webhook.securityContext }} + {{- if and (.enabled) (gt (keys . | len) 1) }} + securityContext: + {{- include "external-secrets.renderSecurityContext" (dict "securityContext" . "context" $) | nindent 12 }} + {{- end }} + {{- end }} + image: {{ include "external-secrets.image" (dict "chartAppVersion" .Chart.AppVersion "image" .Values.webhook.image) | trim }} + imagePullPolicy: {{ .Values.webhook.image.pullPolicy }} + args: + - webhook + - --port={{ .Values.webhook.port }} + - --dns-name={{ include "external-secrets.fullname" . }}-webhook.{{ template "external-secrets.namespace" . }}.svc + - --cert-dir={{ .Values.webhook.certDir }} + - --check-interval={{ .Values.webhook.certCheckInterval }} + - --metrics-addr=:{{ .Values.webhook.metrics.listen.port }} + - --healthz-addr={{ .Values.webhook.readinessProbe.address }}:{{ .Values.webhook.readinessProbe.port }} + - --loglevel={{ .Values.webhook.log.level }} + - --zap-time-encoding={{ .Values.webhook.log.timeEncoding }} + {{- if .Values.webhook.lookaheadInterval }} + - --lookahead-interval={{ .Values.webhook.lookaheadInterval }} + {{- end }} + {{- range $key, $value := .Values.webhook.extraArgs }} + {{- if $value }} + - --{{ $key }}={{ $value }} + {{- else }} + - --{{ $key }} + {{- end }} + {{- end }} + ports: + - containerPort: {{ .Values.webhook.metrics.listen.port }} + protocol: TCP + name: metrics + - containerPort: {{ .Values.webhook.port }} + protocol: TCP + name: webhook + readinessProbe: + httpGet: + port: {{ .Values.webhook.readinessProbe.port }} + path: /readyz + initialDelaySeconds: 20 + periodSeconds: 5 + {{- with .Values.webhook.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.webhook.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: certs + mountPath: {{ .Values.webhook.certDir }} + readOnly: true + {{- if .Values.webhook.extraVolumeMounts }} + {{- toYaml .Values.webhook.extraVolumeMounts | nindent 12 }} + {{- end }} + volumes: + - name: certs + secret: + secretName: {{ include "external-secrets.fullname" . }}-webhook + {{- if .Values.webhook.extraVolumes }} + {{- toYaml .Values.webhook.extraVolumes | nindent 8 }} + {{- end }} + {{- with .Values.webhook.nodeSelector | default .Values.global.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.webhook.affinity | default .Values.global.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.webhook.tolerations | default .Values.global.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.webhook.topologySpreadConstraints | default .Values.global.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.webhook.priorityClassName }} + priorityClassName: {{ .Values.webhook.priorityClassName }} + {{- end }} +{{- end }} diff --git a/backing-services/external-secrets/templates/webhook-poddisruptionbudget.yaml b/backing-services/external-secrets/templates/webhook-poddisruptionbudget.yaml new file mode 100644 index 0000000..58345ba --- /dev/null +++ b/backing-services/external-secrets/templates/webhook-poddisruptionbudget.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.webhook.create .Values.webhook.podDisruptionBudget.enabled }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "external-secrets.fullname" . }}-webhook-pdb + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets-webhook.labels" . | nindent 4 }} + external-secrets.io/component: webhook +spec: + {{- if .Values.webhook.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.webhook.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if .Values.webhook.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.webhook.podDisruptionBudget.maxUnavailable }} + {{- end }} + selector: + matchLabels: + {{- include "external-secrets-webhook.selectorLabels" . | nindent 6 }} +{{- end }} diff --git a/backing-services/external-secrets/templates/webhook-secret.yaml b/backing-services/external-secrets/templates/webhook-secret.yaml new file mode 100644 index 0000000..fa7760e --- /dev/null +++ b/backing-services/external-secrets/templates/webhook-secret.yaml @@ -0,0 +1,14 @@ +{{- if and .Values.webhook.create (not .Values.webhook.certManager.enabled) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets-webhook.labels" . | nindent 4 }} + external-secrets.io/component: webhook + {{- with .Values.webhook.secretAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/external-secrets/templates/webhook-service.yaml b/backing-services/external-secrets/templates/webhook-service.yaml new file mode 100644 index 0000000..59dbddc --- /dev/null +++ b/backing-services/external-secrets/templates/webhook-service.yaml @@ -0,0 +1,37 @@ +{{- if .Values.webhook.create }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets-webhook.labels" . | nindent 4 }} + external-secrets.io/component: webhook + {{- if .Values.webhook.metrics.service.enabled }} + {{- with .Values.webhook.metrics.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} +spec: + type: ClusterIP + {{- if .Values.service.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.service.ipFamilyPolicy }} + {{- end }} + {{- if .Values.service.ipFamilies }} + ipFamilies: {{ .Values.service.ipFamilies | toYaml | nindent 2 }} + {{- end }} + ports: + - port: 443 + targetPort: {{ .Values.webhook.port }} + protocol: TCP + name: webhook + {{- if .Values.webhook.metrics.service.enabled }} + - port: {{ .Values.webhook.metrics.service.port }} + protocol: TCP + targetPort: metrics + name: metrics + {{- end }} + selector: + {{- include "external-secrets-webhook.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/backing-services/external-secrets/templates/webhook-serviceaccount.yaml b/backing-services/external-secrets/templates/webhook-serviceaccount.yaml new file mode 100644 index 0000000..1936218 --- /dev/null +++ b/backing-services/external-secrets/templates/webhook-serviceaccount.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.webhook.create .Values.webhook.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "external-secrets-webhook.serviceAccountName" . }} + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets-webhook.labels" . | nindent 4 }} + {{- with .Values.webhook.serviceAccount.extraLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.webhook.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/external-secrets/values.yaml b/backing-services/external-secrets/values.yaml new file mode 100644 index 0000000..19525ad --- /dev/null +++ b/backing-services/external-secrets/values.yaml @@ -0,0 +1,532 @@ +global: + nodeSelector: {} + tolerations: [] + topologySpreadConstraints: [] + affinity: {} + compatibility: + openshift: + # -- Manages the securityContext properties to make them compatible with OpenShift. + # Possible values: + # auto - Apply configurations if it is detected that OpenShift is the target platform. + # force - Always apply configurations. + # disabled - No modification applied. + adaptSecurityContext: auto + +replicaCount: 1 + +bitwarden-sdk-server: + enabled: false + +# -- Specifies the amount of historic ReplicaSets k8s should keep (see https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#clean-up-policy) +revisionHistoryLimit: 10 + +image: + repository: ghcr.io/external-secrets/external-secrets + pullPolicy: IfNotPresent + # -- The image tag to use. The default is the chart appVersion. + tag: "" + # -- The flavour of tag you want to use + # There are different image flavours available, like distroless and ubi. + # Please see GitHub release notes for image tags for these flavors. + # By default, the distroless image is used. + flavour: "" + +# -- If set, install and upgrade CRDs through helm chart. +installCRDs: true + +crds: + # -- If true, create CRDs for Cluster External Secret. + createClusterExternalSecret: true + # -- If true, create CRDs for Cluster Secret Store. + createClusterSecretStore: true + # -- If true, create CRDs for Push Secret. + createPushSecret: true + annotations: {} + conversion: + enabled: true + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" +namespaceOverride: "" + +# -- Additional labels added to all helm chart resources. +commonLabels: {} + +# -- If true, external-secrets will perform leader election between instances to ensure no more +# than one instance of external-secrets operates at a time. +leaderElect: false + +# -- If set external secrets will filter matching +# Secret Stores with the appropriate controller values. +controllerClass: "" + +# -- If true external secrets will use recommended kubernetes +# annotations as prometheus metric labels. +extendedMetricLabels: false + +# -- If set external secrets are only reconciled in the +# provided namespace +scopedNamespace: "" + +# -- Must be used with scopedNamespace. If true, create scoped RBAC roles under the scoped namespace +# and implicitly disable cluster stores and cluster external secrets +scopedRBAC: false + +# -- if true, the operator will process cluster external secret. Else, it will ignore them. +processClusterExternalSecret: true + +# -- if true, the operator will process cluster store. Else, it will ignore them. +processClusterStore: true + +# -- if true, the operator will process push secret. Else, it will ignore them. +processPushSecret: true + +# -- Specifies whether an external secret operator deployment be created. +createOperator: true + +# -- Specifies the number of concurrent ExternalSecret Reconciles external-secret executes at +# a time. +concurrent: 1 +# -- Specifices Log Params to the Webhook +log: + level: info + timeEncoding: epoch +service: + # -- Set the ip family policy to configure dual-stack see [Configure dual-stack](https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services) + ipFamilyPolicy: "" + # -- Sets the families that should be supported and the order in which they should be applied to ClusterIP as well. Can be IPv4 and/or IPv6. + ipFamilies: [] + +serviceAccount: + # -- Specifies whether a service account should be created. + create: true + # -- Automounts the service account token in all containers of the pod + automount: true + # -- Annotations to add to the service account. + annotations: {} + # -- Extra Labels to add to the service account. + extraLabels: {} + # -- The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template. + name: "" + +rbac: + # -- Specifies whether role and rolebinding resources should be created. + create: true + + servicebindings: + # -- Specifies whether a clusterrole to give servicebindings read access should be created. + create: true + +## -- Extra environment variables to add to container. +extraEnv: [] + +## -- Map of extra arguments to pass to container. +extraArgs: {} + +## -- Extra volumes to pass to pod. +extraVolumes: [] + +## -- Extra Kubernetes objects to deploy with the helm chart +extraObjects: [] + +## -- Extra volumes to mount to the container. +extraVolumeMounts: [] + +## -- Extra containers to add to the pod. +extraContainers: [] + +# -- Annotations to add to Deployment +deploymentAnnotations: {} + +# -- Annotations to add to Pod +podAnnotations: {} + +podLabels: {} + +podSecurityContext: + enabled: true + # fsGroup: 2000 + +securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + enabled: true + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + seccompProfile: + type: RuntimeDefault + +resources: {} + # requests: + # cpu: 10m + # memory: 32Mi + +serviceMonitor: + # -- Specifies whether to create a ServiceMonitor resource for collecting Prometheus metrics + enabled: false + + # -- namespace where you want to install ServiceMonitors + namespace: "" + + # -- Additional labels + additionalLabels: {} + + # -- Interval to scrape metrics + interval: 30s + + # -- Timeout if metrics can't be retrieved in given time interval + scrapeTimeout: 25s + + # -- Let prometheus add an exported_ prefix to conflicting labels + honorLabels: false + + # -- Metric relabel configs to apply to samples before ingestion. [Metric Relabeling](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs) + metricRelabelings: [] + # - action: replace + # regex: (.*) + # replacement: $1 + # sourceLabels: + # - exported_namespace + # targetLabel: namespace + + # -- Relabel configs to apply to samples before ingestion. [Relabeling](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config) + relabelings: [] + # - sourceLabels: [__meta_kubernetes_pod_node_name] + # separator: ; + # regex: ^(.*)$ + # targetLabel: nodename + # replacement: $1 + # action: replace + +metrics: + + listen: + port: 8080 + + service: + # -- Enable if you use another monitoring tool than Prometheus to scrape the metrics + enabled: false + + # -- Metrics service port to scrape + port: 8080 + + # -- Additional service annotations + annotations: {} + +nodeSelector: {} + +tolerations: [] + +topologySpreadConstraints: [] + +affinity: {} + +# -- Pod priority class name. +priorityClassName: "" + +# -- Pod disruption budget - for more details see https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ +podDisruptionBudget: + enabled: false + minAvailable: 1 + # maxUnavailable: 1 + +# -- Run the controller on the host network +hostNetwork: false + +webhook: + # -- Specifies whether a webhook deployment be created. + create: true + # -- Specifices the time to check if the cert is valid + certCheckInterval: "5m" + # -- Specifices the lookaheadInterval for certificate validity + lookaheadInterval: "" + replicaCount: 1 + # -- Specifices Log Params to the Webhook + log: + level: info + timeEncoding: epoch + # -- Specifies the amount of historic ReplicaSets k8s should keep (see https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#clean-up-policy) + revisionHistoryLimit: 10 + + certDir: /tmp/certs + # -- Specifies whether validating webhooks should be created with failurePolicy: Fail or Ignore + failurePolicy: Fail + # -- Specifies if webhook pod should use hostNetwork or not. + hostNetwork: false + image: + repository: ghcr.io/external-secrets/external-secrets + pullPolicy: IfNotPresent + # -- The image tag to use. The default is the chart appVersion. + tag: "" + # -- The flavour of tag you want to use + flavour: "" + imagePullSecrets: [] + nameOverride: "" + fullnameOverride: "" + # -- The port the webhook will listen to + port: 10250 + rbac: + # -- Specifies whether role and rolebinding resources should be created. + create: true + serviceAccount: + # -- Specifies whether a service account should be created. + create: true + # -- Automounts the service account token in all containers of the pod + automount: true + # -- Annotations to add to the service account. + annotations: {} + # -- Extra Labels to add to the service account. + extraLabels: {} + # -- The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template. + name: "" + nodeSelector: {} + + certManager: + # -- Enabling cert-manager support will disable the built in secret and + # switch to using cert-manager (installed separately) to automatically issue + # and renew the webhook certificate. This chart does not install + # cert-manager for you, See https://cert-manager.io/docs/ + enabled: false + # -- Automatically add the cert-manager.io/inject-ca-from annotation to the + # webhooks and CRDs. As long as you have the cert-manager CA Injector + # enabled, this will automatically setup your webhook's CA to the one used + # by cert-manager. See https://cert-manager.io/docs/concepts/ca-injector + addInjectorAnnotations: true + cert: + # -- Create a certificate resource within this chart. See + # https://cert-manager.io/docs/usage/certificate/ + create: true + # -- For the Certificate created by this chart, setup the issuer. See + # https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.IssuerSpec + issuerRef: + group: cert-manager.io + kind: "Issuer" + name: "my-issuer" + # -- Set the requested duration (i.e. lifetime) of the Certificate. See + # https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificateSpec + # One year by default. + duration: "8760h" + # -- How long before the currently issued certificate’s expiry + # cert-manager should renew the certificate. See + # https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificateSpec + # Note that renewBefore should be greater than .webhook.lookaheadInterval + # since the webhook will check this far in advance that the certificate is + # valid. + renewBefore: "" + # -- Add extra annotations to the Certificate resource. + annotations: {} + + tolerations: [] + + topologySpreadConstraints: [] + + affinity: {} + + # -- Pod priority class name. + priorityClassName: "" + + # -- Pod disruption budget - for more details see https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + podDisruptionBudget: + enabled: false + minAvailable: 1 + # maxUnavailable: 1 + + metrics: + + listen: + port: 8080 + + service: + # -- Enable if you use another monitoring tool than Prometheus to scrape the metrics + enabled: false + + # -- Metrics service port to scrape + port: 8080 + + # -- Additional service annotations + annotations: {} + + + readinessProbe: + # -- Address for readiness probe + address: "" + # -- ReadinessProbe port for kubelet + port: 8081 + + + ## -- Extra environment variables to add to container. + extraEnv: [] + + ## -- Map of extra arguments to pass to container. + extraArgs: {} + + ## -- Extra volumes to pass to pod. + extraVolumes: [] + + ## -- Extra volumes to mount to the container. + extraVolumeMounts: [] + + # -- Annotations to add to Secret + secretAnnotations: {} + + # -- Annotations to add to Deployment + deploymentAnnotations: {} + + # -- Annotations to add to Pod + podAnnotations: {} + + podLabels: {} + + podSecurityContext: + enabled: true + # fsGroup: 2000 + + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + enabled: true + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + seccompProfile: + type: RuntimeDefault + + resources: {} + # requests: + # cpu: 10m + # memory: 32Mi + +certController: + # -- Specifies whether a certificate controller deployment be created. + create: true + requeueInterval: "5m" + replicaCount: 1 + # -- Specifices Log Params to the Webhook + log: + level: info + timeEncoding: epoch + # -- Specifies the amount of historic ReplicaSets k8s should keep (see https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#clean-up-policy) + revisionHistoryLimit: 10 + + image: + repository: ghcr.io/external-secrets/external-secrets + pullPolicy: IfNotPresent + tag: "" + flavour: "" + imagePullSecrets: [] + nameOverride: "" + fullnameOverride: "" + rbac: + # -- Specifies whether role and rolebinding resources should be created. + create: true + serviceAccount: + # -- Specifies whether a service account should be created. + create: true + # -- Automounts the service account token in all containers of the pod + automount: true + # -- Annotations to add to the service account. + annotations: {} + # -- Extra Labels to add to the service account. + extraLabels: {} + # -- The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template. + name: "" + nodeSelector: {} + + tolerations: [] + + topologySpreadConstraints: [] + + affinity: {} + + # -- Run the certController on the host network + hostNetwork: false + + # -- Pod priority class name. + priorityClassName: "" + + # -- Pod disruption budget - for more details see https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + podDisruptionBudget: + enabled: false + minAvailable: 1 + # maxUnavailable: 1 + + metrics: + + listen: + port: 8080 + + service: + # -- Enable if you use another monitoring tool than Prometheus to scrape the metrics + enabled: false + + # -- Metrics service port to scrape + port: 8080 + + # -- Additional service annotations + annotations: {} + + readinessProbe: + # -- Address for readiness probe + address: "" + # -- ReadinessProbe port for kubelet + port: 8081 + + ## -- Extra environment variables to add to container. + extraEnv: [] + + ## -- Map of extra arguments to pass to container. + extraArgs: {} + + + ## -- Extra volumes to pass to pod. + extraVolumes: [] + + ## -- Extra volumes to mount to the container. + extraVolumeMounts: [] + + # -- Annotations to add to Deployment + deploymentAnnotations: {} + + # -- Annotations to add to Pod + podAnnotations: {} + + podLabels: {} + + podSecurityContext: + enabled: true + # fsGroup: 2000 + + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + enabled: true + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + seccompProfile: + type: RuntimeDefault + + resources: {} + # requests: + # cpu: 10m + # memory: 32Mi + +# -- Specifies `dnsPolicy` to deployment +dnsPolicy: ClusterFirst + +# -- Specifies `dnsOptions` to deployment +dnsConfig: {} + +# -- Any extra pod spec on the deployment +podSpecExtra: {} diff --git a/backing-services/gitea/.helmignore b/backing-services/gitea/.helmignore new file mode 100644 index 0000000..43ad621 --- /dev/null +++ b/backing-services/gitea/.helmignore @@ -0,0 +1,41 @@ +# 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 +.gitmodules +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ +node_modules/ +.npmrc +package.json +package-lock.json +.gitea/ +Makefile +.markdownlintignore +.markdownlint.yaml +.drone.yml +CONTRIBUTING.md +unittests/ +.editorconfig +.prettierignore +.yamllint +CODEOWNERS +renovate.json5 +.commitlintrc.json +.gitsv/ diff --git a/backing-services/gitea/Chart.lock b/backing-services/gitea/Chart.lock new file mode 100644 index 0000000..6b2ab8c --- /dev/null +++ b/backing-services/gitea/Chart.lock @@ -0,0 +1,15 @@ +dependencies: +- name: postgresql + repository: oci://registry-1.docker.io/bitnamicharts + version: 16.7.27 +- name: postgresql-ha + repository: oci://registry-1.docker.io/bitnamicharts + version: 16.3.2 +- name: valkey-cluster + repository: oci://registry-1.docker.io/bitnamicharts + version: 3.0.24 +- name: valkey + repository: oci://registry-1.docker.io/bitnamicharts + version: 3.0.31 +digest: sha256:ceb6a1890cfdc2627abb85d3e2a4baa64d30afd21dcfabce978a824a67f0a2bb +generated: "2025-08-30T00:03:04.59764502Z" diff --git a/backing-services/gitea/Chart.yaml b/backing-services/gitea/Chart.yaml new file mode 100644 index 0000000..965c8ae --- /dev/null +++ b/backing-services/gitea/Chart.yaml @@ -0,0 +1,78 @@ +annotations: + artifacthub.io/changes: | + - kind: changed + description: update lockfiles (#950) + - kind: changed + description: update workflow dependencies (minor & patch) (#949) + - kind: changed + description: update dependency go-gitea/gitea to v1.24.6 (#948) + - kind: changed + description: update lockfiles (#947) + - kind: changed + description: update https://github.com/aws-actions/configure-aws-credentials action to v5 (#946) + - kind: changed + description: update lockfiles (#945) + - kind: changed + description: update actions/checkout action to v5 (#928) + - kind: changed + description: update workflow dependencies (minor & patch) (#943) + - kind: changed + description: update subcharts (minor & patch) (#942) + - kind: changed + description: update subcharts (minor & patch) (#941) + - kind: changed + description: update unittests/bash/test_helper/bats-support digest to 0954abb (#939) + - kind: changed + description: update alpine/helm docker tag to v3.18.5 (#940) + - kind: changed + description: update maintainers list - add ChristopherHX (#937) + - kind: changed + description: update maintainers list - DaanSelen (#936) + - kind: changed + description: update maintainers list - volker.raschek (#933) + - kind: changed + description: update maintainers list - rossigee (#932) +apiVersion: v2 +appVersion: 1.24.6 +dependencies: +- condition: postgresql.enabled + name: postgresql + repository: oci://registry-1.docker.io/bitnamicharts + version: 16.7.27 +- condition: postgresql-ha.enabled + name: postgresql-ha + repository: oci://registry-1.docker.io/bitnamicharts + version: 16.3.2 +- condition: valkey-cluster.enabled + name: valkey-cluster + repository: oci://registry-1.docker.io/bitnamicharts + version: 3.0.24 +- condition: valkey.enabled + name: valkey + repository: oci://registry-1.docker.io/bitnamicharts + version: 3.0.31 +description: Gitea Helm chart for Kubernetes +icon: https://gitea.com/assets/img/logo.svg +keywords: +- git +- issue tracker +- code review +- wiki +- gitea +- gogs +maintainers: +- email: ross@golder.org + name: Ross Golder +- email: markus.pesch+apps@cryptic.systems + name: Markus Pesch +- email: dselen@nerthus.nl + name: Daan Selen +- email: christopher.homberger@web.de + name: Christopher Homberger +name: gitea +sources: +- https://gitea.com/gitea/helm-gitea +- https://github.com/go-gitea/gitea +- https://docker.gitea.com/gitea +type: application +version: 12.3.0 diff --git a/backing-services/gitea/LICENSE b/backing-services/gitea/LICENSE new file mode 100644 index 0000000..bbf54de --- /dev/null +++ b/backing-services/gitea/LICENSE @@ -0,0 +1,24 @@ +MIT License + +Copyright (c) 2020 The Gitea Authors +Copyright (c) 2020 NOVUM-RGI +Copyright (c) 2019 - 2020 Charlie Drage +Copyright (c) 2018 John Felten + +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/backing-services/gitea/README.md b/backing-services/gitea/README.md new file mode 100644 index 0000000..e712bd7 --- /dev/null +++ b/backing-services/gitea/README.md @@ -0,0 +1,1608 @@ +# Gitea Helm Chart + +- [Introduction](#introduction) +- [Update and versioning policy](#update-and-versioning-policy) +- [Dependencies](#dependencies) + - [HA Dependencies](#ha-dependencies) + - [Non-HA Dependencies](#non-ha-dependencies) + - [Dependency Versioning](#dependency-versioning) +- [Installing](#installing) +- [High Availability](#high-availability) +- [Limit resources](#limit-resources) +- [Configuration](#configuration) + - [Default Configuration](#default-configuration) + - [Database defaults](#database-defaults) + - [Server defaults](#server-defaults) + - [Metrics defaults](#metrics-defaults) + - [Rootless Defaults](#rootless-defaults) + - [Session, Cache and Queue](#session-cache-and-queue) + - [Single-Pod Configurations](#single-pod-configurations) + - [Additional _app.ini_ settings](#additional-appini-settings) + - [User defined environment variables in app.ini](#user-defined-environment-variables-in-appini) + - [External Database](#external-database) + - [Ports and external url](#ports-and-external-url) + - [ClusterIP](#clusterip) + - [SSH and Ingress](#ssh-and-ingress) + - [SSH on crio based kubernetes cluster](#ssh-on-crio-based-kubernetes-cluster) + - [Cache](#cache) + - [Persistence](#persistence) + - [Admin User](#admin-user) + - [LDAP Settings](#ldap-settings) + - [OAuth2 Settings](#oauth2-settings) +- [Configure commit signing](#configure-commit-signing) +- [Metrics and profiling](#metrics-and-profiling) + - [Secure Metrics Endpoint](#secure-metrics-endpoint) +- [Pod annotations](#pod-annotations) +- [TLS certificate rotation](#tls-certificate-rotation) +- [Themes](#themes) +- [Renovate](#renovate) +- [Parameters](#parameters) + - [Global](#global) + - [strategy](#strategy) + - [Image](#image) + - [Security](#security) + - [Service](#service) + - [Ingress](#ingress) + - [deployment](#deployment) + - [ServiceAccount](#serviceaccount) + - [Persistence](#persistence-1) + - [Init](#init) + - [Signing](#signing) + - [Gitea](#gitea) + - [LivenessProbe](#livenessprobe) + - [ReadinessProbe](#readinessprobe) + - [StartupProbe](#startupprobe) + - [valkey-cluster](#valkey-cluster) + - [valkey](#valkey) + - [PostgreSQL HA](#postgresql-ha) + - [PostgreSQL](#postgresql) + - [Advanced](#advanced) +- [Contributing](#contributing) +- [Upgrading](#upgrading) + +[Gitea](https://gitea.com) is a community managed lightweight code hosting solution written in Go. +It is published under the MIT license. + +## Introduction + +This helm chart has taken some inspiration from [jfelten's helm chart](https://github.com/jfelten/gitea-helm-chart). +Yet it takes a completely different approach in providing a database and cache with dependencies. +Additionally, this chart allows to provide LDAP and admin user configuration with values. + +## Update and versioning policy + +The Gitea helm chart versioning does not follow Gitea's versioning. +The latest chart version can be looked up in [https://dl.gitea.com/charts](https://dl.gitea.com/charts) or in the [repository releases](https://gitea.com/gitea/helm-gitea/releases). + +The chart aims to follow Gitea's releases closely. +There might be times when the chart is behind the latest Gitea release. +This might be caused by different reasons, most often due to time constraints of the maintainers (remember, all work here is done voluntarily in the spare time of people). +If you're eager to use the latest Gitea version earlier than this chart catches up, then change the tag in `values.yaml` to the latest Gitea version. +Note that besides the exact Gitea version one can also use the `:1` tag to automatically follow the latest Gitea version. +This should be combined with `image.pullPolicy: "Always"`. +Important: Using the `:1` will also automatically jump to new minor release (e.g. from 1.13 to 1.14) which may eventually cause incompatibilities if major/breaking changes happened between these versions. +This is due to Gitea not strictly following [semantic versioning](https://semver.org/#summary) as breaking changes do not increase the major version. +I.e., "minor" version bumps are considered "major". +Yet most often no issues will be encountered and the chart maintainers aim to communicate early/upfront if this would be the case. + +## Dependencies + +Gitea is most performant when run with an external database and cache. +This chart provides those dependencies via sub-charts. +Users can also configure their own external providers via the configuration. + +### HA Dependencies + +These dependencies are enabled by default: + +- PostgreSQL HA ([Bitnami PostgreSQL-HA](https://github.com/bitnami/charts/blob/main/bitnami/postgresql-ha/Chart.yaml)) +- Valkey-Cluster ([Bitnami Valkey-Cluster](https://github.com/bitnami/charts/blob/main/bitnami/valkey-cluster/Chart.yaml)) + +### Non-HA Dependencies + +Alternatively, the following non-HA replacements are available: + +- PostgreSQL ([Bitnami PostgreSQL](https://github.com/bitnami/charts/blob/main/bitnami/postgresql/Chart.yaml)) +- Valkey ([Bitnami Valkey](https://github.com/bitnami/charts/blob/main/bitnami/valkey/Chart.yaml)) + +### Dependency Versioning + +Updates of sub-charts will be incorporated into the Gitea chart as they are released. +The reasoning behind this is that new users of the chart will start with the most recent sub-chart dependency versions. + +**Note** If you want to stay on an older appVersion of a sub-chart dependency (e.g. PostgreSQL), you need to override the image tag in your `values.yaml` file. +In fact, we recommend to do so right from the start to be independent of major sub-chart dependency changes as they are released. +There is no need to update to every new PostgreSQL major version - you can happily skip some and do larger updates when you are ready for them. + +We recommend to use a rolling tag like `:-debian-` to incorporate minor and patch updates for the respective major version as they are released. +Alternatively you can also use a versioning helper tool like [renovate](https://github.com/renovatebot/renovate). + +Please double-check the image repository and available tags in the sub-chart: + +- [PostgreSQL-HA](https://hub.docker.com/r/bitnami/postgresql-repmgr/tags) +- [PostgreSQL](https://hub.docker.com/r/bitnami/postgresql/tags) +- [Valkey Cluster](https://hub.docker.com/r/bitnami/valkey-cluster/tags) +- [Valkey](https://hub.docker.com/r/bitnami/valkey/tags) + +and look up the image tag which fits your needs on Dockerhub. + +## Installing + +```sh +helm repo add gitea-charts https://dl.gitea.com/charts/ +helm repo update +helm install gitea gitea-charts/gitea +``` + +Alternatively, the chart can also be installed from Dockerhub (since v9.6.0) + +```sh +helm install gitea oci://registry-1.docker.io/giteacharts/gitea +``` + +To avoid potential Dockerhub rate limits, the chart can also be installed via [docker.gitea.com](https://blog.gitea.com/docker-registry-update/) (since v9.6.0) + +```sh +helm install gitea oci://docker.gitea.com/charts/gitea +``` + +When upgrading, please refer to the [Upgrading](#upgrading) section at the bottom of this document for major and breaking changes. + +## High Availability + +Since version 9.0.0 this chart supports running Gitea and it's dependencies in HA mode. +Care must be taken for production use as not all implementation details of Gitea core are officially HA-ready yet. + +Deploying a HA-ready Gitea instance requires some effort including using HA-ready dependencies. +See the [HA Setup](docs/ha-setup.md) document for more details. + +## Limit resources + +If the application is deployed with a CPU resource limit, Prometheus may throw a CPU throttling warning for the +application. This has more or less to do with the fact that the application finds the number of CPUs of the host, but +cannot use the available CPU time to perform computing operations. + +The application must be informed that despite several CPUs only a part (limit) of the available computing time is +available. As this is a Golang application, this can be implemented using `GOMAXPROCS`. The following example is one way +of defining `GOMAXPROCS` automatically based on the defined CPU limit like `1000m`. Please keep in mind, that the CFS +rate of `100ms` - default on each kubernetes node, is also very important to avoid CPU throttling. + +Further information about this topic can be found [under this link](https://kanishk.io/posts/cpu-throttling-in-containerized-go-apps/). + +> [!NOTE] +> The environment variable `GOMAXPROCS` is set automatically, when a CPU limit is defined. An explicit configuration is +> not anymore required. +> +> Please note that a CPU limit < `1000m` can also lead to CPU throttling. Please read the linked documentation carefully. + +```yaml +deployment: + env: + # Will be automatically defined! + - name: GOMAXPROCS + valueFrom: + resourceFieldRef: + divisor: "1" # Is required for GitDevOps systems like ArgoCD/Flux. Otherwise throw the system a diff error. (k8s-default=1) + resource: limits.cpu + +resources: + limits: + cpu: 1000m + memory: 512Mi + requests: + cpu: 100m + memory: 512Mi +``` + +## Configuration + +Gitea offers lots of configuration options. +This is fully described in the [Gitea Cheat Sheet](https://docs.gitea.com/administration/config-cheat-sheet). + +```yaml +gitea: + config: + APP_NAME: "Gitea: With a cup of tea." + repository: + ROOT: "~/gitea-repositories" + repository.pull-request: + WORK_IN_PROGRESS_PREFIXES: "WIP:,[WIP]:" +``` + +### Default Configuration + +This chart will set a few defaults in the Gitea configuration based on the service and ingress settings. +All defaults can be overwritten in `gitea.config`. + +INSTALL_LOCK is always set to true, since we want to configure Gitea with this helm chart and everything is taken care of. + +_All default settings are made directly in the generated `app.ini`, not in the Values._ + +#### Database defaults + +If a builtIn database is enabled the database configuration is set automatically. +For example, PostgreSQL builtIn will appear in the `app.ini` as: + +```ini +[database] +DB_TYPE = postgres +HOST = RELEASE-NAME-postgresql.default.svc.cluster.local:5432 +NAME = gitea +PASSWD = gitea +USER = gitea +``` + +#### Server defaults + +The server defaults are a bit more complex. +If ingress is `enabled`, the `ROOT_URL`, `DOMAIN` and `SSH_DOMAIN` will be set accordingly. +`HTTP_PORT` always defaults to `3000` as well as `SSH_PORT` to `22`. + +```ini +[server] +APP_DATA_PATH = /data +DOMAIN = git.example.com +HTTP_PORT = 3000 +PROTOCOL = http +ROOT_URL = http://git.example.com +SSH_DOMAIN = git.example.com +SSH_LISTEN_PORT = 22 +SSH_PORT = 22 +ENABLE_PPROF = false +``` + +#### Metrics defaults + +The Prometheus `/metrics` endpoint is disabled by default. + +```ini +[metrics] +ENABLED = false +``` + +#### Rootless Defaults + +If `.Values.image.rootless: true`, then the following will occur. In case you use `.Values.image.fullOverride`, check that this works in your image: + +- `$HOME` becomes `/data/gitea/git` + + [see deployment.yaml](./templates/gitea/deployment.yaml) template inside (init-)container "env" declarations + +- `START_SSH_SERVER: true` (Unless explicity overwritten by `gitea.config.server.START_SSH_SERVER`) + + [see \_helpers.tpl](./templates/_helpers.tpl) in `gitea.inline_configuration.defaults.server` definition + +- `SSH_LISTEN_PORT: 2222` (Unless explicity overwritten by `gitea.config.server.SSH_LISTEN_PORT`) + + [see \_helpers.tpl](./templates/_helpers.tpl) in `gitea.inline_configuration.defaults.server` definition + +- `SSH_LOG_LEVEL` environment variable is not injected into the container + + [see deployment.yaml](./templates/gitea/deployment.yaml) template inside container "env" declarations + +#### Session, Cache and Queue + +The session, cache and queue settings are set to use the built-in Valkey Cluster sub-chart dependency. +If Valkey Cluster is disabled, the chart will fall back to the Gitea defaults which use "memory" for `session` and `cache` and "level" for `queue`. + +While these will work and even not cause immediate issues after startup, **they are not recommended for production use**. +Reasons being that a single pod will take on all the work for `session` and `cache` tasks in its available memory. +It is likely that the pod will run out of memory or will face substantial memory spikes, depending on the workload. +External tools such as `valkey-cluster` or `memcached` handle these workloads much better. + +### Single-Pod Configurations + +If HA is not needed/desired, the following configurations can be used to deploy a single-pod Gitea instance. + +1. For a production-ready single-pod Gitea instance without external dependencies (using the chart dependency `postgresql` and `valkey`): + +
+ + values.yml + + ```yaml + valkey-cluster: + enabled: false + valkey: + enabled: true + postgresql: + enabled: true + postgresql-ha: + enabled: false + + persistence: + enabled: true + + gitea: + config: + database: + DB_TYPE: postgres + indexer: + ISSUE_INDEXER_TYPE: bleve + REPO_INDEXER_ENABLED: true + ``` + +
+ +2. For a minimal DEV installation (using the built-in sqlite DB instead of Postgres): + + This will result in a single-pod Gitea instance _without any dependencies and persistence_. + **Do not use this configuration for production use**. + +
+ + values.yml + + ```yaml + valkey-cluster: + enabled: false + valkey: + enabled: false + postgresql: + enabled: false + postgresql-ha: + enabled: false + + persistence: + enabled: false + + gitea: + config: + database: + DB_TYPE: sqlite3 + session: + PROVIDER: memory + cache: + ADAPTER: memory + queue: + TYPE: level + ``` + +
+ +### Additional _app.ini_ settings + +> **The [generic](https://docs.gitea.com/administration/config-cheat-sheet#overall-default) +> section cannot be defined that way.** + +Some settings inside _app.ini_ (like passwords or whole authentication configurations) must be considered sensitive and therefore should not be passed via plain text inside the _values.yaml_ file. +In times of _GitOps_ the values.yaml could be stored in a Git repository where sensitive data should never be accessible. + +The Helm Chart supports this approach and let the user define custom sources like +Kubernetes Secrets to be loaded as environment variables during _app.ini_ creation or update. + +```yaml +gitea: + additionalConfigSources: + - secret: + secretName: gitea-app-ini-oauth + - configMap: + name: gitea-app-ini-plaintext +``` + +This would mount the two additional volumes (`oauth` and `some-additionals`) from different sources to the init container where the _app.ini_ gets updated. +All files mounted that way will be read and converted to environment variables and then added to the _app.ini_ using [environment-to-ini](https://github.com/go-gitea/gitea/tree/main/contrib/environment-to-ini). + +The key of such additional source represents the section inside the _app.ini_. +The value for each key can be multiline ini-like definitions. + +In example, the referenced `gitea-app-ini-plaintext` could look like this. + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: gitea-app-ini-plaintext +data: + session: | + PROVIDER=memory + SAME_SITE=strict + cron.archive_cleanup: | + ENABLED=true +``` + +Or when using a Kubernetes secret, having the same data structure: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: gitea-security-related-configuration +type: Opaque +stringData: + security: | + PASSWORD_COMPLEXITY=off + session: | + SAME_SITE=strict +``` + +#### User defined environment variables in app.ini + +Users are able to define their own environment variables, which are loaded into the containers. +We also support to directly interact with the generated _app.ini_. + +To inject self defined variables into the _app.ini_ a certain format needs to be honored. +This is described in detail on the [env-to-ini](https://github.com/go-gitea/gitea/tree/main/contrib/environment-to-ini) page. + +Prior to Gitea 1.20 and Chart 9.0.0 the helm chart had a custom prefix `ENV_TO_INI`. +After the support for a custom prefix was removed in Gite core, the prefix was changed to `GITEA`. + +For example a database setting needs to have the following format: + +```yaml +gitea: + additionalConfigFromEnvs: + - name: GITEA__DATABASE__HOST + value: my.own.host + - name: GITEA__DATABASE__PASSWD + valueFrom: + secretKeyRef: + name: postgres-secret + key: password +``` + +Priority (highest to lowest) for defining app.ini variables: + +1. Environment variables prefixed with `GITEA` +1. Additional config sources +1. Values defined in `gitea.config` + +### External Database + +Any external database listed in [https://docs.gitea.com/installation/database-prep](https://docs.gitea.com/installation/database-prep) can be used instead of the built-in PostgreSQL. +In fact, it is **highly recommended** to use an external database to ensure a stable Gitea installation longterm. + +If an external database is used, no matter which type, make sure to set `postgresql.enabled` to `false` to disable the use of the built-in PostgreSQL. + +```yaml +gitea: + config: + database: + DB_TYPE: mysql + HOST: + NAME: gitea + USER: root + PASSWD: gitea + SCHEMA: gitea + +postgresql: + enabled: false + +postgresql-ha: + enabled: false +``` + +### Ports and external url + +By default port `3000` is used for web traffic and `22` for ssh. +Those can be changed: + +```yaml +service: + http: + port: 3000 + ssh: + port: 22 +``` + +This helm chart automatically configures the clone urls to use the correct ports. +You can change these ports by hand using the `gitea.config` dict. +However you should know what you're doing. + +### ClusterIP + +By default the `clusterIP` will be set to `None`, which is the default for headless services. +However if you want to omit the clusterIP field in the service, use the following values: + +```yaml +service: + http: + type: ClusterIP + port: 3000 + clusterIP: + ssh: + type: ClusterIP + port: 22 + clusterIP: +``` + +### SSH and Ingress + +If you're using ingress and want to use SSH, keep in mind, that ingress is not able to forward SSH Ports. +You will need a LoadBalancer like `metallb` and a setting in your ssh service annotations. + +```yaml +service: + ssh: + annotations: + metallb.universe.tf/allow-shared-ip: test +``` + +### SSH on crio based kubernetes cluster + +If you use `crio` as container runtime it is not possible to read from a remote repository. +You should get an error message like this: + +```bash +$ git clone git@k8s-demo.internal:admin/test.git +Cloning into 'test'... +Connection reset by 192.168.179.217 port 22 +fatal: Could not read from remote repository. + +Please make sure you have the correct access rights +and the repository exists. +``` + +To solve this problem add the capability `SYS_CHROOT` to the `securityContext`. +More about this issue [under this link](https://gitea.com/gitea/helm-gitea/issues/161). + +### Cache + +The cache handling is done via `valkey-cluster` (via the `bitnami` chart) by default. +This deployment is HA-ready but can also be used for single-pod deployments. +By default, 6 replicas are deployed for a working `valkey-cluster` deployment. +Many cloud providers offer a managed valkey service, which can be used instead of the built-in `valkey-cluster`. + +```yaml +valkey-cluster: + enabled: true +``` + +⚠️ The valkey charts [do not work well with special characters in the password](https://gitea.com/gitea/helm-chart/issues/690). +Consider omitting such or open an issue in the Bitnami repo and let us know once this got fixed. + +### Persistence + +Gitea will be deployed as a deployment. +By simply enabling the persistence and setting the storage class according to your cluster everything else will be taken care of. +The following example will create a PVC as a part of the deployment. + +Please note, that an empty `storageClass` in the persistence will result in kubernetes using your default storage class. + +If you want to use your own storage class define it as follows: + +```yaml +persistence: + enabled: true + storageClass: myOwnStorageClass +``` + +If you want to manage your own PVC you can simply pass the PVC name to the chart. + +```yaml +persistence: + enabled: true + claimName: MyAwesomeGiteaClaim +``` + +In case that persistence has been disabled it will simply use an empty dir volume. + +PostgreSQL handles the persistence in the exact same way. +You can interact with the postgres settings as displayed in the following example: + +```yaml +postgresql: + persistence: + enabled: true + existingClaim: MyAwesomeGiteaPostgresClaim +``` + +### Admin User + +This chart enables you to create a default admin user. +It is also possible to update the password for this user by upgrading or redeploying the chart. +It is not possible to delete an admin user after it has been created. +This has to be done in the ui. +You cannot use `admin` as username. + +```yaml +gitea: + admin: + username: "MyAwesomeGiteaAdmin" + password: "AReallyAwesomeGiteaPassword" + email: "gi@tea.com" +``` + +You can also use an existing Secret to configure the admin user: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: gitea-admin-secret +type: Opaque +stringData: + username: MyAwesomeGiteaAdmin + password: AReallyAwesomeGiteaPassword +``` + +```yaml +gitea: + admin: + existingSecret: gitea-admin-secret +``` + +Whether you use the existing Secret or specify a user name and password, there are three modes for how the admin user password is created or set. + +- `keepUpdated` (the default) will set the admin user password, and reset it to the defined value every time the pod is recreated. +- `initialOnlyNoReset` will set the admin user password when creating it, but never try to update the password. +- `initialOnlyRequireReset` will set the admin user password when creating it, never update it, and require that the password be changed at the initial login. + +These modes can be set like the following: + +```yaml +gitea: + admin: + passwordMode: initialOnlyRequireReset +``` + +### LDAP Settings + +Like the admin user the LDAP settings can be updated. +All LDAP values from are available. + +Multiple LDAP sources can be configured with additional LDAP list items. + +```yaml +gitea: + ldap: + - name: MyAwesomeGiteaLdap + securityProtocol: unencrypted + host: "127.0.0.1" + port: "389" + userSearchBase: ou=Users,dc=example,dc=com + userFilter: sAMAccountName=%s + adminFilter: CN=Admin,CN=Group,DC=example,DC=com + emailAttribute: mail + bindDn: CN=ldap read,OU=Spezial,DC=example,DC=com + bindPassword: JustAnotherBindPw + usernameAttribute: CN + publicSSHKeyAttribute: publicSSHKey +``` + +You can also use an existing secret to set the `bindDn` and `bindPassword`: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: gitea-ldap-secret +type: Opaque +stringData: + bindDn: CN=ldap read,OU=Spezial,DC=example,DC=com + bindPassword: JustAnotherBindPw +``` + +```yaml +gitea: + ldap: + - existingSecret: gitea-ldap-secret + ... +``` + +⚠️ Some options are just flags and therefore don't have any values. +If they are defined in `gitea.ldap` configuration, they will be passed to the Gitea CLI without any value. +Affected options: + +- notActive +- skipTlsVerify +- allowDeactivateAll +- synchronizeUsers +- attributesInBind + +### OAuth2 Settings + +Like the admin user, OAuth2 settings can be updated and disabled but not deleted. +Deleting OAuth2 settings has to be done in the ui. +All OAuth2 values, which are documented [under this link](https://docs.gitea.com/administration/command-line#admin), are +available. + +Multiple OAuth2 sources can be configured with additional OAuth list items. + +```yaml +gitea: + oauth: + - name: "MyAwesomeGiteaOAuth" + provider: "openidConnect" + key: "hello" + secret: "world" + autoDiscoverUrl: "https://gitea.example.com/.well-known/openid-configuration" + #useCustomUrls: + #customAuthUrl: + #customTokenUrl: + #customProfileUrl: + #customEmailUrl: +``` + +You can also use an existing secret to set the `key` and `secret`: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: gitea-oauth-secret +type: Opaque +stringData: + key: hello + secret: world +``` + +```yaml +gitea: + oauth: + - name: "MyAwesomeGiteaOAuth" + existingSecret: gitea-oauth-secret + ... +``` + +## Configure commit signing + +When using the rootless image the gpg key folder is not persistent by default. +If you consider using signed commits for internal Gitea activities (e.g. initial commit), you'd need to provide a signing key. +Prior to [PR186](https://gitea.com/gitea/helm-gitea/pulls/186), imported keys had to be re-imported once the container got replaced by another. + +The mentioned PR introduced a new configuration object `signing` allowing you to configure prerequisites for commit signing. +By default this section is disabled to maintain backwards compatibility. + +```yaml +signing: + enabled: false + gpgHome: /data/git/.gnupg +``` + +Regardless of the used container image the `signing` object allows to specify a private gpg key. +Either using the `signing.privateKey` to define the key inline, or refer to an existing secret containing the key data by using `signing.existingSecret`. + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: custom-gitea-gpg-key +type: Opaque +stringData: + privateKey: |- + -----BEGIN PGP PRIVATE KEY BLOCK----- + ... + -----END PGP PRIVATE KEY BLOCK----- +``` + +```yaml +signing: + existingSecret: custom-gitea-gpg-key +``` + +To use the gpg key, Gitea needs to be configured accordingly. +A detailed description can be found in the [official Gitea documentation](https://docs.gitea.com/administration/signing#general-configuration). + +## Metrics and profiling + +A Prometheus `/metrics` endpoint on the `HTTP_PORT` and `pprof` profiling endpoints on port 6060 can be enabled under `gitea`. +Beware that the metrics endpoint is exposed via the ingress, manage access using ingress annotations for example. + +To deploy the `ServiceMonitor`, you first need to ensure that you have deployed `prometheus-operator` and its [CRDs](https://github.com/prometheus-operator/prometheus-operator#customresourcedefinitions). + +```yaml +gitea: + metrics: + enabled: true + serviceMonitor: + enabled: true + + config: + server: + ENABLE_PPROF: true +``` + +### Secure Metrics Endpoint + +Metrics endpoint `/metrics` can be secured by using `Bearer` token authentication. + +**Note:** Providing non-empty `TOKEN` value will also require authentication for `ServiceMonitor`. + +```yaml +gitea: + metrics: + token: "secure-token" + enabled: true + serviceMonitor: + enabled: true +``` + +## Pod annotations + +Annotations can be added to the Gitea pod. + +```yaml +gitea: + podAnnotations: {} +``` + +## TLS certificate rotation + +If Gitea uses TLS certificates that are mounted as a secret in the container file system, Gitea will not automatically apply them when the TLS certificates are rotated. +Such a rotation can be for example triggered, when the cert-manager issues new TLS certificates before expiring. Further information is described as GitHub +[issue](https://github.com/go-gitea/gitea/issues/27962). + +Until the issue is present, a workaround can be applied. +For example stakater's [reloader](https://github.com/stakater/Reloader) controller can be used to trigger a rolling update. +The following annotation must be added to instruct the reloader controller to trigger a rolling update, when the mounted `configMaps` and `secrets` have been changed. + +```yaml +deployment: + annotations: + reloader.stakater.com/auto: "true" +``` + +Instead of triggering a rolling update for configMap and secret resources, this action can also be defined for individual items. +For example, when the secret named `gitea-tls` is mounted and the reloader controller should only listen for changes of this secret: + +```yaml +deployment: + annotations: + secret.reloader.stakater.com/reload: "gitea-tls" +``` + +## Themes + +Custom themes can be added via k8s secrets and referencing them in `values.yaml`. + +The [http provider](https://registry.terraform.io/providers/hashicorp/http/latest/docs/data-sources/http) is useful here. + +```yaml +extraVolumes: + - name: gitea-themes + secret: + secretName: gitea-themes + +extraVolumeMounts: + - name: gitea-themes + readOnly: true + mountPath: "/data/gitea/public/assets/css" +``` + +The secret can be created via `terraform`: + +```hcl +resource "kubernetes_secret" "gitea-themes" { + metadata { + name = "gitea-themes" + namespace = "gitea" + } + + data = { + "my-theme.css" = data.http.gitea-theme-light.body + "my-theme-dark.css" = data.http.gitea-theme-dark.body + "my-theme-auto.css" = data.http.gitea-theme-auto.body + } + + type = "Opaque" +} + + +data "http" "gitea-theme-light" { + url = "" + + request_headers = { + Accept = "application/json" + } +} + +data "http" "gitea-theme-dark" { + url = "" + + request_headers = { + Accept = "application/json" + } +} + +data "http" "gitea-theme-auto" { + url = "" + + request_headers = { + Accept = "application/json" + } +} +``` + +or natively via `kubectl`: + +```bash +kubectl create secret generic gitea-themes --from-file={{FULL-PATH-TO-CSS}} --namespace gitea +``` + +## Renovate + +To be able to use a digest value which is automatically updated by `Renovate` a [customManager](https://docs.renovatebot.com/modules/manager/regex/) is required. +Here's an examplary `values.yml` definition which makes use of a digest: + +```yaml +image: + repository: gitea/gitea + tag: 1.20.2 + digest: sha256:6e3b85a36653894d6741d0aefb41dfaac39044e028a42e0a520cc05ebd7bfc3f +``` + +By default Renovate adds digest after the `tag`. +To comply with the Gitea helm chart definition of the digest parameter, a "customManagers" definition is required: + +```json +"customManagers": [ + { + "customType": "regex", + "description": "Apply an explicit gitea digest field match", + "fileMatch": ["values\\.ya?ml"], + "matchStrings": ["(?gitea\\/gitea)\\n(?\\s+)tag: (?[^@].*?)\\n\\s+digest: (?sha256:[a-f0-9]+)"], + "datasourceTemplate": "docker", + "autoReplaceStringTemplate": "{{depName}}\n{{indentation}}tag: {{newValue}}\n{{indentation}}digest: {{#if newDigest}}{{{newDigest}}}{{else}}{{{currentDigest}}}{{/if}}" + } +] +``` + +## Parameters + +### Global + +| Name | Description | Value | +| ------------------------- | ---------------------------------------------------------------------------------------------- | ----- | +| `global.imageRegistry` | global image registry override | `""` | +| `global.imagePullSecrets` | global image pull secrets override; can be extended by `imagePullSecrets` | `[]` | +| `global.storageClass` | global storage class override | `""` | +| `global.hostAliases` | global hostAliases which will be added to the pod's hosts files | `[]` | +| `namespace` | An explicit namespace to deploy Gitea into. Defaults to the release namespace if not specified | `""` | +| `replicaCount` | number of replicas for the deployment | `1` | + +### strategy + +| Name | Description | Value | +| --------------------------------------- | -------------- | --------------- | +| `strategy.type` | strategy type | `RollingUpdate` | +| `strategy.rollingUpdate.maxSurge` | maxSurge | `100%` | +| `strategy.rollingUpdate.maxUnavailable` | maxUnavailable | `0` | +| `clusterDomain` | cluster domain | `cluster.local` | + +### Image + +| Name | Description | Value | +| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | +| `image.registry` | image registry, e.g. gcr.io,docker.io | `docker.gitea.com` | +| `image.repository` | Image to start for this pod | `gitea` | +| `image.tag` | Visit: [Image tag](https://hub.docker.com/r/gitea/gitea/tags?page=1&ordering=last_updated). Defaults to `appVersion` within Chart.yaml. | `""` | +| `image.digest` | Image digest. Allows to pin the given image tag. Useful for having control over mutable tags like `latest` | `""` | +| `image.pullPolicy` | Image pull policy | `IfNotPresent` | +| `image.rootless` | Wether or not to pull the rootless version of Gitea, only works on Gitea 1.14.x or higher | `true` | +| `image.fullOverride` | Completely overrides the image registry, path/image, tag and digest. **Adjust `image.rootless` accordingly and review [Rootless defaults](#rootless-defaults).** | `""` | +| `imagePullSecrets` | Secret to use for pulling the image | `[]` | + +### Security + +| Name | Description | Value | +| ---------------------------- | --------------------------------------------------------------- | ------ | +| `podSecurityContext.fsGroup` | Set the shared file system group for all containers in the pod. | `1000` | +| `containerSecurityContext` | Security context | `{}` | +| `securityContext` | Run init and Gitea containers as a specific securityContext | `{}` | +| `podDisruptionBudget` | Pod disruption budget | `{}` | + +### Service + +| Name | Description | Value | +| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | +| `service.http.type` | Kubernetes service type for web traffic | `ClusterIP` | +| `service.http.port` | Port number for web traffic | `3000` | +| `service.http.clusterIP` | ClusterIP setting for http autosetup for deployment is None | `None` | +| `service.http.loadBalancerIP` | LoadBalancer IP setting | `nil` | +| `service.http.nodePort` | NodePort for http service | `nil` | +| `service.http.externalTrafficPolicy` | If `service.http.type` is `NodePort` or `LoadBalancer`, set this to `Local` to enable source IP preservation | `nil` | +| `service.http.externalIPs` | External IPs for service | `nil` | +| `service.http.ipFamilyPolicy` | HTTP service dual-stack policy | `nil` | +| `service.http.ipFamilies` | HTTP service dual-stack familiy selection,for dual-stack parameters see official kubernetes [dual-stack concept documentation](https://kubernetes.io/docs/concepts/services-networking/dual-stack/). | `nil` | +| `service.http.loadBalancerSourceRanges` | Source range filter for http loadbalancer | `[]` | +| `service.http.annotations` | HTTP service annotations | `{}` | +| `service.http.labels` | HTTP service additional labels | `{}` | +| `service.http.loadBalancerClass` | Loadbalancer class | `nil` | +| `service.ssh.type` | Kubernetes service type for ssh traffic | `ClusterIP` | +| `service.ssh.port` | Port number for ssh traffic | `22` | +| `service.ssh.clusterIP` | ClusterIP setting for ssh autosetup for deployment is None | `None` | +| `service.ssh.loadBalancerIP` | LoadBalancer IP setting | `nil` | +| `service.ssh.nodePort` | NodePort for ssh service | `nil` | +| `service.ssh.externalTrafficPolicy` | If `service.ssh.type` is `NodePort` or `LoadBalancer`, set this to `Local` to enable source IP preservation | `nil` | +| `service.ssh.externalIPs` | External IPs for service | `nil` | +| `service.ssh.ipFamilyPolicy` | SSH service dual-stack policy | `nil` | +| `service.ssh.ipFamilies` | SSH service dual-stack familiy selection,for dual-stack parameters see official kubernetes [dual-stack concept documentation](https://kubernetes.io/docs/concepts/services-networking/dual-stack/). | `nil` | +| `service.ssh.hostPort` | HostPort for ssh service | `nil` | +| `service.ssh.loadBalancerSourceRanges` | Source range filter for ssh loadbalancer | `[]` | +| `service.ssh.annotations` | SSH service annotations | `{}` | +| `service.ssh.labels` | SSH service additional labels | `{}` | +| `service.ssh.loadBalancerClass` | Loadbalancer class | `nil` | + +### Ingress + +| Name | Description | Value | +| -------------------------------- | ------------------------------- | ----------------- | +| `ingress.enabled` | Enable ingress | `false` | +| `ingress.className` | DEPRECATED: Ingress class name. | `""` | +| `ingress.pathType` | Ingress Path Type | `Prefix` | +| `ingress.annotations` | Ingress annotations | `{}` | +| `ingress.hosts[0].host` | Default Ingress host | `git.example.com` | +| `ingress.hosts[0].paths[0].path` | Default Ingress path | `/` | +| `ingress.tls` | Ingress tls settings | `[]` | + +### deployment + +| Name | Description | Value | +| ------------------------------------------ | ------------------------------------------------------ | ----- | +| `resources` | Kubernetes resources | `{}` | +| `schedulerName` | Use an alternate scheduler, e.g. "stork" | `""` | +| `nodeSelector` | NodeSelector for the deployment | `{}` | +| `tolerations` | Tolerations for the deployment | `[]` | +| `affinity` | Affinity for the deployment | `{}` | +| `topologySpreadConstraints` | TopologySpreadConstraints for the deployment | `[]` | +| `dnsConfig` | dnsConfig for the deployment | `{}` | +| `priorityClassName` | priorityClassName for the deployment | `""` | +| `deployment.env` | Additional environment variables to pass to containers | `[]` | +| `deployment.terminationGracePeriodSeconds` | How long to wait until forcefully kill the pod | `60` | +| `deployment.labels` | Labels for the deployment | `{}` | +| `deployment.annotations` | Annotations for the Gitea deployment to be created | `{}` | + +### ServiceAccount + +| Name | Description | Value | +| --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `serviceAccount.create` | Enable the creation of a ServiceAccount | `false` | +| `serviceAccount.name` | Name of the created ServiceAccount, defaults to release name. Can also link to an externally provided ServiceAccount that should be used. | `""` | +| `serviceAccount.automountServiceAccountToken` | Enable/disable auto mounting of the service account token | `false` | +| `serviceAccount.imagePullSecrets` | Image pull secrets, available to the ServiceAccount | `[]` | +| `serviceAccount.annotations` | Custom annotations for the ServiceAccount | `{}` | +| `serviceAccount.labels` | Custom labels for the ServiceAccount | `{}` | + +### Persistence + +| Name | Description | Value | +| ------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ---------------------- | +| `persistence.enabled` | Enable persistent storage | `true` | +| `persistence.create` | Whether to create the persistentVolumeClaim for shared storage | `true` | +| `persistence.mount` | Whether the persistentVolumeClaim should be mounted (even if not created) | `true` | +| `persistence.claimName` | Use an existing claim to store repository information | `gitea-shared-storage` | +| `persistence.size` | Size for persistence to store repo information | `10Gi` | +| `persistence.accessModes` | AccessMode for persistence | `["ReadWriteOnce"]` | +| `persistence.labels` | Labels for the persistence volume claim to be created | `{}` | +| `persistence.annotations.helm.sh/resource-policy` | Resource policy for the persistence volume claim | `keep` | +| `persistence.storageClass` | Name of the storage class to use | `nil` | +| `persistence.subPath` | Subdirectory of the volume to mount at | `nil` | +| `persistence.volumeName` | Name of persistent volume in PVC | `""` | +| `extraContainers` | Additional sidecar containers to run in the pod | `[]` | +| `preExtraInitContainers` | Additional init containers to run in the pod before Gitea runs it owns init containers. | `[]` | +| `postExtraInitContainers` | Additional init containers to run in the pod after Gitea runs it owns init containers. | `[]` | +| `extraVolumes` | Additional volumes to mount to the Gitea deployment | `[]` | +| `extraContainerVolumeMounts` | Mounts that are only mapped into the Gitea runtime/main container, to e.g. override custom templates. | `[]` | +| `extraInitVolumeMounts` | Mounts that are only mapped into the init-containers. Can be used for additional preconfiguration. | `[]` | +| `extraVolumeMounts` | **DEPRECATED** Additional volume mounts for init containers and the Gitea main container | `[]` | + +### Init + +| Name | Description | Value | +| ------------------------------------------ | ------------------------------------------------------------------------------------ | ------------ | +| `initPreScript` | Bash shell script copied verbatim to the start of the init-container. | `""` | +| `initContainersScriptsVolumeMountPath` | Path to mount the scripts consumed from the Secrets | `/usr/sbinx` | +| `initContainers.resources.limits` | initContainers.limits Kubernetes resource limits for init containers | `{}` | +| `initContainers.resources.requests.cpu` | initContainers.requests.cpu Kubernetes cpu resource limits for init containers | `100m` | +| `initContainers.resources.requests.memory` | initContainers.requests.memory Kubernetes memory resource limits for init containers | `128Mi` | + +### Signing + +| Name | Description | Value | +| ------------------------ | ----------------------------------------------------------------- | ------------------ | +| `signing.enabled` | Enable commit/action signing | `false` | +| `signing.gpgHome` | GPG home directory | `/data/git/.gnupg` | +| `signing.privateKey` | Inline private gpg key for signed internal Git activity | `""` | +| `signing.existingSecret` | Use an existing secret to store the value of `signing.privateKey` | `""` | + +### Gitea + +| Name | Description | Value | +| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | -------------------- | +| `gitea.admin.username` | Username for the Gitea admin user | `gitea_admin` | +| `gitea.admin.existingSecret` | Use an existing secret to store admin user credentials | `nil` | +| `gitea.admin.password` | Password for the Gitea admin user | `r8sA8CPHD9!bt6d` | +| `gitea.admin.email` | Email for the Gitea admin user | `gitea@local.domain` | +| `gitea.admin.passwordMode` | Mode for how to set/update the admin user password. Options are: initialOnlyNoReset, initialOnlyRequireReset, and keepUpdated | `keepUpdated` | +| `gitea.metrics.enabled` | Enable Gitea metrics | `false` | +| `gitea.metrics.token` | used for `bearer` token authentication on metrics endpoint. If not specified or empty metrics endpoint is public. | `nil` | +| `gitea.metrics.serviceMonitor.enabled` | Enable Gitea metrics service monitor. Requires, that `gitea.metrics.enabled` is also set to true, to enable metrics generally. | `false` | +| `gitea.metrics.serviceMonitor.interval` | Interval at which metrics should be scraped. If not specified Prometheus' global scrape interval is used. | `""` | +| `gitea.metrics.serviceMonitor.relabelings` | RelabelConfigs to apply to samples before scraping. | `[]` | +| `gitea.metrics.serviceMonitor.scheme` | HTTP scheme to use for scraping. For example `http` or `https`. Default is http. | `""` | +| `gitea.metrics.serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended. If not specified, global Prometheus scrape timeout is used. | `""` | +| `gitea.metrics.serviceMonitor.tlsConfig` | TLS configuration to use when scraping the metric endpoint by Prometheus. | `{}` | +| `gitea.ldap` | LDAP configuration | `[]` | +| `gitea.oauth` | OAuth configuration | `[]` | +| `gitea.config.server.SSH_PORT` | SSH port for rootlful Gitea image | `22` | +| `gitea.config.server.SSH_LISTEN_PORT` | SSH port for rootless Gitea image | `2222` | +| `gitea.additionalConfigSources` | Additional configuration from secret or configmap | `[]` | +| `gitea.additionalConfigFromEnvs` | Additional configuration sources from environment variables | `[]` | +| `gitea.podAnnotations` | Annotations for the Gitea pod | `{}` | +| `gitea.ssh.logLevel` | Configure OpenSSH's log level. Only available for root-based Gitea image. | `INFO` | + +### LivenessProbe + +| Name | Description | Value | +| ----------------------------------------- | ------------------------------------------------ | ------ | +| `gitea.livenessProbe.enabled` | Enable liveness probe | `true` | +| `gitea.livenessProbe.tcpSocket.port` | Port to probe for liveness | `http` | +| `gitea.livenessProbe.initialDelaySeconds` | Initial delay before liveness probe is initiated | `200` | +| `gitea.livenessProbe.timeoutSeconds` | Timeout for liveness probe | `1` | +| `gitea.livenessProbe.periodSeconds` | Period for liveness probe | `10` | +| `gitea.livenessProbe.successThreshold` | Success threshold for liveness probe | `1` | +| `gitea.livenessProbe.failureThreshold` | Failure threshold for liveness probe | `10` | + +### ReadinessProbe + +| Name | Description | Value | +| ------------------------------------------ | ------------------------------------------------- | ------ | +| `gitea.readinessProbe.enabled` | Enable readiness probe | `true` | +| `gitea.readinessProbe.tcpSocket.port` | Port to probe for readiness | `http` | +| `gitea.readinessProbe.initialDelaySeconds` | Initial delay before readiness probe is initiated | `5` | +| `gitea.readinessProbe.timeoutSeconds` | Timeout for readiness probe | `1` | +| `gitea.readinessProbe.periodSeconds` | Period for readiness probe | `10` | +| `gitea.readinessProbe.successThreshold` | Success threshold for readiness probe | `1` | +| `gitea.readinessProbe.failureThreshold` | Failure threshold for readiness probe | `3` | + +### StartupProbe + +| Name | Description | Value | +| ---------------------------------------- | ----------------------------------------------- | ------- | +| `gitea.startupProbe.enabled` | Enable startup probe | `false` | +| `gitea.startupProbe.tcpSocket.port` | Port to probe for startup | `http` | +| `gitea.startupProbe.initialDelaySeconds` | Initial delay before startup probe is initiated | `60` | +| `gitea.startupProbe.timeoutSeconds` | Timeout for startup probe | `1` | +| `gitea.startupProbe.periodSeconds` | Period for startup probe | `10` | +| `gitea.startupProbe.successThreshold` | Success threshold for startup probe | `1` | +| `gitea.startupProbe.failureThreshold` | Failure threshold for startup probe | `10` | + +### valkey-cluster + +Valkey cluster and [Valkey](#valkey) cannot be enabled at the same time. + +| Name | Description | Value | +| ------------------------------------- | -------------------------------------------------------------------- | ------- | +| `valkey-cluster.enabled` | Enable valkey cluster | `true` | +| `valkey-cluster.usePassword` | Whether to use password authentication | `false` | +| `valkey-cluster.usePasswordFiles` | Whether to mount passwords as files instead of environment variables | `false` | +| `valkey-cluster.cluster.nodes` | Number of valkey cluster master nodes | `3` | +| `valkey-cluster.cluster.replicas` | Number of valkey cluster master node replicas | `0` | +| `valkey-cluster.service.ports.valkey` | Port of Valkey service | `6379` | + +### valkey + +Valkey and [Valkey cluster](#valkey-cluster) cannot be enabled at the same time. + +| Name | Description | Value | +| ------------------------------------ | ------------------------------------------- | ------------ | +| `valkey.enabled` | Enable valkey standalone or replicated | `false` | +| `valkey.architecture` | Whether to use standalone or replication | `standalone` | +| `valkey.global.valkey.password` | Required password | `changeme` | +| `valkey.master.count` | Number of Valkey master instances to deploy | `1` | +| `valkey.master.service.ports.valkey` | Port of Valkey service | `6379` | + +### PostgreSQL HA + +| Name | Description | Value | +| ------------------------------------------- | ---------------------------------------------------------------- | ----------- | +| `postgresql-ha.enabled` | Enable PostgreSQL HA | `true` | +| `postgresql-ha.postgresql.password` | Password for the `gitea` user (overrides `auth.password`) | `changeme4` | +| `postgresql-ha.global.postgresql.database` | Name for a custom database to create (overrides `auth.database`) | `gitea` | +| `postgresql-ha.global.postgresql.username` | Name for a custom user to create (overrides `auth.username`) | `gitea` | +| `postgresql-ha.global.postgresql.password` | Name for a custom password to create (overrides `auth.password`) | `gitea` | +| `postgresql-ha.postgresql.repmgrPassword` | Repmgr Password | `changeme2` | +| `postgresql-ha.postgresql.postgresPassword` | postgres Password | `changeme1` | +| `postgresql-ha.pgpool.adminPassword` | pgpool adminPassword | `changeme3` | +| `postgresql-ha.pgpool.srCheckPassword` | pgpool srCheckPassword | `changeme4` | +| `postgresql-ha.service.ports.postgresql` | PostgreSQL service port (overrides `service.ports.postgresql`) | `5432` | +| `postgresql-ha.persistence.size` | PVC Storage Request for PostgreSQL HA volume | `10Gi` | + +### PostgreSQL + +| Name | Description | Value | +| ------------------------------------------------------- | ---------------------------------------------------------------- | ------- | +| `postgresql.enabled` | Enable PostgreSQL | `false` | +| `postgresql.global.postgresql.auth.password` | Password for the `gitea` user (overrides `auth.password`) | `gitea` | +| `postgresql.global.postgresql.auth.database` | Name for a custom database to create (overrides `auth.database`) | `gitea` | +| `postgresql.global.postgresql.auth.username` | Name for a custom user to create (overrides `auth.username`) | `gitea` | +| `postgresql.global.postgresql.service.ports.postgresql` | PostgreSQL service port (overrides `service.ports.postgresql`) | `5432` | +| `postgresql.primary.persistence.size` | PVC Storage Request for PostgreSQL volume | `10Gi` | + +### Advanced + +| Name | Description | Value | +| ------------------ | ------------------------------------------------------------------ | --------- | +| `checkDeprecation` | Set it to false to skip this basic validation check. | `true` | +| `test.enabled` | Set it to false to disable test-connection Pod. | `true` | +| `test.image.name` | Image name for the wget container used in the test-connection Pod. | `busybox` | +| `test.image.tag` | Image tag for the wget container used in the test-connection Pod. | `latest` | +| `extraDeploy` | Array of extra objects to deploy with the release | `[]` | + +## Contributing + +Expected workflow is: Fork -> Patch -> Push -> Pull Request + +See [CONTRIBUTORS GUIDE](CONTRIBUTING.md) for details. + +## Upgrading + +This section lists major and breaking changes of each Helm Chart version. +Please read them carefully to upgrade successfully, especially the change of the **default database backend**! +If you miss this, blindly upgrading may delete your Postgres instance and you may lose your data! + +
+ +To 12.0.0 + + + +**Breaking changes** + + +- Outsourced "Actions" related configuration. + To deploy and use "Actions", please see the new dedicated chart at . + It is maintained by a seperate maintainer group and hasn't seen a release yet (at the time of the 12.0 release). + Feel encouraged to contribute if "Actions" is important to you! + + This change was made to avoid overloading the existing helm chart, which is already quite large in size and configuration options. + In addition, the existing maintainers team was not actively using "Actions" which slowed down development and community contributions. + While the new chart is still young (and waiting for contributions! and maintainers), we believe that it is the best way moving forward for both parts. +- Migrated from Redis/Redis-cluster to Valkey/Valkey-cluster charts (#775). + While marked as breaking, there is no need to migrate data. + The cache will start to refill automatically. +- Migrated ingress from `networking.k8s.io/v1beta` to `networking.k8s.io/v1`. + We didn't make any changes to the syntax, so the upgrade should be seamless. + +
+ +
+ +To 11.0.0 + + + +**Breaking changes** + + +- Update Gitea to 1.23.x (review the [1.23 release blog post](https://blog.gitea.com/release-of-1.23.0/) for all application breaking changes) +- Update PostgreSQL sub-chart dependencies to appVersion 17.x +- Update Redis sub-chart to version 20.x (appVersion 7.4) + Although there are no breaking changes in the Redis Chart itself, it updates Redis from `7.2` to `7.4`. We recommend checking the release notes: + - [Redis Chart release notes (starting with v20.0.0)](https://github.com/bitnami/charts/blob/HEAD/bitnami/redis/CHANGELOG.md#2000-2024-08-09). + - [Redis 7.4 release notes](https://raw.githubusercontent.com/redis/redis/7.4/00-RELEASENOTES). +- Update Redis Cluster sub-chart to version 11.x (appVersion 7.4) + Although there are no breaking changes in the Redis Chart itself, it updates Redis from `7.2` to `7.4`. We recommend checking the release notes: + - [Redis Chart release notes (starting with v11.0.0)](https://github.com/bitnami/charts/blob/HEAD/bitnami/redis-cluster/CHANGELOG.md#1100-2024-08-09). + - [Redis 7.4 release notes](https://raw.githubusercontent.com/redis/redis/7.4/00-RELEASENOTES). +
+ +
+ +To 10.0.0 + + + +**Breaking changes** + + +- Update PostgreSQL sub-chart dependencies to appVersion 16.x +- Update to sub-charts versioning approach: Users are encouraged to pin the version tag of the sub-chart dependencies to a major appVersion. + This avoids issues during chart upgrades and allows to incorporate new sub-chart versions as they are released. + Please see the new [README section describing the versioning approach for sub-chart versions](#dependency-versioning). + +
+ +
+ +To 9.6.0 + +Chart 9.6.0 ships with Gitea 1.21.0. +While there are no breaking changes in the chart, please check the changes of the [1.21 release blog post](https://blog.gitea.com/release-of-1.21.0/). + +
+ +
+ +To 9.0.0 + +This chart release comes with many breaking changes while aiming for a HA-ready setup. +Please go through all of them carefully to perform a successful upgrade. +Here's a brief summary again, followed by more detailed migration instructions: + +- Switch from `Statefulset` to `Deployment` +- Switch from `Memcached` to `redis-cluster` as the default session and queue provider +- Switch from `postgres` to `postgres-ha` as the default database provider +- A chart-internal PVC bootstrapping logic + - New `persistence.mount`: whether to mount an existent PVC (even if not creating it) + - New `persistence.create`: whether to create a new PVC + - Renamed `persistence.existingClaim` to `persistence.claimName` + +While not required, we recommend to start with a RWX PV for new installations. +A RWX volume is required for installation aiming for HA. + +If you want to stay with a pre-existing RWO PV, you need to set + +- `persistence.mount=true` +- `persistence.create=false` +- `persistence.claimName` to the name of your existing PVC. + +If you do not, Gitea will create a new PVC which will in turn create a new PV. +If this happened to you by accident, you can still recover your data by setting using the settings from above in a subsequent run. + +If you want to stay with a `memcache` instead of `redis-cluster`, you need to deploy `memcache` manually (e.g. from [bitnami](https://github.com/bitnami/charts/tree/main/bitnami/memcached)) and set + +- `cache.HOST = ""` +- `cache.ADAPTER = "memcache"` +- `session.PROVIDER = "memcache"` +- `session.PROVIDER_CONFIG = ""` +- `queue.TYPE = "memcache"` +- `queue.CONN_STR = ""` + +The `memcache` connection string has the scheme `memcache://:`, e.g. `gitea-memcached.gitea.svc.cluster.local:11211`. +The first item here (``) will be different compared to the example if you deploy `memcache` yourself. + +The above changes are motivated by the idea to tidy dependencies but also have HA-ready ones at the same time. +The previous `memcache` default was not HA-ready, hence we decided to switch to `redis-cluster` by default. + +If you are coming from an existing deployment and [#356](https://gitea.com/gitea/helm-gitea/issues/356) is still open, you need to set the config sections for `cache`, `session` and `queue` explicitly: + +```yaml +gitea: + config: + session: + PROVIDER: redis-cluster + PROVIDER_CONFIG: redis+cluster://:gitea@gitea-valkey-cluster-headless..svc.cluster.local:6379/0?pool_size=100&idle_timeout=180s& + + cache: + ENABLED: true + ADAPTER: redis-cluster + HOST: redis+cluster://:gitea@gitea-valkey-cluster-headless..svc.cluster.local:6379/0?pool_size=100&idle_timeout=180s& + + queue: + TYPE: redis + CONN_STR: redis+cluster://:gitea@gitea-valkey-cluster-headless..svc.cluster.local:6379/0?pool_size=100&idle_timeout=180s& +``` + + + +**Switch to rootless image by default** + + +If you are facing errors like `WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED` due to this automatic transition: +Have a look at [this discussion](https://gitea.com/gitea/helm-gitea/issues/487#issue-220660) and either set `image.rootless: false` or manually update your `~/.ssh/known_hosts` file(s). + + + +**Transitioning from a RWO to RWX Persistent Volume** + + +If you want to switch to a RWX volume and go for HA, you need to + +1. Backup the data stored under `/data` +2. Let the chart create a new RWX PV (or do it statically yourself) +3. Restore the backup to the same location in the new PV + + + +**Transitioning from Postgres to Postgres HA** + + +If you are running with a non-HA PG DB from a previous chart release, you need to set + +- `postgresql-ha.enabled=false` +- `postgresql.enabled=true` + +This is needed to stay with your existing single-instance DB (as the HA-variant is the new default). + + + +**Change of env-to-ini prefix** + + +Before this release, the env-to-ini prefix was `ENV_TO_INI__`. +This allowed a clear distinction between user-provided and chart-provided env-to-ini variables. +Due to the removal custom prefix feature in the upstream implementation of env-to-ini, the prefix has been changed to the default `GITEA__`. + +If you previously had defined env vars that had the `ENV_TO_INI__` prefix, you need to change them to `GITEA__` in order for them to be picked up by the chart. + +
+ +
+ +To 8.0.0 + +### Removal of MariaDB and MySQL DB chart dependencies + +In this version support for DB chart dependencies of MySQL and MariaDB have been removed to simplify the maintenance of the helm chart. +External MySQL and MariaDB databases are still supported and will be in the future. + +### Postgres Update from v11 to v15 + +This Chart version updates the Postgres chart dependency and subsequently Postgres from v11 to v15. +Please read the [Postgres Release Notes](https://www.postgresql.org/docs/release/) for version-specific changes. +With respect to `values.yaml`, parameters `username`, `database` and `password` have been regrouped under `auth` and slightly renamed. +`persistence` has also been regrouped under the `primary` key. +Please adjust your `values.yaml` accordingly. + +**Attention**: The Postgres upgrade is not automatically handled by the chart and must be done by yourself. +See [this comment](https://gitea.com/gitea/helm-gitea/issues/452#issuecomment-740885) for an extensive walkthrough. +We again highly encourage users to use an external (managed) database for production instances. + +
+ +
+ +To 7.0.0 + +### Private GPG key configuration for Gitea signing actions + +Having `signing.enabled=true` now requires to use either `signing.privateKey` or `signing.existingSecret` so that the Chart can automatically prepare the GPG key for Gitea internal signing actions. +See [Configure commit signing](#configure-commit-signing) for details. + +
+ +
+ +To 6.0.0 + +### Different volume mounts for init-containers and runtime container + +**The `extraVolumeMounts` is deprecated** in favor of `extraInitVolumeMounts` and `extraContainerVolumeMounts`. +You can now have different mounts for the initialization phase and Gitea runtime. +The deprecated `extraVolumeMounts` will still be available for the time being and is mounted into every container. +If you want to switch to the new settings and want to mount specific volumes into all containers, you have to configure their mount points within both new settings. + +**Combining values from the deprecated setting with values from the new settings is not possible.** + +### New `enabled` flag for `startupProbe` + +Prior to this version the `startupProbe` was just a commented sample within the `values.yaml`. +With the migration to an auto-generated [Parameters](#parameters) section, a new parameter `gitea.startupProbe.enabled` has been introduced set to +`false` by default. + +If you are using the `startupProbe` you need to add that new parameter and set it to `true`. +Otherwise, your defined probe won't be considered after the upgrade. + +
+ +
+ +To 5.0.0 + +> 💥 The Helm Chart now requires Gitea versions of at least 1.11.0. + +### Enable Dependencies + +The values to enable the dependencies, such as PostgreSQL, Memcached, MySQL and MariaDB have been moved from `gitea.database.builtIn.` to the dependency values. + +You can now enable the dependencies as followed: + +```yaml +memcached: + enabled: true + +postgresql: + enabled: true + +mysql: + enabled: false + +mariadb: + enabled: false +``` + +### App.ini generation + +The app.ini generation has changed and now utilizes the environment-to-ini script provided by newer Gitea versions. +This change ensures, that the app.ini is now persistent. + +### Secret Key generation + +Gitea secret keys (SECRET_KEY, INTERNAL_TOKEN, JWT_SECRET) are now generated automatically in certain situations: + +- New install: By default the secrets are created automatically. + If you provide secrets via `gitea.config` they will be used instead of automatic generation. +- Existing installs: The secrets won't be deployed, neither via configuration nor via auto generation. + We explicitly prevent to set new secrets. + +> 💡 It would be possible to set new secret keys manually by entering the running container and rewriting the app.ini by hand. +> However, this it is not advisable to do so for existing installations. +> Certain settings like _LDAP_ would not be readable anymore. + +### Probes + +`gitea.customLivenessProbe`, `gitea.customReadinessProbe` and `gitea.customStartupProbe` have been removed. + +They are replaced by the settings `gitea.livenessProbe`, `gitea.readinessProbe` and `gitea.startupProbe` which are now fully configurable and used _as-is_ for +a Chart deployment. +If you have customized their values instead of using the `custom` prefixed settings, please ensure that you remove the `enabled` property from each of them. + +In case you want to disable one of these probes, let's say the `livenessProbe`, add the following to your values. +The `podAnnotation` is just there to have a bit more context. + +```diff +gitea: ++ livenessProbe: + podAnnotations: {} +``` + +### Multiple OAuth and LDAP authentication sources + +With `5.0.0` of this Chart it is now possible to configure Gitea with multiple OAuth and LDAP sources. +As a result, you need to update an existing OAuth/LDAP configuration in your customized `values.yaml` by replacing the object with settings to a list +of settings objects. +See [OAuth2 Settings](#oauth2-settings) and [LDAP Settings](#ldap-settings) section for details. + +
+ +
+ +To 4.0.0 + +### Ingress changes + +To provide a more flexible Ingress configuration we now support not only host settings but also provide configuration for the path and pathType. +So this change changes the hosts from a simple string list, to a list containing a more complex object for more configuration. + +```diff +ingress: + enabled: false + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" +- hosts: +- - git.example.com ++ hosts: ++ - host: git.example.com ++ paths: ++ - path: / ++ pathType: Prefix + tls: [] + # - secretName: chart-example-tls + # hosts: + # - git.example.com +``` + +If you want everything as it was before, you can simply add the following code to all your host entries. + +```yaml +paths: + - path: / + pathType: Prefix +``` + +### Dropped kebab-case support + +In 3.x.x it was possible to provide an ldap configuration via kebab-case, this support has now been dropped and only camel case is supported. +See [LDAP section](#ldap-settings) for more information. + +### Dependency update + +The chart comes with multiple databases and Memcached as dependency, the latest release updated the dependencies. + +- Memcached: `4.2.20` -> `5.9.0` +- PostgreSQL: `9.7.2` -> `10.3.17` +- MariaDB: `8.0.0` -> `9.3.6` + +If you're using the builtin databases you will most likely redeploy the chart in order to update the database correctly. + +### Execution of initPreScript + +Generally spoken, this might not be a breaking change, but it is worth to be mentioned. + +Prior to `4.0.0` only one init container was used to both setup directories and configure Gitea. +As of now the actual Gitea configuration is separated from the other pre-execution. +This also includes the execution of _initPreScript_. +If you have such script, please be aware of this. +Dynamically prepare the Gitea setup during execution by e.g. adding environment variables to the execution context won't work anymore. + +### Gitea Version 1.14.X repository ROOT + +Previously the ROOT folder for the Gitea repositories was located at `/data/git/gitea-repositories`. +In version `1.14` has the path been changed to `/data/gitea-repositories`. + +This chart will set the `gitea.config.repository.ROOT` value default to `/data/git/gitea-repositories`. + +
diff --git a/backing-services/gitea/charts/postgresql-ha/.helmignore b/backing-services/gitea/charts/postgresql-ha/.helmignore new file mode 100644 index 0000000..207983f --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/.helmignore @@ -0,0 +1,25 @@ +# 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 +# img folder +img/ +# Changelog +CHANGELOG.md diff --git a/backing-services/gitea/charts/postgresql-ha/Chart.lock b/backing-services/gitea/charts/postgresql-ha/Chart.lock new file mode 100644 index 0000000..feadd8e --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + version: 2.31.4 +digest: sha256:fc442e77200e1914dd46fe26490dcf62f44caa51db673c2f8e67d5319cd4c163 +generated: "2025-08-14T15:29:38.353757874Z" diff --git a/backing-services/gitea/charts/postgresql-ha/Chart.yaml b/backing-services/gitea/charts/postgresql-ha/Chart.yaml new file mode 100644 index 0000000..e4231ce --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/Chart.yaml @@ -0,0 +1,43 @@ +annotations: + category: Database + images: | + - name: os-shell + image: docker.io/bitnami/os-shell:12-debian-12-r51 + - name: pgpool + image: docker.io/bitnami/pgpool:4.6.3-debian-12-r0 + - name: postgres-exporter + image: docker.io/bitnami/postgres-exporter:0.17.1-debian-12-r16 + - name: postgresql-repmgr + image: docker.io/bitnami/postgresql-repmgr:17.6.0-debian-12-r2 + licenses: Apache-2.0 + tanzuCategory: service +apiVersion: v2 +appVersion: 17.6.0 +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + tags: + - bitnami-common + version: 2.x.x +description: This PostgreSQL cluster solution includes the PostgreSQL replication + manager, an open-source tool for managing replication and failover on PostgreSQL + clusters. +home: https://bitnami.com +icon: https://dyltqmyl993wv.cloudfront.net/assets/stacks/postgresql/img/postgresql-stack-220x234.png +keywords: +- postgresql +- repmgr +- pgpool +- postgres +- database +- sql +- replication +- cluster +- high availability +maintainers: +- name: Broadcom, Inc. All Rights Reserved. + url: https://github.com/bitnami/charts +name: postgresql-ha +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/postgresql-ha +version: 16.3.2 diff --git a/backing-services/gitea/charts/postgresql-ha/README.md b/backing-services/gitea/charts/postgresql-ha/README.md new file mode 100644 index 0000000..1ee8fdf --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/README.md @@ -0,0 +1,1344 @@ + + +# Bitnami package for PostgreSQL HA + +This PostgreSQL cluster solution includes the PostgreSQL replication manager, an open-source tool for managing replication and failover on PostgreSQL clusters. + +[Overview of PostgreSQL HA](https://www.postgresql.org/) + +Trademarks: This software listing is packaged by Bitnami. The respective trademarks mentioned in the offering are owned by the respective companies, and use of them does not imply any affiliation or endorsement. + +## TL;DR + +```console +helm install my-release oci://registry-1.docker.io/bitnamicharts/postgresql-ha +``` + +Looking to use PostgreSQL HA in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the commercial edition of the Bitnami catalog. + +## ⚠️ Important Notice: Upcoming changes to the Bitnami Catalog + +Beginning August 28th, 2025, Bitnami will evolve its public catalog to offer a curated set of hardened, security-focused images under the new [Bitnami Secure Images initiative](https://news.broadcom.com/app-dev/broadcom-introduces-bitnami-secure-images-for-production-ready-containerized-applications). As part of this transition: + +- Granting community users access for the first time to security-optimized versions of popular container images. +- Bitnami will begin deprecating support for non-hardened, Debian-based software images in its free tier and will gradually remove non-latest tags from the public catalog. As a result, community users will have access to a reduced number of hardened images. These images are published only under the “latest” tag and are intended for development purposes +- Starting August 28th, over two weeks, all existing container images, including older or versioned tags (e.g., 2.50.0, 10.6), will be migrated from the public catalog (docker.io/bitnami) to the “Bitnami Legacy” repository (docker.io/bitnamilegacy), where they will no longer receive updates. +- For production workloads and long-term support, users are encouraged to adopt Bitnami Secure Images, which include hardened containers, smaller attack surfaces, CVE transparency (via VEX/KEV), SBOMs, and enterprise support. + +These changes aim to improve the security posture of all Bitnami users by promoting best practices for software supply chain integrity and up-to-date deployments. For more details, visit the [Bitnami Secure Images announcement](https://github.com/bitnami/containers/issues/83267). + +## Introduction + +This [Helm](https://github.com/kubernetes/helm) chart installs [PostgreSQL](https://www.postgresql.org/) with HA architecture in a Kubernetes cluster. Welcome to [contribute](https://github.com/bitnami/charts/blob/main/CONTRIBUTING.md) to Helm Chart for PostgreSQL HA. + +This Helm chart has been developed based on [bitnami/postgresql](https://github.com/bitnami/charts/tree/main/bitnami/postgresql) chart but including some changes to guarantee high availability such as: + +- A new deployment, service have been added to deploy [Pgpool-II](https://pgpool.net/mediawiki/index.php/Main_Page) to act as proxy for PostgreSQL backend. It helps to reduce connection overhead, acts as a load balancer for PostgreSQL, and ensures database node failover. +- Replacing `bitnami/postgresql` with `bitnami/postgresql-repmgr` which includes and configures [repmgr](https://repmgr.org/). Repmgr ensures standby nodes assume the primary role when the primary node is unhealthy. + +## Differences between the PostgreSQL-HA and PostgreSQL Helm charts + +There are two different ways to deploy a PostgreSQL cluster, using the PostgreSQL Helm chart or the PostgreSQL High Availability (HA) Helm chart. Both solutions provide a simple and reliable way to run PostgreSQL in a production environment. Keep reading to discover the differences between them and check which one better suits your needs. + +- Both the PostgreSQL HA and the PostgreSQL chart configures a cluster with a primary/replica topology. The primary node has writing permissions while replication is on the replica nodes which have read-only permissions. +- The PostgreSQL HA Helm chart deploys a cluster with four nodes by default, one for Pgpool-II, and three PostgreSQL+Repmgr replicas. The PostgreSQL chart configures a cluster with two nodes by default (one primary and one replica). +- The PostgreSQL HA Helm chart uses Pgpool-II to handle the connection to the nodes. Pgpool-II is responsible to spread the queries among nodes. +- The PostgreSQL HA Helm chart includes a Repmgr module that ensures high-availability thanks to automatic membership control. If the primary is down, any of the replica nodes will be promoted as primary to avoid data loss. + +The following diagram shows you the options you have for using Bitnami's PostgreSQL solutions in your deployments: + +![A diagram comparing a PostgreSQL solution versus a PostgreSQL HA with Pgpool-II and Repmgr](img/postgresql-ha-topology.png) + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```console +helm install my-release oci://REGISTRY_NAME/REPOSITORY_NAME/postgresql-ha +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +## Configuration and installation details + +### Resource requests and limits + +Bitnami charts allow setting resource requests and limits for all containers inside the chart deployment. These are inside the `resources` value (check parameter table). Setting requests is essential for production workloads and these should be adapted to your specific use case. + +To make this process easier, the chart contains the `resourcesPreset` values, which automatically sets the `resources` section according to different presets. Check these presets in [the bitnami/common chart](https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15). However, in production workloads using `resourcesPreset` is discouraged as it may not fully adapt to your specific needs. Find more information on container resource management in the [official Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). + +### Prometheus metrics + +This chart can be integrated with Prometheus by setting `metrics.enabled` to `true`. This will deploy a sidecar container with [postgres_exporter](https://github.com/prometheus-community/postgres_exporter) in all pods. It will also create `metrics` services that can be configured under the `metrics.service` section. These services will be have the necessary annotations to be automatically scraped by Prometheus. + +#### Prometheus requirements + +It is necessary to have a working installation of Prometheus or Prometheus Operator for the integration to work. Install the [Bitnami Prometheus helm chart](https://github.com/bitnami/charts/tree/main/bitnami/prometheus) or the [Bitnami Kube Prometheus helm chart](https://github.com/bitnami/charts/tree/main/bitnami/kube-prometheus) to easily have a working Prometheus in your cluster. + +#### Integration with Prometheus Operator + +The chart can deploy `ServiceMonitor` objects for integration with Prometheus Operator installations. To do so, set the value `metrics.serviceMonitor.enabled=true`. Ensure that the Prometheus Operator `CustomResourceDefinitions` are installed in the cluster or it will fail with the following error: + +```text +no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1" +``` + +Install the [Bitnami Kube Prometheus helm chart](https://github.com/bitnami/charts/tree/main/bitnami/kube-prometheus) for having the necessary CRDs and the Prometheus Operator. + +### Update credentials + +Bitnami charts configure credentials at first boot. Any further change in the secrets or credentials require manual intervention. Follow these instructions: + +- Update the user password following [the upstream documentation](https://www.postgresql.org/docs/current/sql-alteruser.html) +- Update the password secret with the new values (replace the SECRET_NAME, POSTGRES_PASSWORD and PASSWORD and REPMGR_PASSWORD placeholders) + +```shell +kubectl create secret generic SECRET_NAME --from-literal=postgres-password=POSTGRES_PASSWORD --from-literal=password=PASSWORD --from-literal=repmgr-password=REPMGR_PASSWORD --dry-run -o yaml | kubectl apply -f - +``` + +### [Rolling VS Immutable tags](https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-understand-rolling-tags-containers-index.html) + +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. + +### Use a different PostgreSQL version + +To modify the application version used in this chart, specify a different version of the image using the `postgresql.image.tag` parameter and/or a different repository using the `postgresql.image.repository` parameter. + +### Use a volume for /dev/shm + +When working with huge databeses, `/dev/shm` can run out of space. A way to fix this is to use the `postgresql.extraVolumes` and `postgresql.extraVolumeMounts` values. In the example below, we set an `emptyDir` volume with 512Mb: + +```yaml +postgresql: + extraVolumes: + - name: dshm + emptyDir: + medium: Memory + sizeLimit: 512Mi + extraVolumeMounts: + - name: dshm + mountPath: /dev/shm +``` + +### Configure the way how to expose Pgpool-II + +- **ClusterIP**: Exposes the service on a cluster-internal IP. Choosing this value makes the service only reachable from within the cluster. Set `service.type=ClusterIP` to choose this service type. +- **NodePort**: Exposes the service on each Node's IP at a static port (the NodePort). You will be able to contact the NodePort service, from outside the cluster, by requesting `NodeIP:NodePort`. Set `service.type=NodePort` to choose this service type. +- **LoadBalancer**: Exposes the service externally using a cloud provider's load balancer. Set `service.type=LoadBalancer` to choose this service type. + +### Adjust permissions of persistent volume mountpoint + +As the images run as non-root by default, it is necessary to adjust the ownership of the persistent volumes so that the containers can write data into it. + +By default, the chart is configured to use Kubernetes Security Context to automatically change the ownership of the volume. However, this feature does not work in all Kubernetes distributions. +As an alternative, this chart supports using an initContainer to change the ownership of the volume before mounting it in the final destination. + +You can enable this initContainer by setting `volumePermissions.enabled` to `true`. + +### LDAP + +LDAP support can be enabled in the chart by specifying the `ldap.` parameters while creating a release. The following parameters should be configured to properly enable the LDAP support in the chart. + +- **ldap.enabled**: Enable LDAP support. Defaults to `false`. +- **ldap.uri**: LDAP URL beginning in the form `ldap[s]://:`. No defaults. +- **ldap.basedn**: LDAP base DN. No defaults. +- **ldap.binddn**: LDAP bind DN. No defaults. +- **ldap.bindpw**: LDAP bind password. No defaults. +- **ldap.bslookup**: LDAP base lookup. No defaults. +- **ldap.nss_initgroups_ignoreusers**: LDAP ignored users. `root,nslcd`. +- **ldap.scope**: LDAP search scope. No defaults. +- **ldap.searchfilter**: LDAP search filter. No defaults. +- **ldap.searchmap**: LDAP search map. No defaults. +- **ldap.tls_reqcert**: LDAP TLS check on server certificates. No defaults. + +For example: + +```text +ldap.enabled="true" +ldap.uri="ldap://my_ldap_server" +ldap.basedn="dc=example\,dc=org" +ldap.binddn="cn=admin\,dc=example\,dc=org" +ldap.bindpw="admin" +ldap.bslookup="ou=group-ok\,dc=example\,dc=org" +ldap.nss_initgroups_ignoreusers="root\,nslcd" +ldap.scope="sub" +ldap.searchfilter="posixaccount" +ldap.searchmap="uid" +ldap.tls_reqcert="demand" +``` + +Next, login to the PostgreSQL server using the `psql` client and add the PAM authenticated LDAP users. + +> Note: Parameters including commas must be escaped as shown in the above example. + +### Securing traffic using TLS + +The chart handles two main flows of traffic information: + +- Connections between end-clients and Pgpool-II (sometimes referred to as *frontend* connections). +- Internal connections between Pgpool-II and PostgreSQL nodes (sometimes referred to as *backend* connections). + +The Bitnami postgresql-ha chart allows configuring the securitization of both types of traffic using TLS. + +#### Encrypt traffic between clients and Pgpool-II (frontend) + +TLS for end-client connections can be enabled in the chart by specifying the `pgpool.tls.*` parameters when installing a release. Below you can find detailed information about these parameters: + +- `pgpool.tls.enabled`: Enable TLS support. Defaults to `false`. +- `pgpool.tls.certificatesSecret`: Name of an existing secret that contains the certificates. No defaults. +- `pgpool.tls.certFilename`: Certificate filename. No defaults. +- `pgpool.tls.certKeyFilename`: Certificate key filename. No defaults. + +For example: + +- First, create a secret with the certificates files. You will need to generate previously the certificate files: + + ```console + kubectl create secret generic pgpool-tls-secret --from-file=./cert.crt --from-file=./cert.key --from-file=./ca.crt + ``` + +> Note: Although certificate generation is out of the scope of this guide, bear in mind that PostgreSQL requires that server TLS certificates specify the actual DNS server name in the CN (Common Name) field. + +- Then, install the chart using the following parameters: + + ```console + pgpool.tls.enabled=true + pgpool.tls.certificatesSecret="pgpool-tls-secret" + pgpool.tls.certFilename="cert.crt" + pgpool.tls.certKeyFilename="cert.key" + ``` + +> Note: Certificates permissions: Pgpool-II requires certain permissions on sensitive files (such as certificate keys) to start up. Due to an on-going [issue](https://github.com/kubernetes/kubernetes/issues/57923) regarding K8s permissions and the use of `containerSecurityContext.runAsUser`, an init container will adapt the permissions to ensure everything works as expected. + +##### Enable client certificate authentication + +When TLS is configured for *frontend* connections, the server can be configured to authenticate clients by verifying their provided TLS certificate is valid and trusted. Hence, the client will not be sent a password prompt. + +You can enable this authentication feature additionally specifying the following parameter: + +- `postgresql.tls.certCAFilename`: CA Certificate filename. No defaults. + + ```console + $ psql --host postgresql-ha-pgpool -d "dbname=XXXXX user=YYYYYY sslcert=client.crt sslkey=client.key sslmode=require" + psql (14.4) + SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off) + Type "help" for help. + + postgres=> + ``` + +Clients using this method to authenticate will be required to provide a certificate with the CN (Common Name) field matching the requested database user name. Please, refer to [the official documentation](https://www.postgresql.org/docs/current/auth-cert.html) for further information. + +> Note: As with traditional password-based authentication, database users must exist in both Pgpool-II and PostgreSQL nodes and have the correct privileges to connect to a database. You may use the `postgresql.initdbScripts` and `pgpool.customUsers` properties to create them in advance. + +#### Encrypt traffic between Pgpool-II and PostgreSQL nodes (backend) + +TLS for backend connections can be enabled in the chart by specifying the `postgresql.tls.*` parameters while creating a release. Below you can find detailed information about these parameters: + +- `postgresql.tls.enabled`: Enable TLS support. Defaults to `false` +- `postgresql.tls.certificatesSecret`: Name of an existing secret that contains the certificates. No defaults. +- `postgresql.tls.certFilename`: Certificate filename. No defaults. +- `postgresql.tls.certKeyFilename`: Certificate key filename. No defaults. + +For example: + +- First, create a secret with the certificates files. You will need to generate previously the certificate files: + + ```console + kubectl create secret generic postgresql-tls-secret --from-file=./cert.crt --from-file=./cert.key --from-file=./ca.crt + ``` + +- Then, install the chart using the following parameters: + + ```console + postgresql.tls.enabled=true + postgresql.tls.certificatesSecret="postgresql-tls-secret" + postgresql.tls.certFilename="cert.crt" + postgresql.tls.certKeyFilename="cert.key" + ``` + +> Note: Certificates permissions: PostgreSQL requires certain permissions on sensitive files (such as certificate keys) to start up. Due to an on-going [issue](https://github.com/kubernetes/kubernetes/issues/57923) regarding K8s permissions and the use of `containerSecurityContext.runAsUser`, an init container will adapt the permissions to ensure everything works as expected. + +If you want to encrypt both *frontend* and *backend* traffics, you may use the same secret for Pgpool and PostgreSQL TLS configuration. + +### repmgr.conf / postgresql.conf / pg_hba.conf / pgpool.conf / pool_hba.conf files as configMap + +This Helm chart also supports to customize the whole configuration file. + +You can specify the Pgpool-II, PostgreSQL and Repmgr configuration using the `pgpool.configuration`, `pgpool.poolHbaConfiguration`, `postgresql.configuration`, `postgresql.pgHbaConfiguration`, and `postgresql.repmgrConfiguration` parameters. The corresponding files will be mounted as ConfigMap to the containers and it will be used for configuring Pgpool-II, Repmgr and the PostgreSQL server. + +In addition to this option, you can also set an external ConfigMap(s) with all the configuration files. This is done by setting the `postgresql.configurationCM` and `pgpool.configurationCM` parameters. Note that this will override the 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 specify the extended configuration using the `postgresql.extendedConf` parameter. A file 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`. + +In addition to this option, you can also set an external ConfigMap with all the extra configuration files. This is done by setting the `postgresql.extendedConfCM` parameter. Note that this will override the previous option. + +### Initialize a fresh instance + +The [Bitnami PostgreSQL with Repmgr](https://github.com/bitnami/containers/tree/main/bitnami/postgresql-repmgr) image allows you to use your custom scripts to initialize a fresh instance. You can specify custom scripts using the `initdbScripts` parameter as dict so they can be consumed as a ConfigMap. + +In addition to this option, you can also set an external ConfigMap with all the initialization scripts. This is done by setting the `initdbScriptsCM` 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 above parameters (`initdbScripts`, `initdbScriptsCM`, and `initdbScriptsSecret`) are supported in both StatefulSet by prepending `postgresql` or `pgpool` to the parameter, depending on the use case (see above parameters table). + +The allowed extensions are `.sh`, `.sql` and `.sql.gz` in the **Postgresql** container while only `.sh` in the case of the **Pgpool-II** one. + ++info: and + +### Use of global variables + +In more complex scenarios, we may have the following tree of dependencies + +```text + +--------------+ + | | + +------------+ Chart 1 +-----------+ + | | | | + | --------+------+ | + | | | + | | | + | | | + | | | + v v v ++-------+------+ +--------+------+ +--------+------+ +| | | | | | +| PostgreSQL HA | | 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 HA as well. In order to do so, subcharts 1 and 2 need to know the PostgreSQL HA credentials, so one option for deploying could be deploy Chart 1 with the following parameters: + +```text +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: + +```text +global.postgresql.postgresqlPassword=testtest +global.postgresql.postgresqlDatabase=db1 +``` + +This way, the credentials will be available in all of the sub-charts. + +### Setting Pod's affinity + +This chart allows you to set your custom affinity using the `XXX.affinity` paremeter(s). Find more information about Pod's affinity in the [kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). + +As an alternative, you can use of the preset configurations for pod affinity, pod anti-affinity, and node affinity available at the [bitnami/common](https://github.com/bitnami/charts/tree/main/bitnami/common#affinities) chart. To do so, set the `XXX.podAffinityPreset`, `XXX.podAntiAffinityPreset`, or `XXX.nodeAffinityPreset` parameters. + +### Backup and restore + +To back up and restore Helm chart deployments on Kubernetes, you need to back up the persistent volumes from the source deployment and attach them to a new deployment using [Velero](https://velero.io/), a Kubernetes backup/restore tool. Find the instructions for using Velero in [this guide](https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-backup-restore-deployments-velero-index.html). + +## Persistence + +The data is persisted by default using PVC templates in the PostgreSQL StatefulSet. You can disable the persistence setting the `persistence.enabled` parameter to `false`. +A default `StorageClass` is needed in the Kubernetes cluster to dynamically provision the volumes. Specify another StorageClass in the `persistence.storageClass` or set `persistence.existingClaim` if you have already existing persistent volumes to use. + +## Parameters + +### Global parameters + +| Name | Description | Value | +| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `global.imageRegistry` | Global Docker image registry | `""` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | +| `global.defaultStorageClass` | Global default StorageClass for Persistent Volume(s) | `""` | +| `global.postgresql.username` | PostgreSQL username (overrides `postgresql.username`) | `""` | +| `global.postgresql.password` | PostgreSQL password (overrides `postgresql.password`) | `""` | +| `global.postgresql.database` | PostgreSQL database (overrides `postgresql.database`) | `""` | +| `global.postgresql.repmgrUsername` | PostgreSQL repmgr username (overrides `postgresql.repmgrUsername`) | `""` | +| `global.postgresql.repmgrPassword` | PostgreSQL repmgr password (overrides `postgresql.repmgrpassword`) | `""` | +| `global.postgresql.repmgrDatabase` | PostgreSQL repmgr database (overrides `postgresql.repmgrDatabase`) | `""` | +| `global.postgresql.existingSecret` | Name of existing secret to use for PostgreSQL passwords (overrides `postgresql.existingSecret`) | `""` | +| `global.ldap.bindpw` | LDAP bind password (overrides `ldap.bindpw`) | `""` | +| `global.ldap.existingSecret` | Name of existing secret to use for LDAP passwords (overrides `ldap.existingSecret`) | `""` | +| `global.pgpool.adminUsername` | Pgpool-II Admin username (overrides `pgpool.adminUsername`) | `""` | +| `global.pgpool.adminPassword` | Pgpool-II Admin password (overrides `pgpool.adminPassword`) | `""` | +| `global.pgpool.srCheckUsername` | Pgpool-II SR Check username (overrides `pgpool.srCheckUsername`) | `""` | +| `global.pgpool.srCheckPassword` | Pgpool-II SR Check password (overrides `pgpool.srCheckPassword`) | `""` | +| `global.pgpool.existingSecret` | Pgpool-II existing secret | `""` | +| `global.security.allowInsecureImages` | Allows skipping image verification | `false` | +| `global.compatibility.openshift.adaptSecurityContext` | Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) | `auto` | + +### Common parameters + +| Name | Description | Value | +| ------------------------ | --------------------------------------------------------------------------------------------------- | --------------- | +| `kubeVersion` | Override Kubernetes version | `""` | +| `nameOverride` | String to partially override common.names.fullname template (will maintain the release name) | `""` | +| `fullnameOverride` | String to fully override common.names.fullname template | `""` | +| `namespaceOverride` | String to fully override common.names.namespace | `""` | +| `commonLabels` | Common labels to add to all resources (sub-charts are not considered). Evaluated as a template | `{}` | +| `commonAnnotations` | Common annotations to add to all resources (sub-charts are not considered). Evaluated as a template | `{}` | +| `clusterDomain` | Kubernetes Cluster Domain | `cluster.local` | +| `extraDeploy` | Array of extra objects to deploy with the release (evaluated as a template) | `[]` | +| `diagnosticMode.enabled` | Enable diagnostic mode (all probes will be disabled and the command will be overridden) | `false` | +| `diagnosticMode.command` | Command to override all containers in the deployment | `[]` | +| `diagnosticMode.args` | Args to override all containers in the deployment | `[]` | + +### PostgreSQL with Repmgr parameters + +| Name | Description | Value | +| -------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | +| `postgresql.image.registry` | PostgreSQL with Repmgr image registry | `REGISTRY_NAME` | +| `postgresql.image.repository` | PostgreSQL with Repmgr image repository | `REPOSITORY_NAME/postgresql-repmgr` | +| `postgresql.image.digest` | PostgreSQL with Repmgr image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `postgresql.image.pullPolicy` | PostgreSQL with Repmgr image pull policy | `IfNotPresent` | +| `postgresql.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `postgresql.image.debug` | Specify if debug logs should be enabled | `false` | +| `postgresql.labels` | Labels to add to the StatefulSet. Evaluated as template | `{}` | +| `postgresql.podLabels` | Labels to add to the StatefulSet pods. Evaluated as template | `{}` | +| `postgresql.serviceAnnotations` | Provide any additional annotations for PostgreSQL service | `{}` | +| `postgresql.replicaCount` | Number of replicas to deploy. Use an odd number. Having 3 replicas is the minimum to get quorum when promoting a new primary. | `3` | +| `postgresql.updateStrategy.type` | Postgresql StatefulSet strategy type | `RollingUpdate` | +| `postgresql.containerPorts.postgresql` | PostgreSQL port | `5432` | +| `postgresql.automountServiceAccountToken` | Mount Service Account token in pod | `false` | +| `postgresql.hostAliases` | Deployment pod host aliases | `[]` | +| `postgresql.hostNetwork` | Specify if host network should be enabled for PostgreSQL pod | `false` | +| `postgresql.hostIPC` | Specify if host IPC should be enabled for PostgreSQL pod | `false` | +| `postgresql.podAnnotations` | Additional pod annotations | `{}` | +| `postgresql.podAffinityPreset` | PostgreSQL pod affinity preset. Ignored if `postgresql.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `postgresql.podAntiAffinityPreset` | PostgreSQL pod anti-affinity preset. Ignored if `postgresql.affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `postgresql.nodeAffinityPreset.type` | PostgreSQL node affinity preset type. Ignored if `postgresql.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `postgresql.nodeAffinityPreset.key` | PostgreSQL node label key to match Ignored if `postgresql.affinity` is set. | `""` | +| `postgresql.nodeAffinityPreset.values` | PostgreSQL node label values to match. Ignored if `postgresql.affinity` is set. | `[]` | +| `postgresql.affinity` | Affinity for PostgreSQL pods assignment | `{}` | +| `postgresql.nodeSelector` | Node labels for PostgreSQL pods assignment | `{}` | +| `postgresql.tolerations` | Tolerations for PostgreSQL pods assignment | `[]` | +| `postgresql.topologySpreadConstraints` | Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template | `[]` | +| `postgresql.priorityClassName` | Pod priority class | `""` | +| `postgresql.schedulerName` | Use an alternate scheduler, e.g. "stork". | `""` | +| `postgresql.terminationGracePeriodSeconds` | Seconds PostgreSQL pod needs to terminate gracefully | `""` | +| `postgresql.podSecurityContext.enabled` | Enable security context for PostgreSQL with Repmgr | `true` | +| `postgresql.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `postgresql.podSecurityContext.sysctls` | Set kernel settings using the sysctl interface | `[]` | +| `postgresql.podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `postgresql.podSecurityContext.fsGroup` | Group ID for the PostgreSQL with Repmgr filesystem | `1001` | +| `postgresql.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `postgresql.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `postgresql.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `postgresql.containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `postgresql.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `postgresql.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `postgresql.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `postgresql.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `postgresql.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `postgresql.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `postgresql.command` | Override default container command (useful when using custom images) | `[]` | +| `postgresql.args` | Override default container args (useful when using custom images) | `[]` | +| `postgresql.lifecycleHooks` | LifecycleHook to set additional configuration at startup, e.g. LDAP settings via REST API. Evaluated as a template | `{}` | +| `postgresql.extraEnvVars` | Array containing extra environment variables | `[]` | +| `postgresql.extraEnvVarsCM` | ConfigMap with extra environment variables | `""` | +| `postgresql.extraEnvVarsSecret` | Secret with extra environment variables | `""` | +| `postgresql.extraVolumes` | Extra volumes to add to the StatefulSet | `[]` | +| `postgresql.extraVolumeMounts` | Extra volume mounts to add to the container. Normally used with `extraVolumes`. | `[]` | +| `postgresql.initContainers` | Extra init containers to add to the StatefulSet | `[]` | +| `postgresql.sidecars` | Extra sidecar containers to add to the StatefulSet | `[]` | +| `postgresql.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if postgresql.resources is set (postgresql.resources is recommended for production). | `micro` | +| `postgresql.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `postgresql.podManagementPolicy` | Sets the pod management policy | `Parallel` | +| `postgresql.livenessProbe.enabled` | Enable livenessProbe | `true` | +| `postgresql.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `15` | +| `postgresql.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `postgresql.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `postgresql.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `postgresql.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `postgresql.readinessProbe.enabled` | Enable readinessProbe | `true` | +| `postgresql.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `postgresql.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `postgresql.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` | +| `postgresql.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `postgresql.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `postgresql.startupProbe.enabled` | Enable startupProbe | `false` | +| `postgresql.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `5` | +| `postgresql.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `postgresql.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `postgresql.startupProbe.failureThreshold` | Failure threshold for startupProbe | `10` | +| `postgresql.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `postgresql.customLivenessProbe` | Override default liveness probe | `{}` | +| `postgresql.customReadinessProbe` | Override default readiness probe | `{}` | +| `postgresql.customStartupProbe` | Override default startup probe | `{}` | +| `postgresql.networkPolicy.enabled` | Specifies whether a NetworkPolicy should be created | `true` | +| `postgresql.networkPolicy.allowExternal` | Don't require server label for connections | `true` | +| `postgresql.networkPolicy.allowExternalEgress` | Allow the pod to access any range of port and all destinations. | `true` | +| `postgresql.networkPolicy.extraIngress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `postgresql.networkPolicy.extraEgress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `postgresql.networkPolicy.ingressNSMatchLabels` | Labels to match to allow traffic from other namespaces | `{}` | +| `postgresql.networkPolicy.ingressNSPodMatchLabels` | Pod labels to match to allow traffic from other namespaces | `{}` | +| `postgresql.pdb.create` | Specifies whether to create a Pod disruption budget for PostgreSQL with Repmgr | `true` | +| `postgresql.pdb.minAvailable` | Minimum number / percentage of pods that should remain scheduled | `""` | +| `postgresql.pdb.maxUnavailable` | Maximum number/percentage of pods that may be made unavailable. Defaults to `1` if both `postgresql.pdb.minAvailable` and `postgresql.pdb.maxUnavailable` are empty. | `""` | +| `postgresql.username` | PostgreSQL username | `postgres` | +| `postgresql.password` | PostgreSQL password | `""` | +| `postgresql.database` | PostgreSQL database | `""` | +| `postgresql.existingSecret` | PostgreSQL password using existing secret | `""` | +| `postgresql.postgresPassword` | PostgreSQL password for the `postgres` user when `username` is not `postgres` | `""` | +| `postgresql.usePasswordFiles` | Set to `true` to mount PostgreSQL secret as a file instead of passing environment variable | `true` | +| `postgresql.pgHbaTrustAll` | Configures PostgreSQL HBA to trust every user | `false` | +| `postgresql.syncReplication` | Enable synchronous replication synchronous, waiting until data is synchronized in every replica before other queries can be run | `false` | +| `postgresql.syncReplicationMode` | This specifies the method to choose synchronous standbys from the listed servers. Valid values: empty, FIRST, ANY. | `""` | +| `postgresql.repmgrUsername` | PostgreSQL Repmgr username | `repmgr` | +| `postgresql.repmgrPassword` | PostgreSQL Repmgr password | `""` | +| `postgresql.repmgrDatabase` | PostgreSQL Repmgr database | `repmgr` | +| `postgresql.repmgrUsePassfile` | Configure Repmgr to use `passfile` instead of `password` vars*:*:*:username:password" | `true` | +| `postgresql.repmgrPassfilePath` | Custom path where `passfile` will be stored | `""` | +| `postgresql.repmgrLogLevel` | Repmgr log level (DEBUG, INFO, NOTICE, WARNING, ERROR, ALERT, CRIT or EMERG) | `NOTICE` | +| `postgresql.repmgrConnectTimeout` | Repmgr backend connection timeout (in seconds) | `5` | +| `postgresql.repmgrReconnectAttempts` | Repmgr backend reconnection attempts | `2` | +| `postgresql.repmgrReconnectInterval` | Repmgr backend reconnection interval (in seconds) | `3` | +| `postgresql.repmgrFenceOldPrimary` | Set if fencing of old primary in multiple primary situation is desired | `false` | +| `postgresql.repmgrChildNodesCheckInterval` | Repmgr child nodes check interval (in seconds) | `5` | +| `postgresql.repmgrChildNodesConnectedMinCount` | Repmgr minimum number of connected child nodes before being considered as failed primary for fencing | `1` | +| `postgresql.repmgrChildNodesDisconnectTimeout` | Repmgr time before node will be fenced when insufficient child nodes are detected (in seconds) | `30` | +| `postgresql.upgradeRepmgrExtension` | Upgrade Repmgr extension in the database | `false` | +| `postgresql.usePgRewind` | Use pg_rewind for standby failover (experimental) | `false` | +| `postgresql.audit.logHostname` | Add client hostnames to the log file | `true` | +| `postgresql.audit.logConnections` | Add client log-in operations to the log file | `false` | +| `postgresql.audit.logDisconnections` | Add client log-outs operations to the log file | `false` | +| `postgresql.audit.pgAuditLog` | Add operations to log using the pgAudit extension | `""` | +| `postgresql.audit.pgAuditLogCatalog` | Log catalog using pgAudit | `off` | +| `postgresql.audit.clientMinMessages` | Message log level to share with the user | `error` | +| `postgresql.audit.logLinePrefix` | Template string for the log line prefix | `""` | +| `postgresql.audit.logTimezone` | Timezone for the log timestamps | `""` | +| `postgresql.sharedPreloadLibraries` | Shared preload libraries (comma-separated list) | `pgaudit, repmgr` | +| `postgresql.maxConnections` | Maximum total connections | `""` | +| `postgresql.postgresConnectionLimit` | Maximum connections for the postgres user | `""` | +| `postgresql.dbUserConnectionLimit` | Maximum connections for the created user | `""` | +| `postgresql.tcpKeepalivesInterval` | TCP keepalives interval | `""` | +| `postgresql.tcpKeepalivesIdle` | TCP keepalives idle | `""` | +| `postgresql.tcpKeepalivesCount` | TCP keepalives count | `""` | +| `postgresql.statementTimeout` | Statement timeout | `""` | +| `postgresql.pghbaRemoveFilters` | Comma-separated list of patterns to remove from the pg_hba.conf file | `""` | +| `postgresql.extraInitContainers` | Extra init containers | `[]` | +| `postgresql.repmgrConfiguration` | Repmgr configuration | `""` | +| `postgresql.configuration` | PostgreSQL configuration | `""` | +| `postgresql.pgHbaConfiguration` | PostgreSQL client authentication configuration | `""` | +| `postgresql.configurationCM` | Name of existing ConfigMap with configuration files | `""` | +| `postgresql.extendedConf` | Extended PostgreSQL configuration (requires `volumePermissions.enabled` to be `true`) | `""` | +| `postgresql.extendedConfCM` | ConfigMap with PostgreSQL extended configuration (requires `volumePermissions.enabled` to be `true`) | `""` | +| `postgresql.initdbScripts` | Dictionary of initdb scripts | `{}` | +| `postgresql.initdbScriptsCM` | ConfigMap with scripts to be run at first boot | `""` | +| `postgresql.initdbScriptsSecret` | Secret with scripts to be run at first boot | `""` | +| `postgresql.tls.enabled` | Enable TLS traffic support for end-client connections | `false` | +| `postgresql.tls.preferServerCiphers` | Whether to use the server's TLS cipher preferences rather than the client's | `true` | +| `postgresql.tls.certificatesSecret` | Name of an existing secret that contains the certificates | `""` | +| `postgresql.tls.certFilename` | Certificate filename | `""` | +| `postgresql.tls.certKeyFilename` | Certificate key filename | `""` | +| `postgresql.preStopDelayAfterPgStopSeconds` | Minimal number of seconds preStop hook waits after PostgreSQL instance is stopped | `25` | +| `postgresql.headlessWithNotReadyAddresses` | set postgres headless service into publishNotReadyAddresses mode | `false` | +| `witness.create` | Create PostgreSQL witness nodes | `false` | +| `witness.labels` | Labels to add to the StatefulSet. Evaluated as template | `{}` | +| `witness.podLabels` | Labels to add to the StatefulSet pods. Evaluated as template | `{}` | +| `witness.replicaCount` | Number of replicas to deploy. | `1` | +| `witness.updateStrategy.type` | Postgresql StatefulSet strategy type | `RollingUpdate` | +| `witness.containerPorts.postgresql` | PostgreSQL witness port | `5432` | +| `witness.automountServiceAccountToken` | Mount Service Account token in pod | `false` | +| `witness.hostAliases` | Deployment pod host aliases | `[]` | +| `witness.hostNetwork` | Specify if host network should be enabled for PostgreSQL witness pod | `false` | +| `witness.hostIPC` | Specify if host IPC should be enabled for PostgreSQL witness pod | `false` | +| `witness.podAnnotations` | Additional pod annotations | `{}` | +| `witness.podAffinityPreset` | PostgreSQL witness pod affinity preset. Ignored if `witness.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `witness.podAntiAffinityPreset` | PostgreSQL witness pod anti-affinity preset. Ignored if `witness.affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `witness.nodeAffinityPreset.type` | PostgreSQL witness node affinity preset type. Ignored if `witness.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `witness.nodeAffinityPreset.key` | PostgreSQL witness node label key to match Ignored if `witness.affinity` is set. | `""` | +| `witness.nodeAffinityPreset.values` | PostgreSQL witness node label values to match. Ignored if `witness.affinity` is set. | `[]` | +| `witness.affinity` | Affinity for PostgreSQL witness pods assignment | `{}` | +| `witness.nodeSelector` | Node labels for PostgreSQL witness pods assignment | `{}` | +| `witness.tolerations` | Tolerations for PostgreSQL witness pods assignment | `[]` | +| `witness.topologySpreadConstraints` | Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template | `[]` | +| `witness.priorityClassName` | Pod priority class | `""` | +| `witness.schedulerName` | Use an alternate scheduler, e.g. "stork". | `""` | +| `witness.terminationGracePeriodSeconds` | Seconds PostgreSQL witness pod needs to terminate gracefully | `""` | +| `witness.podSecurityContext.enabled` | Enable security context for PostgreSQL witness with Repmgr | `true` | +| `witness.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `witness.podSecurityContext.sysctls` | Set kernel settings using the sysctl interface | `[]` | +| `witness.podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `witness.podSecurityContext.fsGroup` | Group ID for the PostgreSQL witness with Repmgr filesystem | `1001` | +| `witness.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `witness.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `witness.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `witness.containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `witness.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `witness.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `witness.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `witness.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `witness.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `witness.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `witness.command` | Override default container command (useful when using custom images) | `[]` | +| `witness.args` | Override default container args (useful when using custom images) | `[]` | +| `witness.lifecycleHooks` | LifecycleHook to set additional configuration at startup, e.g. LDAP settings via REST API. Evaluated as a template | `{}` | +| `witness.extraEnvVars` | Array containing extra environment variables | `[]` | +| `witness.extraEnvVarsCM` | ConfigMap with extra environment variables | `""` | +| `witness.extraEnvVarsSecret` | Secret with extra environment variables | `""` | +| `witness.extraVolumes` | Extra volumes to add to the deployment | `[]` | +| `witness.extraVolumeMounts` | Extra volume mounts to add to the container. Normally used with `extraVolumes`. | `[]` | +| `witness.initContainers` | Extra init containers to add to the deployment | `[]` | +| `witness.sidecars` | Extra sidecar containers to add to the deployment | `[]` | +| `witness.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if witness.resources is set (witness.resources is recommended for production). | `micro` | +| `witness.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `witness.livenessProbe.enabled` | Enable livenessProbe | `true` | +| `witness.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `30` | +| `witness.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `witness.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `witness.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `witness.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `witness.readinessProbe.enabled` | Enable readinessProbe | `true` | +| `witness.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `witness.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `witness.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` | +| `witness.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `witness.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `witness.startupProbe.enabled` | Enable startupProbe | `false` | +| `witness.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `5` | +| `witness.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `witness.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `witness.startupProbe.failureThreshold` | Failure threshold for startupProbe | `10` | +| `witness.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `witness.customLivenessProbe` | Override default liveness probe | `{}` | +| `witness.customReadinessProbe` | Override default readiness probe | `{}` | +| `witness.customStartupProbe` | Override default startup probe | `{}` | +| `witness.pdb.create` | Specifies whether to create a Pod disruption budget for PostgreSQL witness with Repmgr | `true` | +| `witness.pdb.minAvailable` | Minimum number / percentage of pods that should remain scheduled | `""` | +| `witness.pdb.maxUnavailable` | Maximum number/percentage of pods that may be made unavailable. Defaults to `1` if both `witness.pdb.minAvailable` and `witness.pdb.maxUnavailable` are empty. | `""` | +| `witness.upgradeRepmgrExtension` | Upgrade repmgr extension in the database | `false` | +| `witness.pgHbaTrustAll` | Configures PostgreSQL HBA to trust every user | `false` | +| `witness.repmgrLogLevel` | Repmgr log level (DEBUG, INFO, NOTICE, WARNING, ERROR, ALERT, CRIT or EMERG) | `NOTICE` | +| `witness.repmgrConnectTimeout` | Repmgr backend connection timeout (in seconds) | `5` | +| `witness.repmgrReconnectAttempts` | Repmgr backend reconnection attempts | `2` | +| `witness.repmgrReconnectInterval` | Repmgr backend reconnection interval (in seconds) | `3` | +| `witness.audit.logHostname` | Add client hostnames to the log file | `true` | +| `witness.audit.logConnections` | Add client log-in operations to the log file | `false` | +| `witness.audit.logDisconnections` | Add client log-outs operations to the log file | `false` | +| `witness.audit.pgAuditLog` | Add operations to log using the pgAudit extension | `""` | +| `witness.audit.pgAuditLogCatalog` | Log catalog using pgAudit | `off` | +| `witness.audit.clientMinMessages` | Message log level to share with the user | `error` | +| `witness.audit.logLinePrefix` | Template string for the log line prefix | `""` | +| `witness.audit.logTimezone` | Timezone for the log timestamps | `""` | +| `witness.maxConnections` | Maximum total connections | `""` | +| `witness.postgresConnectionLimit` | Maximum connections for the postgres user | `""` | +| `witness.dbUserConnectionLimit` | Maximum connections for the created user | `""` | +| `witness.tcpKeepalivesInterval` | TCP keepalives interval | `""` | +| `witness.tcpKeepalivesIdle` | TCP keepalives idle | `""` | +| `witness.tcpKeepalivesCount` | TCP keepalives count | `""` | +| `witness.statementTimeout` | Statement timeout | `""` | +| `witness.pghbaRemoveFilters` | Comma-separated list of patterns to remove from the pg_hba.conf file | `""` | +| `witness.extraInitContainers` | Extra init containers | `[]` | +| `witness.repmgrConfiguration` | Repmgr configuration | `""` | +| `witness.configuration` | PostgreSQL configuration | `""` | +| `witness.pgHbaConfiguration` | PostgreSQL client authentication configuration | `""` | +| `witness.configurationCM` | Name of existing ConfigMap with configuration files | `""` | +| `witness.extendedConf` | Extended PostgreSQL configuration (requires `volumePermissions.enabled` to be `true`) | `""` | +| `witness.extendedConfCM` | ConfigMap with PostgreSQL extended configuration (requires `volumePermissions.enabled` to be `true`) | `""` | +| `witness.initdbScripts` | Dictionary of initdb scripts | `{}` | +| `witness.initdbScriptsCM` | ConfigMap with scripts to be run at first boot | `""` | +| `witness.initdbScriptsSecret` | Secret with scripts to be run at first boot | `""` | + +### Pgpool-II parameters + +| Name | Description | Value | +| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | +| `pgpool.image.registry` | Pgpool-II image registry | `REGISTRY_NAME` | +| `pgpool.image.repository` | Pgpool-II image repository | `REPOSITORY_NAME/pgpool` | +| `pgpool.image.digest` | Pgpool-II image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `pgpool.image.pullPolicy` | Pgpool-II image pull policy | `IfNotPresent` | +| `pgpool.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `pgpool.image.debug` | Specify if debug logs should be enabled | `false` | +| `pgpool.customUsers.usernames` | Comma or semicolon separated list of additional users that will be performing connections to the database using pgpool. | `""` | +| `pgpool.customUsers.passwords` | Comma or semicolon separated list of the associated passwords for the users above. Must have the same number of elements as the usernames list. | `""` | +| `pgpool.automountServiceAccountToken` | Mount Service Account token in pod | `false` | +| `pgpool.hostAliases` | Deployment pod host aliases | `[]` | +| `pgpool.customUsersSecret` | Name of a secret containing the usernames and passwords of accounts that will be added to pgpool_passwd | `""` | +| `pgpool.existingSecret` | Pgpool-II admin password using existing secret | `""` | +| `pgpool.labels` | Labels to add to the Deployment. Evaluated as template | `{}` | +| `pgpool.podLabels` | Labels to add to the pods. Evaluated as template | `{}` | +| `pgpool.serviceLabels` | Labels to add to the service. Evaluated as template | `{}` | +| `pgpool.serviceAnnotations` | Provide any additional annotations for Pgpool-II service | `{}` | +| `pgpool.customLivenessProbe` | Override default liveness probe | `{}` | +| `pgpool.customReadinessProbe` | Override default readiness probe | `{}` | +| `pgpool.customStartupProbe` | Override default startup probe | `{}` | +| `pgpool.command` | Override default container command (useful when using custom images) | `[]` | +| `pgpool.args` | Override default container args (useful when using custom images) | `[]` | +| `pgpool.lifecycleHooks` | LifecycleHook to set additional configuration at startup, e.g. LDAP settings via REST API. Evaluated as a template | `{}` | +| `pgpool.extraEnvVars` | Array containing extra environment variables | `[]` | +| `pgpool.extraEnvVarsCM` | ConfigMap with extra environment variables | `""` | +| `pgpool.extraEnvVarsSecret` | Secret with extra environment variables | `""` | +| `pgpool.extraVolumes` | Extra volumes to add to the deployment | `[]` | +| `pgpool.extraVolumeMounts` | Extra volume mounts to add to the container. Normally used with `extraVolumes` | `[]` | +| `pgpool.initContainers` | Extra init containers to add to the deployment | `[]` | +| `pgpool.sidecars` | Extra sidecar containers to add to the deployment | `[]` | +| `pgpool.replicaCount` | The number of replicas to deploy | `1` | +| `pgpool.podAnnotations` | Additional pod annotations | `{}` | +| `pgpool.priorityClassName` | Pod priority class | `""` | +| `pgpool.schedulerName` | Use an alternate scheduler, e.g. "stork". | `""` | +| `pgpool.terminationGracePeriodSeconds` | Seconds pgpool pod needs to terminate gracefully | `""` | +| `pgpool.topologySpreadConstraints` | Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template | `[]` | +| `pgpool.podAffinityPreset` | Pgpool-II pod affinity preset. Ignored if `pgpool.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `pgpool.podAntiAffinityPreset` | Pgpool-II pod anti-affinity preset. Ignored if `pgpool.affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `pgpool.nodeAffinityPreset.type` | Pgpool-II node affinity preset type. Ignored if `pgpool.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `pgpool.nodeAffinityPreset.key` | Pgpool-II node label key to match Ignored if `pgpool.affinity` is set. | `""` | +| `pgpool.nodeAffinityPreset.values` | Pgpool-II node label values to match. Ignored if `pgpool.affinity` is set. | `[]` | +| `pgpool.affinity` | Affinity for Pgpool-II pods assignment | `{}` | +| `pgpool.nodeSelector` | Node labels for Pgpool-II pods assignment | `{}` | +| `pgpool.tolerations` | Tolerations for Pgpool-II pods assignment | `[]` | +| `pgpool.podSecurityContext.enabled` | Enable security context for Pgpool-II | `true` | +| `pgpool.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `pgpool.podSecurityContext.sysctls` | Set kernel settings using the sysctl interface | `[]` | +| `pgpool.podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `pgpool.podSecurityContext.fsGroup` | Group ID for the Pgpool-II filesystem | `1001` | +| `pgpool.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `pgpool.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `pgpool.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `pgpool.containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `pgpool.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `pgpool.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `pgpool.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `pgpool.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `pgpool.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `pgpool.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `pgpool.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if pgpool.resources is set (pgpool.resources is recommended for production). | `micro` | +| `pgpool.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `pgpool.livenessProbe.enabled` | Enable livenessProbe | `true` | +| `pgpool.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `30` | +| `pgpool.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `pgpool.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `pgpool.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `3` | +| `pgpool.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `pgpool.readinessProbe.enabled` | Enable readinessProbe | `true` | +| `pgpool.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `pgpool.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `5` | +| `pgpool.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` | +| `pgpool.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `5` | +| `pgpool.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `pgpool.startupProbe.enabled` | Enable startupProbe | `false` | +| `pgpool.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `5` | +| `pgpool.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `pgpool.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `pgpool.startupProbe.failureThreshold` | Failure threshold for startupProbe | `10` | +| `pgpool.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `pgpool.networkPolicy.enabled` | Specifies whether a NetworkPolicy should be created | `true` | +| `pgpool.networkPolicy.allowExternal` | Don't require server label for connections | `true` | +| `pgpool.networkPolicy.allowExternalEgress` | Allow the pod to access any range of port and all destinations. | `true` | +| `pgpool.networkPolicy.extraIngress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `pgpool.networkPolicy.extraEgress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `pgpool.networkPolicy.ingressNSMatchLabels` | Labels to match to allow traffic from other namespaces | `{}` | +| `pgpool.networkPolicy.ingressNSPodMatchLabels` | Pod labels to match to allow traffic from other namespaces | `{}` | +| `pgpool.pdb.create` | Specifies whether a Pod disruption budget should be created for Pgpool-II pods | `true` | +| `pgpool.pdb.minAvailable` | Minimum number / percentage of pods that should remain scheduled | `""` | +| `pgpool.pdb.maxUnavailable` | Maximum number/percentage of pods that may be made unavailable. Defaults to `1` if both `pgpool.pdb.minAvailable` and `pgpool.pdb.maxUnavailable` are empty. | `""` | +| `pgpool.updateStrategy` | Strategy used to replace old Pods by new ones | `{}` | +| `pgpool.containerPorts.postgresql` | Pgpool-II port | `5432` | +| `pgpool.minReadySeconds` | How many seconds a pod needs to be ready before killing the next, during update | `""` | +| `pgpool.adminUsername` | Pgpool-II Admin username | `admin` | +| `pgpool.adminPassword` | Pgpool-II Admin password | `""` | +| `pgpool.srCheckUsername` | Pgpool-II Streaming Replication Check username | `sr_check_user` | +| `pgpool.srCheckPassword` | Pgpool-II Streaming Replication Check password | `""` | +| `pgpool.srCheckDatabase` | Name of the database to perform Streaming Replication Check | `postgres` | +| `pgpool.usePasswordFiles` | Set to `true` to mount pgpool secret as a file instead of passing environment variable | `true` | +| `pgpool.authenticationMethod` | Pgpool authentication method. Use 'md5' for PSQL < 14. | `scram-sha-256` | +| `pgpool.logConnections` | Log all client connections (PGPOOL_ENABLE_LOG_CONNECTIONS) | `false` | +| `pgpool.logHostname` | Log the client hostname instead of IP address (PGPOOL_ENABLE_LOG_HOSTNAME) | `true` | +| `pgpool.logPcpProcesses` | Log PCP processes (PGPOOL_ENABLE_LOG_PCP_PROCESSES) | `true` | +| `pgpool.logPerNodeStatement` | Log every SQL statement for each DB node separately (PGPOOL_ENABLE_LOG_PER_NODE_STATEMENT) | `false` | +| `pgpool.logLinePrefix` | Format of the log entry lines (PGPOOL_LOG_LINE_PREFIX) | `""` | +| `pgpool.clientMinMessages` | Log level for clients | `error` | +| `pgpool.numInitChildren` | The number of preforked Pgpool-II server processes. It is also the concurrent | `""` | +| `pgpool.reservedConnections` | Number of reserved connections. When zero, excess connection block. When non-zero, excess connections are refused with an error message. | `1` | +| `pgpool.maxPool` | The maximum number of cached connections in each child process (PGPOOL_MAX_POOL) | `""` | +| `pgpool.childMaxConnections` | The maximum number of client connections in each child process (PGPOOL_CHILD_MAX_CONNECTIONS) | `""` | +| `pgpool.childLifeTime` | The time in seconds to terminate a Pgpool-II child process if it remains idle (PGPOOL_CHILD_LIFE_TIME) | `""` | +| `pgpool.clientIdleLimit` | The time in seconds to disconnect a client if it remains idle since the last query (PGPOOL_CLIENT_IDLE_LIMIT) | `""` | +| `pgpool.connectionLifeTime` | The time in seconds to terminate the cached connections to the PostgreSQL backend (PGPOOL_CONNECTION_LIFE_TIME) | `""` | +| `pgpool.useConnectionCache` | Use connection cache (PGPOOL_ENABLE_CONNECTION_CACHE) | `true` | +| `pgpool.useLoadBalancing` | Use Pgpool-II Load-Balancing | `true` | +| `pgpool.disableLoadBalancingOnWrite` | LoadBalancer on write actions behavior | `transaction` | +| `pgpool.configuration` | Pgpool-II configuration | `""` | +| `pgpool.poolHbaConfiguration` | Pgpool-II client authentication configuration | `""` | +| `pgpool.configurationCM` | ConfigMap with Pgpool-II configuration | `""` | +| `pgpool.initdbScripts` | Dictionary of initdb scripts | `{}` | +| `pgpool.initdbScriptsCM` | ConfigMap with scripts to be run every time Pgpool-II container is initialized | `""` | +| `pgpool.initdbScriptsSecret` | Secret with scripts to be run every time Pgpool-II container is initialized | `""` | +| `pgpool.tls.enabled` | Enable TLS traffic support for end-client connections | `false` | +| `pgpool.tls.autoGenerated` | Create self-signed TLS certificates. Currently only supports PEM certificates | `false` | +| `pgpool.tls.preferServerCiphers` | Whether to use the server's TLS cipher preferences rather than the client's | `true` | +| `pgpool.tls.certificatesSecret` | Name of an existing secret that contains the certificates | `""` | +| `pgpool.tls.certFilename` | Certificate filename | `""` | +| `pgpool.tls.certKeyFilename` | Certificate key filename | `""` | +| `pgpool.tls.certCAFilename` | CA Certificate filename | `""` | + +### LDAP parameters + +| Name | Description | Value | +| ------------------------------- | ------------------------------------------------------------ | ------------ | +| `ldap.enabled` | Enable LDAP support | `false` | +| `ldap.existingSecret` | Name of existing secret to use for LDAP passwords | `""` | +| `ldap.uri` | LDAP URL beginning in the form `ldap[s]://:` | `""` | +| `ldap.basedn` | LDAP base DN | `""` | +| `ldap.binddn` | LDAP bind DN | `""` | +| `ldap.bindpw` | LDAP bind password | `""` | +| `ldap.bslookup` | LDAP base lookup | `""` | +| `ldap.scope` | LDAP search scope | `""` | +| `ldap.searchfilter` | LDAP search filter | `""` | +| `ldap.searchmap` | LDAP search map | `""` | +| `ldap.tlsReqcert` | LDAP TLS check on server certificates | `""` | +| `ldap.nssInitgroupsIgnoreusers` | LDAP ignored users | `root,nslcd` | + +### Other Parameters + +| Name | Description | Value | +| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `rbac.create` | Create Role and RoleBinding (required for PSP to work) | `false` | +| `rbac.rules` | Custom RBAC rules to set | `[]` | +| `serviceAccount.create` | Specifies whether a ServiceAccount should be created | `true` | +| `serviceAccount.name` | The name of the ServiceAccount to use. | `""` | +| `serviceAccount.annotations` | Additional custom annotations for the ServiceAccount | `{}` | +| `serviceAccount.automountServiceAccountToken` | Allows auto mount of ServiceAccountToken on the serviceAccount created | `false` | +| `psp.create` | Whether to create a PodSecurityPolicy. WARNING: PodSecurityPolicy is deprecated in Kubernetes v1.21 or later, unavailable in v1.25 or later | `false` | + +### Metrics parameters + +| Name | Description | Value | +| ------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | +| `metrics.enabled` | Enable PostgreSQL Prometheus exporter | `false` | +| `metrics.image.registry` | PostgreSQL Prometheus exporter image registry | `REGISTRY_NAME` | +| `metrics.image.repository` | PostgreSQL Prometheus exporter image repository | `REPOSITORY_NAME/postgres-exporter` | +| `metrics.image.digest` | PostgreSQL Prometheus exporter image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `metrics.image.pullPolicy` | PostgreSQL Prometheus exporter image pull policy | `IfNotPresent` | +| `metrics.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `metrics.image.debug` | Specify if debug logs should be enabled | `false` | +| `metrics.podSecurityContext.enabled` | Enable security context for PostgreSQL Prometheus exporter | `true` | +| `metrics.podSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `metrics.podSecurityContext.runAsUser` | User ID for the PostgreSQL Prometheus exporter container | `1001` | +| `metrics.podSecurityContext.runAsGroup` | Group ID for the PostgreSQL Prometheus exporter container | `1001` | +| `metrics.podSecurityContext.runAsNonRoot` | Set PostgreSQL Prometheus exporter container's Security Context runAsNonRoot | `true` | +| `metrics.podSecurityContext.seccompProfile.type` | Set PostgreSQL Prometheus exporter container's Security Context seccompProfile | `RuntimeDefault` | +| `metrics.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if metrics.resources is set (metrics.resources is recommended for production). | `nano` | +| `metrics.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `metrics.containerPorts.http` | Prometheus metrics exporter port | `9187` | +| `metrics.livenessProbe.enabled` | Enable livenessProbe | `true` | +| `metrics.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `30` | +| `metrics.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `metrics.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `metrics.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `metrics.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `metrics.readinessProbe.enabled` | Enable readinessProbe | `true` | +| `metrics.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `metrics.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `metrics.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` | +| `metrics.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `metrics.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `metrics.startupProbe.enabled` | Enable startupProbe | `false` | +| `metrics.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `5` | +| `metrics.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `metrics.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `metrics.startupProbe.failureThreshold` | Failure threshold for startupProbe | `10` | +| `metrics.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `metrics.customLivenessProbe` | Override default liveness probe | `{}` | +| `metrics.customReadinessProbe` | Override default readiness probe | `{}` | +| `metrics.customStartupProbe` | Override default startup probe | `{}` | +| `metrics.service.enabled` | PostgreSQL Prometheus exporter metrics service enabled | `true` | +| `metrics.service.type` | PostgreSQL Prometheus exporter metrics service type | `ClusterIP` | +| `metrics.service.ports.metrics` | PostgreSQL Prometheus exporter metrics service port | `9187` | +| `metrics.service.nodePorts.metrics` | PostgreSQL Prometheus exporter Node Port | `""` | +| `metrics.service.clusterIP` | PostgreSQL Prometheus exporter metrics service Cluster IP | `""` | +| `metrics.service.loadBalancerIP` | PostgreSQL Prometheus exporter service Load Balancer IP | `""` | +| `metrics.service.loadBalancerSourceRanges` | PostgreSQL Prometheus exporter service Load Balancer sources | `[]` | +| `metrics.service.externalTrafficPolicy` | PostgreSQL Prometheus exporter service external traffic policy | `Cluster` | +| `metrics.annotations` | Annotations for PostgreSQL Prometheus exporter service | `{}` | +| `metrics.customMetrics` | Additional custom metrics | `{}` | +| `metrics.extraEnvVars` | Array containing extra environment variables | `[]` | +| `metrics.extraEnvVarsCM` | ConfigMap with extra environment variables | `""` | +| `metrics.extraEnvVarsSecret` | Secret with extra environment variables | `""` | +| `metrics.serviceMonitor.enabled` | if `true`, creates a Prometheus Operator ServiceMonitor (also requires `metrics.enabled` to be `true`) | `false` | +| `metrics.serviceMonitor.namespace` | Optional namespace which Prometheus is running in | `""` | +| `metrics.serviceMonitor.interval` | How frequently to scrape metrics (use by default, falling back to Prometheus' default) | `""` | +| `metrics.serviceMonitor.scrapeTimeout` | Service monitor scrape timeout | `""` | +| `metrics.serviceMonitor.annotations` | Additional annotations for the ServiceMonitor | `{}` | +| `metrics.serviceMonitor.labels` | Additional labels that can be used so ServiceMonitor will be discovered by Prometheus | `{}` | +| `metrics.serviceMonitor.selector` | Defaults to what's used if you follow CoreOS Prometheus Install Instructions () | `{}` | +| `metrics.serviceMonitor.relabelings` | ServiceMonitor relabelings. Value is evaluated as a template | `[]` | +| `metrics.serviceMonitor.metricRelabelings` | ServiceMonitor metricRelabelings. Value is evaluated as a template | `[]` | +| `metrics.serviceMonitor.honorLabels` | Specify honorLabels parameter to add the scrape endpoint | `false` | +| `metrics.serviceMonitor.jobLabel` | The name of the label on the target service to use as the job name in prometheus. | `""` | + +### Volume permissions parameters + +| Name | Description | Value | +| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | +| `volumePermissions.enabled` | Enable init container to adapt volume permissions | `false` | +| `volumePermissions.image.registry` | Init container volume-permissions image registry | `REGISTRY_NAME` | +| `volumePermissions.image.repository` | Init container volume-permissions image repository | `REPOSITORY_NAME/os-shell` | +| `volumePermissions.image.digest` | Init container volume-permissions image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `volumePermissions.image.pullPolicy` | Init container volume-permissions image pull policy | `IfNotPresent` | +| `volumePermissions.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `volumePermissions.podSecurityContext.enabled` | Whether to enable security context for the volume-permissions init container | `true` | +| `volumePermissions.podSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `volumePermissions.podSecurityContext.runAsUser` | Init container volume-permissions User ID | `0` | +| `volumePermissions.podSecurityContext.runAsGroup` | Group ID for the init container volume-permissions container | `0` | +| `volumePermissions.podSecurityContext.runAsNonRoot` | Set Security Context runAsNonRoot for the init container volume-permissions container | `false` | +| `volumePermissions.podSecurityContext.seccompProfile.type` | Set Security Context seccompProfile for the init container volume-permissions container | `RuntimeDefault` | +| `volumePermissions.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if volumePermissions.resources is set (volumePermissions.resources is recommended for production). | `nano` | +| `volumePermissions.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | + +### Persistence parameters + +| Name | Description | Value | +| -------------------------------------------------- | --------------------------------------------------------------------------------------- | --------------------- | +| `persistence.enabled` | Enable data persistence | `true` | +| `persistence.existingClaim` | A manually managed Persistent Volume and Claim | `""` | +| `persistence.storageClass` | Persistent Volume Storage Class | `""` | +| `persistence.mountPath` | The path the volume will be mounted at, useful when using different PostgreSQL images. | `/bitnami/postgresql` | +| `persistence.accessModes` | List of access modes of data volume | `["ReadWriteOnce"]` | +| `persistence.size` | Persistent Volume Claim size | `8Gi` | +| `persistence.annotations` | Persistent Volume Claim annotations | `{}` | +| `persistence.labels` | Persistent Volume Claim labels | `{}` | +| `persistence.selector` | Selector to match an existing Persistent Volume (this value is evaluated as a template) | `{}` | +| `persistentVolumeClaimRetentionPolicy.enabled` | Enable Persistent volume retention policy for postgresql Statefulset | `false` | +| `persistentVolumeClaimRetentionPolicy.whenScaled` | Volume retention behavior when the replica count of the StatefulSet is reduced | `Retain` | +| `persistentVolumeClaimRetentionPolicy.whenDeleted` | Volume retention behavior that applies when the StatefulSet is deleted | `Retain` | + +### Traffic Exposure parameters + +| Name | Description | Value | +| ---------------------------------- | ----------------------------------------------------------------------------- | ------------ | +| `service.type` | Kubernetes service type (`ClusterIP`, `NodePort` or `LoadBalancer`) | `ClusterIP` | +| `service.ports.postgresql` | PostgreSQL port | `5432` | +| `service.portName` | PostgreSQL service port name | `postgresql` | +| `service.nodePorts.postgresql` | Kubernetes service nodePort | `""` | +| `service.loadBalancerIP` | Load balancer IP if service type is `LoadBalancer` | `""` | +| `service.loadBalancerSourceRanges` | Addresses that are allowed when service is LoadBalancer | `[]` | +| `service.clusterIP` | Set the Cluster IP to use | `""` | +| `service.externalTrafficPolicy` | Enable client source IP preservation | `Cluster` | +| `service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `service.sessionAffinity` | Control where client requests go, to the same pod or round-robin | `None` | +| `service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `service.annotations` | Provide any additional annotations both for PostgreSQL and Pgpool-II services | `{}` | +| `service.serviceLabels` | Labels for PostgreSQL service | `{}` | +| `service.headless.annotations` | Annotations for the headless service. | `{}` | + +### Backup parameters + +| Name | Description | Value | +| ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `backup.enabled` | Enable the logical dump of the database "regularly" | `false` | +| `backup.cronjob.schedule` | Set the cronjob parameter schedule | `@daily` | +| `backup.cronjob.timeZone` | Set the cronjob parameter timeZone | `""` | +| `backup.cronjob.concurrencyPolicy` | Set the cronjob parameter concurrencyPolicy | `Allow` | +| `backup.cronjob.failedJobsHistoryLimit` | Set the cronjob parameter failedJobsHistoryLimit | `1` | +| `backup.cronjob.successfulJobsHistoryLimit` | Set the cronjob parameter successfulJobsHistoryLimit | `3` | +| `backup.cronjob.startingDeadlineSeconds` | Set the cronjob parameter startingDeadlineSeconds | `""` | +| `backup.cronjob.ttlSecondsAfterFinished` | Set the cronjob parameter ttlSecondsAfterFinished | `""` | +| `backup.cronjob.restartPolicy` | Set the cronjob parameter restartPolicy | `OnFailure` | +| `backup.cronjob.podSecurityContext.enabled` | Enable PodSecurityContext for CronJob/Backup | `true` | +| `backup.cronjob.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `backup.cronjob.podSecurityContext.sysctls` | Set kernel settings using the sysctl interface | `[]` | +| `backup.cronjob.podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `backup.cronjob.podSecurityContext.fsGroup` | Group ID for the CronJob | `1001` | +| `backup.cronjob.containerSecurityContext.enabled` | Enable container security context | `true` | +| `backup.cronjob.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `backup.cronjob.containerSecurityContext.runAsUser` | User ID for the backup container | `1001` | +| `backup.cronjob.containerSecurityContext.runAsGroup` | Group ID for the backup container | `1001` | +| `backup.cronjob.containerSecurityContext.runAsNonRoot` | Set backup container's Security Context runAsNonRoot | `true` | +| `backup.cronjob.containerSecurityContext.readOnlyRootFilesystem` | Is the container itself readonly | `true` | +| `backup.cronjob.containerSecurityContext.allowPrivilegeEscalation` | Is it possible to escalate backup pod(s) privileges | `false` | +| `backup.cronjob.containerSecurityContext.seccompProfile.type` | Set backup container's Security Context seccompProfile type | `RuntimeDefault` | +| `backup.cronjob.containerSecurityContext.capabilities.drop` | Set backup container's Security Context capabilities to drop | `["ALL"]` | +| `backup.cronjob.command` | Set backup container's command to run | `["/bin/bash","-c","PGPASSWORD=\"${PGPASSWORD:-$(< \"$PGPASSWORD_FILE\")}\" pg_dumpall --clean --if-exists --load-via-partition-root --quote-all-identifiers --no-password --file=\"${PGDUMP_DIR}/pg_dumpall-$(date '+%Y-%m-%d-%H-%M').pgdump\""]` | +| `backup.cronjob.labels` | Set the cronjob labels | `{}` | +| `backup.cronjob.annotations` | Set the cronjob annotations | `{}` | +| `backup.cronjob.nodeSelector` | Node labels for PostgreSQL backup CronJob pod assignment | `{}` | +| `backup.cronjob.tolerations` | Tolerations for PostgreSQL backup CronJob pod assignment | `[]` | +| `backup.cronjob.podAffinityPreset` | PostgreSQL backup pod affinity preset. Ignored if `backup.cronjob.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `backup.cronjob.nodeAffinityPreset.type` | PostgreSQL backup node affinity preset type. Ignored if `backup.cronjob.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `backup.cronjob.nodeAffinityPreset.key` | PostgreSQL backup node label key to match Ignored if `backup.cronjob.affinity` is set. | `""` | +| `backup.cronjob.nodeAffinityPreset.values` | PostgreSQL backup node label values to match. Ignored if `backup.cronjob.affinity` is set. | `[]` | +| `backup.cronjob.affinity` | Affinity for PostgreSQL backup pods assignment | `{}` | +| `backup.cronjob.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if backup.cronjob.resources is set (backup.cronjob.resources is recommended for production). | `nano` | +| `backup.cronjob.resources` | Set container requests and limits for different resources like CPU or memory | `{}` | +| `backup.cronjob.extraEnvVars` | Array containing extra environment variables | `[]` | +| `backup.cronjob.extraEnvVarsCM` | ConfigMap with extra environment variables | `""` | +| `backup.cronjob.extraEnvVarsSecret` | Secret with extra environment variables | `""` | +| `backup.cronjob.extraVolumes` | Extra volumes to add to the backup container | `[]` | +| `backup.cronjob.extraVolumeMounts` | Extra volume mounts to add to the backup container. Normally used with `extraVolumes` | `[]` | +| `backup.cronjob.storage.existingClaim` | Provide an existing `PersistentVolumeClaim` (only when `architecture=standalone`) | `""` | +| `backup.cronjob.storage.resourcePolicy` | Setting it to "keep" to avoid removing PVCs during a helm delete operation. Leaving it empty will delete PVCs after the chart deleted | `""` | +| `backup.cronjob.storage.storageClass` | PVC Storage Class for the backup data volume | `""` | +| `backup.cronjob.storage.accessModes` | PV Access Mode | `["ReadWriteOnce"]` | +| `backup.cronjob.storage.size` | PVC Storage Request for the backup data volume | `8Gi` | +| `backup.cronjob.storage.annotations` | PVC annotations | `{}` | +| `backup.cronjob.storage.mountPath` | Path to mount the volume at | `/backup/pgdump` | +| `backup.cronjob.storage.subPath` | Subdirectory of the volume to mount at | `""` | +| `backup.cronjob.storage.volumeClaimTemplates.selector` | A label query over volumes to consider for binding (e.g. when using local volumes) | `{}` | + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +helm install my-release \ + --set postgresql.password=password \ + oci://REGISTRY_NAME/REPOSITORY_NAME/postgresql-ha +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The above command sets the password for user `postgres` to `password`. + +> NOTE: Once this chart is deployed, it is not possible to change the application's access credentials, such as usernames or passwords, using Helm. To change these application credentials after deployment, delete any persistent volumes (PVs) used by the chart and re-deploy it, or use the application's built-in administrative tools if available. + +Alternatively, a YAML file that specifies the values for the above parameters can be provided while installing the chart. For example, + +```console +helm install my-release \ + -f values.yaml \ + bitnami/postgresql-ha +``` + +## Troubleshooting + +Find more information about how to deal with common errors related to Bitnami's Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues). + +## Upgrading + +### To 16.0.0 + +This major version makes it possible to customize the user & password to be used by Pgpool-II for performing Stream Replication Checks and sets the default user to `sr_check_user`. Previously, the user was hardcoded to `repmgr`, reusing the same user used by Repmgr. This change allows for a more flexible & secure configuration, as the user used by Pgpool-II can be different from the one used by Repmgr. + +This major version includes a security fix for [GHSA-mx38-x658-5fwj](https://github.com/bitnami/charts/security/advisories/GHSA-mx38-x658-5fwj) and CVE-2025-22248. Upgrading to this or higher versions is recommended. + +Given users' creation is skipped when there's existing data, upgrading from `15.x` to `16.x` will fail when persistence is enabled unless the user is created manually or the `pgpool.srCheckUsername` and `pgpool.srCheckPassword` parameters are set to the same values as the `postgresql.repmgrUsername` and `postgresql.repmgrPassword` parameters: + +- Manually create the user: + +```console +export POSTGRES_PASSWORD=$(kubectl get secret --namespace default postgresql-ha-postgresql -o jsonpath="{.data.password}" | base64 -d) +kubectl run pg-client --rm --tty -i --restart='Never' --image docker.io/bitnami/postgresql-repmgr:17 --env="PGPASSWORD=$POSTGRES_PASSWORD" --command -- \ + psql -h postgresql-ha-pgpool -p 5432 -U postgres --command "CREATE ROLE sr_check_user WITH LOGIN PASSWORD 'some-password';" +kubectl run pg-client --rm --tty -i --restart='Never' --image docker.io/bitnami/postgresql-repmgr:17 --env="PGPASSWORD=$POSTGRES_PASSWORD" --command -- \ + psql -h postgresql-ha-pgpool -p 5432 -U postgres --command "GRANT CONNECT ON DATABASE postgres TO sr_check_user;" +helm upgrade my-release oci://REGISTRY_NAME/REPOSITORY_NAME/postgresql-ha \ + --set pgpool.srCheckPassword="some-password" +``` + +- Setting `pgpool.srCheckUsername` and `pgpool.srCheckPassword` parameters with the same values as `postgresql.repmgrUsername` and `postgresql.repmgrPassword` parameters: + +```console +export REPMGR_PASSWORD=$(kubectl get secret --namespace default postgresql-ha-postgresql -o jsonpath="{.data.repmgr-password}" | base64 -d) +helm upgrade my-release oci://REGISTRY_NAME/REPOSITORY_NAME/postgresql-ha \ + --set pgpool.srCheckUsername="repmgr" \ + --set pgpool.srCheckPassword="$REPMGR_PASSWORD" +``` + +### To 15.1.0 + +This version introduces image verification for security purposes. To disable it, set `global.security.allowInsecureImages` to `true`. More details at [GitHub issue](https://github.com/bitnami/charts/issues/30850). + +It's necessary to specify the existing passwords while performing a upgrade to ensure the secrets are not updated with invalid randomly generated passwords. Remember to specify the existing values of the `postgresql.password` and `postgresql.repmgrPassword` parameters when upgrading the chart: + +```console +helm upgrade my-release oci://REGISTRY_NAME/REPOSITORY_NAME/postgresql-ha \ + --set postgresql.password=[POSTGRES_PASSWORD] \ + --set postgresql.repmgrPassword=[REPMGR_PASSWORD] +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> Note: you need to substitute the placeholders *[POSTGRES_PASSWORD]*, and *[REPMGR_PASSWORD]* with the values obtained from instructions in the installation notes. +> Note: As general rule, it is always wise to do a backup before the upgrading procedures. + +If a message like the following appears in the logs: + +```log +... +postgresql-repmgr 13:57:07.50 INFO ==> ** Starting repmgrd ** +[2024-06-12 13:57:07] [NOTICE] repmgrd (repmgrd 5.4.1) starting up +[2024-06-12 13:57:07] [ERROR] an older version of the "repmgr" extension is installed +[2024-06-12 13:57:07] [DETAIL] extension version 5.3 is installed but newer version 5.4 is available +... +``` + +You will need to perform the following step first, and then continue with the upgrade: + +```console +$ helm upgrade mypg oci://registry-1.docker.io/bitnamicharts/postgresql-ha \ + --set postgresql.replicaCount=1 \ + --set postgresql.upgradeRepmgrExtension=true +``` + +### To 14.0.0 + +This major bump changes the following security defaults: + +- `runAsGroup` is changed from `0` to `1001` +- `readOnlyRootFilesystem` is set to `true` +- `resourcesPreset` is changed from `none` to the minimum size working in our test suites (NOTE: `resourcesPreset` is not meant for production usage, but `resources` adapted to your use case). +- `global.compatibility.openshift.adaptSecurityContext` is changed from `disabled` to `auto`. + +This could potentially break any customization or init scripts used in your deployment. If this is the case, change the default values to the previous ones. + +### To 13.0.0 + +This major version adapts the NetworkPolicy objects to the most recent Bitnami standards. Now there is a separate object for `pgpool` and for `postgresql`, being located in their corresponding sections. It is also enabled by default in other to comply with the best security standards. + +Check the parameter section for the new value structure. + +### To 12.0.0 + +This major version updates the PostgreSQL container image version used from 15 to 16, the new stable version. There are no major changes in the chart, but we recommend checking the [PostgreSQL 16 release notes](https://www.postgresql.org/docs/current/release-16.html) before upgrading. + +> Note: Due to an error in our release process, the latest version in the previous major branch (11.9.8) already uses 16 by default, see [PR#19590](https://github.com/bitnami/charts/pull/19590) + +### To 10.0.0 + +This major version changes the default PostgreSQL image from 14.x to 15.x. Follow the [official instructions](https://www.postgresql.org/docs/15/upgrading.html) to upgrade to 15.x. + +### To 9.0.0 + +This chart major version updates the PostgreSQL image's version to the latest major, `v14`, as well as standarizes the templates and values. These changes can be sumarised in the following: + +- Image parameters that used `imageNameImage` are now under `imageName.image` +- `containerPort` parameters are now found by `containerPorts.xxxx` +- `service.port` parameters are now found by `service.ports.xxxx` +- `imageName.securityContext` parameters are now under `imageName.podSecurityContext` +- `serviceAccount.enabled` parameter has been renamed to `serviceAccount.create` +- `postgresql.updateStrategyType` parameter has been renamed to `postgresql.updateStrategy.type` +- Added the `pgpool.authenticationMethod` parameter. Use "md5" for older PSQL versions and the default value of "scram-sha-256" when using PSQL > v14. + +> Note: Keep in mind you will find an error such as the one below when upgrading since the new chart major version also bumps the application version. To workaround this issue you need to upgrade the database, please refer to the [official PostgreSQL documentation](https://www.postgresql.org/docs/current/upgrading.html) for more information about this. + +```log +postgresql-repmgr 14:41:21.00 INFO ==> Setting up streaming replication slave... +postgresql-repmgr 14:41:21.04 INFO ==> Starting PostgreSQL in background... +waiting for server to start....2022-04-12 14:41:21.069 GMT [220] FATAL: database files are incompatible with server +2022-04-12 14:41:21.069 GMT [220] DETAIL: The data directory was initialized by PostgreSQL version 11, which is not compatible with this version 14.2. +pg_ctl: could not start server +``` + +### To 8.0.0 + +A new major version of repmgr (5.3) was included. To upgrade to this major version, it's necessary to upgrade the repmgr extension installed on the database. To do so, follow the steps below: + +- Reduce your PostgreSQL setup to one replica (primary node) and upgrade to `8.0.0`, enabling the repmgr extension upgrade: + +```console +helm upgrade my-release --version 8.0.0 oci://REGISTRY_NAME/REPOSITORY_NAME/postgresql-ha \ + --set postgresql.password=[POSTGRESQL_PASSWORD] \ + --set postgresql.repmgrPassword=[REPMGR_PASSWORD] \ + --set postgresql.replicaCount=1 \ + --set postgresql.upgradeRepmgrExtension=true +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +- Scale your PostgreSQL setup to the original number of replicas: + +```console +helm upgrade my-release --version 8.0.0 oci://REGISTRY_NAME/REPOSITORY_NAME/postgresql-ha \ + --set postgresql.password=[POSTGRESQL_PASSWORD] \ + --set postgresql.repmgrPassword=[REPMGR_PASSWORD] \ + --set postgresql.replicaCount=[NUMBER_OF_REPLICAS] +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> Note: you need to substitute the placeholders *[POSTGRESQL_PASSWORD]*, and *[REPMGR_PASSWORD]* with the values obtained from instructions in the installation notes. + +### To 6.4.0 + +Support for adding custom configuration files or initialization scripts by placing them under the "files" directory in the working directory was removed. This functionality was very confusing for users since they do not usually clone the repo nor they fetch the charts to their working directories. +As an alternative to this feature, users can still use the equivalent parameters available in the `values.yaml` to load their custom configuration & scripts. + +### To 6.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +#### What changes were introduced in this major version? + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- Move dependency information from the *requirements.yaml* to the *Chart.yaml* +- After running `helm dependency update`, a *Chart.lock* file is generated containing the same structure used in the previous *requirements.lock* +- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts + +#### Considerations when upgrading to this version + +- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues +- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore +- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 + +#### Useful links + +- +- +- + +### To 5.2.0 + +A new version of repmgr (5.2.0) was included. To upgrade to this version, it's necessary to upgrade the repmgr extension installed on the database. To do so, follow the steps below: + +- Reduce your PostgreSQL setup to one replica (primary node) and upgrade to `5.2.0`, enabling the repmgr extension upgrade: + +```console +helm upgrade my-release --version 5.2.0 oci://REGISTRY_NAME/REPOSITORY_NAME/postgresql-ha \ + --set postgresql.password=[POSTGRESQL_PASSWORD] \ + --set postgresql.repmgrPassword=[REPMGR_PASSWORD] \ + --set postgresql.replicaCount=1 \ + --set postgresql.upgradeRepmgrExtension=true +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +- Scale your PostgreSQL setup to the original number of replicas: + +```console +helm upgrade my-release --version 5.2.0 oci://REGISTRY_NAME/REPOSITORY_NAME/postgresql-ha \ + --set postgresql.password=[POSTGRESQL_PASSWORD] \ + --set postgresql.repmgrPassword=[REPMGR_PASSWORD] \ + --set postgresql.replicaCount=[NUMBER_OF_REPLICAS] +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> Note: you need to substitute the placeholders *[POSTGRESQL_PASSWORD]*, and *[REPMGR_PASSWORD]* with the values obtained from instructions in the installation notes (`helm get notes RELEASE_NAME`). + +### To 5.0.0 + +This release uses parallel deployment for the postgresql statefullset. This should fix the issues related to not being able to restart the cluster under some contions where the master node is not longer node `-0`. +This version is next major version to v3.x.y + +- To upgrade to this version you will need to delete the deployment, keep the PVCs and launch a new deployment keeping the deployment name. + +```console +$ # e.g. Previous deployment v3.9.1 +helm install my-release \ + --set postgresql.password=[POSTGRESQL_PASSWORD] \ + --set postgresql.repmgrPassword=[REPMGR_PASSWORD] \ + oci://REGISTRY_NAME/REPOSITORY_NAME/postgresql-ha --version 3.9.1 + +$ # Update repository information +helm repo update + +$ # upgrade to v5.0.0 +helm delete my-release +helm install my-release \ + --set postgresql.password=[POSTGRESQL_PASSWORD] \ + --set postgresql.repmgrPassword=[REPMGR_PASSWORD] \ + oci://REGISTRY_NAME/REPOSITORY_NAME/postgresql-ha --version 5.0.0 +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +### To 4.0.x + +Due to an error handling the version numbers these versions are actually part of the 3.x versions and not a new major version. + +### To 3.0.0 + +A new major version of repmgr (5.1.0) was included. To upgrade to this major version, it's necessary to upgrade the repmgr extension installed on the database. To do so, follow the steps below: + +- Reduce your PostgreSQL setup to one replica (primary node) and upgrade to `3.0.0`, enabling the repmgr extension upgrade: + +```console +helm upgrade my-release --version 3.0.0 oci://REGISTRY_NAME/REPOSITORY_NAME/postgresql-ha \ + --set postgresql.password=[POSTGRESQL_PASSWORD] \ + --set postgresql.repmgrPassword=[REPMGR_PASSWORD] \ + --set postgresql.replicaCount=1 \ + --set postgresql.upgradeRepmgrExtension=true +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +- Scale your PostgreSQL setup to the original number of replicas: + +```console +helm upgrade my-release --version 3.0.0 oci://REGISTRY_NAME/REPOSITORY_NAME/postgresql-ha \ + --set postgresql.password=[POSTGRESQL_PASSWORD] \ + --set postgresql.repmgrPassword=[REPMGR_PASSWORD] \ + --set postgresql.replicaCount=[NUMBER_OF_REPLICAS] +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> Note: you need to substitute the placeholders *[POSTGRESQL_PASSWORD]*, and *[REPMGR_PASSWORD]* with the values obtained from instructions in the installation notes. + +### To 2.0.0 + +The [Bitnami Pgpool](https://github.com/bitnami/containers/tree/main/bitnami/pgpool) image was migrated to a "non-root" user approach. Previously the container ran as the `root` user and the Pgpool daemon was started as the `pgpool` user. From now on, both the container and the Pgpool daemon run as user `1001`. You can revert this behavior by setting the parameters `pgpool.containerSecurityContext.runAsUser`, and `pgpool.securityContext.fsGroup` to `0`. + +Consequences: + +- No backwards compatibility issues are expected since all the data is at PostgreSQL pods, and Pgpool uses a deployment without persistence. Therefore, upgrades should work smoothly from `1.x.x` versions. +- Environment variables related to LDAP configuration were renamed removing the `PGPOOL_` prefix. For instance, to indicate the LDAP URI to use, you must set `LDAP_URI` instead of `PGPOOL_LDAP_URI` + +### To 1.0.0 + +A new major version of repmgr (5.0.0) was included. To upgrade to this major version, it's necessary to upgrade the repmgr extension installed on the database. To do so, follow the steps below: + +- Reduce your PostgreSQL setup to one replica (primary node) and upgrade to `1.0.0`, enabling the repmgr extension upgrade: + +```console +helm upgrade my-release --version 1.0.0 oci://REGISTRY_NAME/REPOSITORY_NAME/postgresql-ha \ + --set postgresql.password=[POSTGRESQL_PASSWORD] \ + --set postgresql.repmgrPassword=[REPMGR_PASSWORD] \ + --set postgresql.replicaCount=1 \ + --set postgresql.upgradeRepmgrExtension=true +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +- Scale your PostgreSQL setup to the original number of replicas: + +```console +helm upgrade my-release --version 1.0.0 oci://REGISTRY_NAME/REPOSITORY_NAME/postgresql-ha \ + --set postgresql.password=[POSTGRESQL_PASSWORD] \ + --set postgresql.repmgrPassword=[REPMGR_PASSWORD] \ + --set postgresql.replicaCount=[NUMBER_OF_REPLICAS] +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> Note: you need to substitute the placeholders *[POSTGRESQL_PASSWORD]*, and *[REPMGR_PASSWORD]* with the values obtained from instructions in the installation notes. + +### To 0.4.0 + +In this version, the chart will use PostgreSQL-Repmgr container images with the Postgis extension included. The version used in Postgresql version 10, 11 and 12 is Postgis 2.5, and in Postgresql 9.6 is Postgis 2.3. Postgis has been compiled with the following dependencies: + +- protobuf +- protobuf-c +- json-c +- geos +- proj +- gdal + +## Bitnami Kubernetes Documentation + +Bitnami Kubernetes documentation is available at [https://docs.bitnami.com/](https://docs.bitnami.com/). You can find there the following resources: + +- [Documentation for PostgreSQL HA Helm chart](https://github.com/bitnami/charts/tree/main/bitnami/postgresql-ha) +- [Get Started with Kubernetes guides](https://docs.bitnami.com/kubernetes/) +- [Kubernetes FAQs](https://docs.bitnami.com/kubernetes/faq/) +- [Kubernetes Developer guides](https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-index.html) + +## License + +Copyright © 2025 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/.helmignore b/backing-services/gitea/charts/postgresql-ha/charts/common/.helmignore new file mode 100644 index 0000000..d0e1084 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/.helmignore @@ -0,0 +1,26 @@ +# 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 +.vscode/ +# img folder +img/ +# Changelog +CHANGELOG.md diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/Chart.yaml b/backing-services/gitea/charts/postgresql-ha/charts/common/Chart.yaml new file mode 100644 index 0000000..fb04f76 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/Chart.yaml @@ -0,0 +1,23 @@ +annotations: + category: Infrastructure + licenses: Apache-2.0 +apiVersion: v2 +appVersion: 2.31.4 +description: A Library Helm Chart for grouping common logic between bitnami charts. + This chart is not deployable by itself. +home: https://bitnami.com +icon: https://dyltqmyl993wv.cloudfront.net/downloads/logos/bitnami-mark.png +keywords: +- common +- helper +- template +- function +- bitnami +maintainers: +- name: Broadcom, Inc. All Rights Reserved. + url: https://github.com/bitnami/charts +name: common +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/common +type: library +version: 2.31.4 diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/README.md b/backing-services/gitea/charts/postgresql-ha/charts/common/README.md new file mode 100644 index 0000000..71368aa --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/README.md @@ -0,0 +1,387 @@ +# Bitnami Common Library Chart + +A [Helm Library Chart](https://helm.sh/docs/topics/library_charts/#helm) for grouping common logic between Bitnami charts. + +## TL;DR + +```yaml +dependencies: + - name: common + version: 2.x.x + repository: oci://registry-1.docker.io/bitnamicharts +``` + +```console +helm dependency update +``` + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "common.names.fullname" . }} +data: + myvalue: "Hello World" +``` + +Looking to use our applications in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the commercial edition of the Bitnami catalog. + +## ⚠️ Important Notice: Upcoming changes to the Bitnami Catalog + +Beginning August 28th, 2025, Bitnami will evolve its public catalog to offer a curated set of hardened, security-focused images under the new [Bitnami Secure Images initiative](https://news.broadcom.com/app-dev/broadcom-introduces-bitnami-secure-images-for-production-ready-containerized-applications). As part of this transition: + +- Granting community users access for the first time to security-optimized versions of popular container images. +- Bitnami will begin deprecating support for non-hardened, Debian-based software images in its free tier and will gradually remove non-latest tags from the public catalog. As a result, community users will have access to a reduced number of hardened images. These images are published only under the “latest” tag and are intended for development purposes +- Starting August 28th, over two weeks, all existing container images, including older or versioned tags (e.g., 2.50.0, 10.6), will be migrated from the public catalog (docker.io/bitnami) to the “Bitnami Legacy” repository (docker.io/bitnamilegacy), where they will no longer receive updates. +- For production workloads and long-term support, users are encouraged to adopt Bitnami Secure Images, which include hardened containers, smaller attack surfaces, CVE transparency (via VEX/KEV), SBOMs, and enterprise support. + +These changes aim to improve the security posture of all Bitnami users by promoting best practices for software supply chain integrity and up-to-date deployments. For more details, visit the [Bitnami Secure Images announcement](https://github.com/bitnami/containers/issues/83267). + +## Introduction + +This chart provides a common template helpers which can be used to develop new charts using [Helm](https://helm.sh) package manager. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ + +## Parameters + +The following table lists the helpers available in the library which are scoped in different sections. + +### Affinities + +| Helper identifier | Description | Expected Input | +| ------------------------------- | ---------------------------------------------------- | ------------------------------------------------------------ | +| `common.affinities.nodes.soft` | Return a soft nodeAffinity definition | `dict "key" "FOO" "values" (list "BAR" "BAZ")` | +| `common.affinities.nodes.hard` | Return a hard nodeAffinity definition | `dict "key" "FOO" "values" (list "BAR" "BAZ")` | +| `common.affinities.nodes` | Return a nodeAffinity definition | `dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")` | +| `common.affinities.topologyKey` | Return a topologyKey definition | `dict "topologyKey" "FOO"` | +| `common.affinities.pods.soft` | Return a soft podAffinity/podAntiAffinity definition | `dict "component" "FOO" "context" $` | +| `common.affinities.pods.hard` | Return a hard podAffinity/podAntiAffinity definition | `dict "component" "FOO" "context" $` | +| `common.affinities.pods` | Return a podAffinity/podAntiAffinity definition | `dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")` | + +### Capabilities + +| Helper identifier | Description | Expected Input | +| --------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------- | +| `common.capabilities.kubeVersion` | Return the target Kubernetes version (using client default if .Values.kubeVersion is not set). | `.` Chart context | +| `common.capabilities.apiVersions.has` | Return true if the apiVersion is supported | `dict "version" "batch/v1" "context" $` | +| `common.capabilities.job.apiVersion` | Return the appropriate apiVersion for job. | `.` Chart context | +| `common.capabilities.cronjob.apiVersion` | Return the appropriate apiVersion for cronjob. | `.` Chart context | +| `common.capabilities.daemonset.apiVersion` | Return the appropriate apiVersion for daemonset. | `.` Chart context | +| `common.capabilities.deployment.apiVersion` | Return the appropriate apiVersion for deployment. | `.` Chart context | +| `common.capabilities.statefulset.apiVersion` | Return the appropriate apiVersion for statefulset. | `.` Chart context | +| `common.capabilities.ingress.apiVersion` | Return the appropriate apiVersion for ingress. | `.` Chart context | +| `common.capabilities.rbac.apiVersion` | Return the appropriate apiVersion for RBAC resources. | `.` Chart context | +| `common.capabilities.crd.apiVersion` | Return the appropriate apiVersion for CRDs. | `.` Chart context | +| `common.capabilities.policy.apiVersion` | Return the appropriate apiVersion for podsecuritypolicy. | `.` Chart context | +| `common.capabilities.networkPolicy.apiVersion` | Return the appropriate apiVersion for networkpolicy. | `.` Chart context | +| `common.capabilities.apiService.apiVersion` | Return the appropriate apiVersion for APIService. | `.` Chart context | +| `common.capabilities.hpa.apiVersion` | Return the appropriate apiVersion for Horizontal Pod Autoscaler | `.` Chart context | +| `common.capabilities.vpa.apiVersion` | Return the appropriate apiVersion for Vertical Pod Autoscaler. | `.` Chart context | +| `common.capabilities.psp.supported` | Returns true if PodSecurityPolicy is supported | `.` Chart context | +| `common.capabilities.supportsHelmVersion` | Returns true if the used Helm version is 3.3+ | `.` Chart context | +| `common.capabilities.admissionConfiguration.supported` | Returns true if AdmissionConfiguration is supported | `.` Chart context | +| `common.capabilities.admissionConfiguration.apiVersion` | Return the appropriate apiVersion for AdmissionConfiguration. | `.` Chart context | +| `common.capabilities.podSecurityConfiguration.apiVersion` | Return the appropriate apiVersion for PodSecurityConfiguration. | `.` Chart context | + +### Compatibility + +| Helper identifier | Description | Expected Input | +| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | +| `common.compatibility.isOpenshift` | Return true if the detected platform is Openshift | `.` Chart context | +| `common.compatibility.renderSecurityContext` | Render a compatible securityContext depending on the platform. By default it is maintained as it is. In other platforms like Openshift we remove default user/group values that do not work out of the box with the restricted-v1 SCC | `dict "secContext" .Values.containerSecurityContext "context" $` | + +### Errors + +| Helper identifier | Description | Expected Input | +| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | +| `common.errors.upgrade.passwords.empty` | It will ensure required passwords are given when we are upgrading a chart. If `validationErrors` is not empty it will throw an error and will stop the upgrade action. | `dict "validationErrors" (list $validationError00 $validationError01) "context" $` | +| `common.errors.insecureImages` | Throw error when original container images are replaced. The error can be bypassed by setting the `global.security.allowInsecureImages` to true. | `dict "images" (list .Values.path.to.the.imageRoot) "context" $` | + +### Images + +| Helper identifier | Description | Expected Input | +| --------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | +| `common.images.image` | Return the proper and full image name | `dict "imageRoot" .Values.path.to.the.image "global" $`, see [ImageRoot](#imageroot) for the structure. | +| `common.images.pullSecrets` | Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead) | `dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global` | +| `common.images.renderPullSecrets` | Return the proper Docker Image Registry Secret Names (evaluates values as templates) | `dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $` | +| `common.images.version` | Return the proper image version | `dict "imageRoot" .Values.path.to.the.image "chart" .Chart` , see [ImageRoot](#imageroot) for the structure. | + +### Ingress + +| Helper identifier | Description | Expected Input | +| ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `common.ingress.backend` | Generate a proper Ingress backend entry depending on the API version | `dict "serviceName" "foo" "servicePort" "bar"`, see the [Ingress deprecation notice](https://kubernetes.io/blog/2019/07/18/api-deprecations-in-1-16/) for the syntax differences | +| `common.ingress.certManagerRequest` | Prints "true" if required cert-manager annotations for TLS signed certificates are set in the Ingress annotations | `dict "annotations" .Values.path.to.the.ingress.annotations` | + +### Labels + +| Helper identifier | Description | Expected Input | +| --------------------------- | --------------------------------------------------------------------------- | ----------------- | +| `common.labels.standard` | Return Kubernetes standard labels | `.` Chart context | +| `common.labels.matchLabels` | Labels to use on `deploy.spec.selector.matchLabels` and `svc.spec.selector` | `.` Chart context | + +### Names + +| Helper identifier | Description | Expected Input | +| ---------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | +| `common.names.name` | Expand the name of the chart or use `.Values.nameOverride` | `.` Chart context | +| `common.names.fullname` | Create a default fully qualified app name. | `.` Chart context | +| `common.names.namespace` | Allow the release namespace to be overridden | `.` Chart context | +| `common.names.fullname.namespace` | Create a fully qualified app name adding the installation's namespace | `.` Chart context | +| `common.names.chart` | Chart name plus version | `.` Chart context | +| `common.names.dependency.fullname` | Create a default fully qualified dependency name. | `dict "chartName" "dependency-chart-name" "chartValues" .Values.dependency-chart "context" $` | + +### Resources + +| Helper identifier | Description | Expected Input | +| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | +| `common.resources.preset` | Return a resource request/limit object based on a given preset. These presets are for basic testing and not meant to be used in production. | `dict "type" "nano"` | + +### Secrets + +| Helper identifier | Description | Expected Input | +| --------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `common.secrets.name` | Generate the name of the secret. | `dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $` see [ExistingSecret](#existingsecret) for the structure. | +| `common.secrets.key` | Generate secret key. | `dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName"` see [ExistingSecret](#existingsecret) for the structure. | +| `common.secrets.passwords.manage` | Generate secret password or retrieve one if already created. | `dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "honorProvidedValues" false "context" $`, length, strong, honorProvidedValues and chartName fields are optional. | +| `common.secrets.exists` | Returns whether a previous generated secret already exists. | `dict "secret" "secret-name" "context" $` | +| `common.secrets.lookup` | Reuses the value from an existing secret, otherwise sets its value to a default value. | `dict "secret" "secret-name" "key" "keyName" "defaultValue" .Values.myValue "context" $` | + +### Storage + +| Helper identifier | Description | Expected Input | +| ---------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------- | +| `common.storage.class` | Return the proper Storage Class | `dict "persistence" .Values.path.to.the.persistence "global" $`, see [Persistence](#persistence) for the structure. | + +### TplValues + +| Helper identifier | Description | Expected Input | +| ---------------------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `common.tplvalues.render` | Renders a value that contains template | `dict "value" .Values.path.to.the.Value "context" $`, value is the value should rendered as template, context frequently is the chart context `$` or `.` | +| `common.tplvalues.merge` | Merge a list of values that contains template after rendering them. | `dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $` | +| `common.tplvalues.merge-overwrite` | Merge a list of values that contains template after rendering them. | `dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $` | + +### Utils + +| Helper identifier | Description | Expected Input | +| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | +| `common.utils.fieldToEnvVar` | Build environment variable name given a field. | `dict "field" "my-password"` | +| `common.utils.secret.getvalue` | Print instructions to get a secret value. | `dict "secret" "secret-name" "field" "secret-value-field" "context" $` | +| `common.utils.getValueFromKey` | Gets a value from `.Values` object given its key path | `dict "key" "path.to.key" "context" $` | +| `common.utils.getKeyFromList` | Returns first `.Values` key with a defined value or first of the list if all non-defined | `dict "keys" (list "path.to.key1" "path.to.key2") "context" $` | +| `common.utils.checksumTemplate` | Checksum a template at "path" containing a *single* resource (ConfigMap,Secret) for use in pod annotations, excluding the metadata (see #18376) | `dict "path" "/configmap.yaml" "context" $` | + +### Validations + +| Helper identifier | Description | Expected Input | +| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `common.validations.values.single.empty` | Validate a value must not be empty. | `dict "valueKey" "path.to.value" "secret" "secret.name" "field" "my-password" "subchart" "subchart" "context" $` secret, field and subchart are optional. In case they are given, the helper will generate a how to get instruction. See [ValidateValue](#validatevalue) | +| `common.validations.values.multiple.empty` | Validate a multiple values must not be empty. It returns a shared error for all the values. | `dict "required" (list $validateValueConf00 $validateValueConf01) "context" $`. See [ValidateValue](#validatevalue) | +| `common.validations.values.mariadb.passwords` | This helper will ensure required password for MariaDB are not empty. It returns a shared error for all the values. | `dict "secret" "mariadb-secret" "subchart" "true" "context" $` subchart field is optional and could be true or false it depends on where you will use mariadb chart and the helper. | + +### Warnings + +| Helper identifier | Description | Expected Input | +| -------------------------------- | ----------------------------------------------------------------- | ---------------------------------------------------------- | +| `common.warnings.rollingTag` | Warning about using rolling tag. | `ImageRoot` see [ImageRoot](#imageroot) for the structure. | +| `common.warnings.modifiedImages` | Warning about replaced images from the original. | `ImageRoot` see [ImageRoot](#imageroot) for the structure. | +| `common.warnings.resources` | Warning about not setting the resource object in all deployments. | `dict "sections" (list "path1" "path2") context $` | + +## Special input schemas + +### ImageRoot + +```yaml +registry: + type: string + description: Docker registry where the image is located + example: docker.io + +repository: + type: string + description: Repository and image name + example: bitnami/nginx + +tag: + type: string + description: image tag + example: 1.16.1-debian-10-r63 + +pullPolicy: + type: string + description: Specify a imagePullPolicy.' + +pullSecrets: + type: array + items: + type: string + description: Optionally specify an array of imagePullSecrets (evaluated as templates). + +debug: + type: boolean + description: Set to true if you would like to see extra information on logs + example: false + +## An instance would be: +# registry: docker.io +# repository: bitnami/nginx +# tag: 1.16.1-debian-10-r63 +# pullPolicy: IfNotPresent +# debug: false +``` + +### Persistence + +```yaml +enabled: + type: boolean + description: Whether enable persistence. + example: true + +storageClass: + type: string + description: Ghost data Persistent Volume Storage Class, If set to "-", storageClassName: "" which disables dynamic provisioning. + example: "-" + +accessMode: + type: string + description: Access mode for the Persistent Volume Storage. + example: ReadWriteOnce + +size: + type: string + description: Size the Persistent Volume Storage. + example: 8Gi + +path: + type: string + description: Path to be persisted. + example: /bitnami + +## An instance would be: +# enabled: true +# storageClass: "-" +# accessMode: ReadWriteOnce +# size: 8Gi +# path: /bitnami +``` + +### ExistingSecret + +```yaml +name: + type: string + description: Name of the existing secret. + example: mySecret +keyMapping: + description: Mapping between the expected key name and the name of the key in the existing secret. + type: object + +## An instance would be: +# name: mySecret +# keyMapping: +# password: myPasswordKey +``` + +#### Example of use + +When we store sensitive data for a deployment in a secret, some times we want to give to users the possibility of using theirs existing secrets. + +```yaml +# templates/secret.yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }} + labels: + app: {{ include "common.names.fullname" . }} +type: Opaque +data: + password: {{ .Values.password | b64enc | quote }} + +# templates/dpl.yaml +--- +... + env: + - name: PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "common.secrets.name" (dict "existingSecret" .Values.existingSecret "context" $) }} + key: {{ include "common.secrets.key" (dict "existingSecret" .Values.existingSecret "key" "password") }} +... + +# values.yaml +--- +name: mySecret +keyMapping: + password: myPasswordKey +``` + +### ValidateValue + +#### NOTES.txt + +```console +{{- $validateValueConf00 := (dict "valueKey" "path.to.value00" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value01" "secret" "secretName" "field" "password-01") -}} + +{{ include "common.validations.values.multiple.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} +``` + +If we force those values to be empty we will see some alerts + +```console +helm install test mychart --set path.to.value00="",path.to.value01="" + 'path.to.value00' must not be empty, please add '--set path.to.value00=$PASSWORD_00' to the command. To get the current value: + + export PASSWORD_00=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-00}" | base64 -d) + + 'path.to.value01' must not be empty, please add '--set path.to.value01=$PASSWORD_01' to the command. To get the current value: + + export PASSWORD_01=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-01}" | base64 -d) +``` + +## Upgrading + +### To 1.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +#### What changes were introduced in this major version? + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- Use `type: library`. [Here](https://v3.helm.sh/docs/faq/#library-chart-support) you can find more information. +- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts + +#### Considerations when upgrading to this version + +- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues +- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore +- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 + +#### Useful links + +- +- +- + +## License + +Copyright © 2025 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_affinities.tpl b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_affinities.tpl new file mode 100644 index 0000000..c6ccc62 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_affinities.tpl @@ -0,0 +1,169 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a soft nodeAffinity definition +{{ include "common.affinities.nodes.soft" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.soft" -}} +preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} + weight: 1 +{{- end -}} + +{{/* +Return a hard nodeAffinity definition +{{ include "common.affinities.nodes.hard" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.hard" -}} +requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} +{{- end -}} + +{{/* +Return a nodeAffinity definition +{{ include "common.affinities.nodes" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.nodes.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.nodes.hard" . -}} + {{- end -}} +{{- end -}} + +{{/* +Return a topologyKey definition +{{ include "common.affinities.topologyKey" (dict "topologyKey" "BAR") -}} +*/}} +{{- define "common.affinities.topologyKey" -}} +{{ .topologyKey | default "kubernetes.io/hostname" -}} +{{- end -}} + +{{/* +Return a soft podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.soft" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "extraNamespaces" (list "namespace1" "namespace2") "context" $) -}} +*/}} +{{- define "common.affinities.pods.soft" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +{{- $extraNamespaces := default (list) .extraNamespaces -}} +preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if $extraNamespaces }} + namespaces: + - {{ .context.Release.Namespace }} + {{- with $extraNamespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: 1 + {{- range $extraPodAffinityTerms }} + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if .namespaces }} + namespaces: + - {{ $.context.Release.Namespace }} + {{- with .namespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: {{ .weight | default 1 -}} + {{- end -}} +{{- end -}} + +{{/* +Return a hard podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.hard" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "extraNamespaces" (list "namespace1" "namespace2") "context" $) -}} +*/}} +{{- define "common.affinities.pods.hard" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +{{- $extraNamespaces := default (list) .extraNamespaces -}} +requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if $extraNamespaces }} + namespaces: + - {{ .context.Release.Namespace }} + {{- with $extraNamespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 6 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- range $extraPodAffinityTerms }} + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if .namespaces }} + namespaces: + - {{ $.context.Release.Namespace }} + {{- with .namespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 6 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- end -}} +{{- end -}} + +{{/* +Return a podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.pods" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.pods.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.pods.hard" . -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_capabilities.tpl b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_capabilities.tpl new file mode 100644 index 0000000..58f58c1 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_capabilities.tpl @@ -0,0 +1,178 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the target Kubernetes version +*/}} +{{- define "common.capabilities.kubeVersion" -}} +{{- default (default .Capabilities.KubeVersion.Version .Values.kubeVersion) ((.Values.global).kubeVersion) -}} +{{- end -}} + +{{/* +Return true if the apiVersion is supported +Usage: +{{ include "common.capabilities.apiVersions.has" (dict "version" "batch/v1" "context" $) }} +*/}} +{{- define "common.capabilities.apiVersions.has" -}} +{{- $providedAPIVersions := default .context.Values.apiVersions ((.context.Values.global).apiVersions) -}} +{{- if and (empty $providedAPIVersions) (.context.Capabilities.APIVersions.Has .version) -}} + {{- true -}} +{{- else if has .version $providedAPIVersions -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for poddisruptionbudget. +*/}} +{{- define "common.capabilities.policy.apiVersion" -}} +{{- print "policy/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "common.capabilities.networkPolicy.apiVersion" -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for job. +*/}} +{{- define "common.capabilities.job.apiVersion" -}} +{{- print "batch/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for cronjob. +*/}} +{{- define "common.capabilities.cronjob.apiVersion" -}} +{{- print "batch/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for daemonset. +*/}} +{{- define "common.capabilities.daemonset.apiVersion" -}} +{{- print "apps/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for deployment. +*/}} +{{- define "common.capabilities.deployment.apiVersion" -}} +{{- print "apps/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for statefulset. +*/}} +{{- define "common.capabilities.statefulset.apiVersion" -}} +{{- print "apps/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "common.capabilities.ingress.apiVersion" -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for RBAC resources. +*/}} +{{- define "common.capabilities.rbac.apiVersion" -}} +{{- print "rbac.authorization.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for CRDs. +*/}} +{{- define "common.capabilities.crd.apiVersion" -}} +{{- print "apiextensions.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for APIService. +*/}} +{{- define "common.capabilities.apiService.apiVersion" -}} +{{- print "apiregistration.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Horizontal Pod Autoscaler. +*/}} +{{- define "common.capabilities.hpa.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" .context -}} +{{- print "autoscaling/v2" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Vertical Pod Autoscaler. +*/}} +{{- define "common.capabilities.vpa.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "autoscaling/v1beta2" -}} +{{- else -}} +{{- print "autoscaling/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if PodSecurityPolicy is supported +*/}} +{{- define "common.capabilities.psp.supported" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if or (empty $kubeVersion) (semverCompare "<1.25-0" $kubeVersion) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if AdmissionConfiguration is supported +*/}} +{{- define "common.capabilities.admissionConfiguration.supported" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} + {{- true -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for AdmissionConfiguration. +*/}} +{{- define "common.capabilities.admissionConfiguration.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "apiserver.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiserver.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for PodSecurityConfiguration. +*/}} +{{- define "common.capabilities.podSecurityConfiguration.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "pod-security.admission.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "pod-security.admission.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the used Helm version is 3.3+. +A way to check the used Helm version was not introduced until version 3.3.0 with .Capabilities.HelmVersion, which contains an additional "{}}" structure. +This check is introduced as a regexMatch instead of {{ if .Capabilities.HelmVersion }} because checking for the key HelmVersion in <3.3 results in a "interface not found" error. +**To be removed when the catalog's minimun Helm version is 3.3** +*/}} +{{- define "common.capabilities.supportsHelmVersion" -}} +{{- if regexMatch "{(v[0-9])*[^}]*}}$" (.Capabilities | toString ) }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_compatibility.tpl b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_compatibility.tpl new file mode 100644 index 0000000..19c26db --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_compatibility.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return true if the detected platform is Openshift +Usage: +{{- include "common.compatibility.isOpenshift" . -}} +*/}} +{{- define "common.compatibility.isOpenshift" -}} +{{- if .Capabilities.APIVersions.Has "security.openshift.io/v1" -}} +{{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Render a compatible securityContext depending on the platform. By default it is maintained as it is. In other platforms like Openshift we remove default user/group values that do not work out of the box with the restricted-v1 SCC +Usage: +{{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) -}} +*/}} +{{- define "common.compatibility.renderSecurityContext" -}} +{{- $adaptedContext := .secContext -}} + +{{- if (((.context.Values.global).compatibility).openshift) -}} + {{- if or (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "force") (and (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "auto") (include "common.compatibility.isOpenshift" .context)) -}} + {{/* Remove incompatible user/group values that do not work in Openshift out of the box */}} + {{- $adaptedContext = omit $adaptedContext "fsGroup" "runAsUser" "runAsGroup" -}} + {{- if not .secContext.seLinuxOptions -}} + {{/* If it is an empty object, we remove it from the resulting context because it causes validation issues */}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{/* Remove empty seLinuxOptions object if global.compatibility.omitEmptySeLinuxOptions is set to true */}} +{{- if and (((.context.Values.global).compatibility).omitEmptySeLinuxOptions) (not .secContext.seLinuxOptions) -}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} +{{- end -}} +{{/* Remove fields that are disregarded when running the container in privileged mode */}} +{{- if $adaptedContext.privileged -}} + {{- $adaptedContext = omit $adaptedContext "capabilities" -}} +{{- end -}} +{{- omit $adaptedContext "enabled" | toYaml -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_errors.tpl b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_errors.tpl new file mode 100644 index 0000000..fb704c9 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_errors.tpl @@ -0,0 +1,92 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Throw error when upgrading using empty passwords values that must not be empty. + +Usage: +{{- $validationError00 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password00" "secret" "secretName" "field" "password-00") -}} +{{- $validationError01 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password01" "secret" "secretName" "field" "password-01") -}} +{{ include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $validationError00 $validationError01) "context" $) }} + +Required password params: + - validationErrors - String - Required. List of validation strings to be return, if it is empty it won't throw error. + - context - Context - Required. Parent context. +*/}} +{{- define "common.errors.upgrade.passwords.empty" -}} + {{- $validationErrors := join "" .validationErrors -}} + {{- if and $validationErrors .context.Release.IsUpgrade -}} + {{- $errorString := "\nPASSWORDS ERROR: You must provide your current passwords when upgrading the release." -}} + {{- $errorString = print $errorString "\n Note that even after reinstallation, old credentials may be needed as they may be kept in persistent volume claims." -}} + {{- $errorString = print $errorString "\n Further information can be obtained at https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues/#credential-errors-while-upgrading-chart-releases" -}} + {{- $errorString = print $errorString "\n%s" -}} + {{- printf $errorString $validationErrors | fail -}} + {{- end -}} +{{- end -}} + +{{/* +Throw error when original container images are replaced. +The error can be bypassed by setting the "global.security.allowInsecureImages" to true. In this case, +a warning message will be shown instead. + +Usage: +{{ include "common.errors.insecureImages" (dict "images" (list .Values.path.to.the.imageRoot) "context" $) }} +*/}} +{{- define "common.errors.insecureImages" -}} +{{- $relocatedImages := list -}} +{{- $replacedImages := list -}} +{{- $bitnamiLegacyImages := list -}} +{{- $retaggedImages := list -}} +{{- $globalRegistry := ((.context.Values.global).imageRegistry) -}} +{{- $originalImages := .context.Chart.Annotations.images -}} +{{- range .images -}} + {{- $registryName := default .registry $globalRegistry -}} + {{- $fullImageNameNoTag := printf "%s/%s" $registryName .repository -}} + {{- $fullImageName := printf "%s:%s" $fullImageNameNoTag .tag -}} + {{- if not (contains $fullImageNameNoTag $originalImages) -}} + {{- if not (contains $registryName $originalImages) -}} + {{- $relocatedImages = append $relocatedImages $fullImageName -}} + {{- else if not (contains .repository $originalImages) -}} + {{- $replacedImages = append $replacedImages $fullImageName -}} + {{- if contains "docker.io/bitnamilegacy/" $fullImageNameNoTag -}} + {{- $bitnamiLegacyImages = append $bitnamiLegacyImages $fullImageName -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- if not (contains (printf "%s:%s" .repository .tag) $originalImages) -}} + {{- $retaggedImages = append $retaggedImages $fullImageName -}} + {{- end -}} +{{- end -}} + +{{- if and (or (gt (len $relocatedImages) 0) (gt (len $replacedImages) 0)) (((.context.Values.global).security).allowInsecureImages) -}} + {{- print "\n\n⚠ SECURITY WARNING: Verifying original container images was skipped. Please note this Helm chart was designed, tested, and validated on multiple platforms using a specific set of Bitnami and Bitnami Secure Images containers. Substituting other containers is likely to cause degraded security and performance, broken chart features, and missing environment variables.\n" -}} +{{- else if (or (gt (len $relocatedImages) 0) (gt (len $replacedImages) 0)) -}} + {{- $errorString := "Original containers have been substituted for unrecognized ones. Deploying this chart with non-standard containers is likely to cause degraded security and performance, broken chart features, and missing environment variables." -}} + {{- $errorString = print $errorString "\n\nUnrecognized images:" -}} + {{- range (concat $relocatedImages $replacedImages) -}} + {{- $errorString = print $errorString "\n - " . -}} + {{- end -}} + {{- if and (eq (len $relocatedImages) 0) (eq (len $replacedImages) (len $bitnamiLegacyImages)) -}} + {{- $errorString = print "\n\n⚠ WARNING: " $errorString -}} + {{- print $errorString -}} + {{- else if or (contains "docker.io/bitnami/" $originalImages) (contains "docker.io/bitnamiprem/" $originalImages) (contains "docker.io/bitnamisecure/" $originalImages) -}} + {{- $errorString = print "\n\n⚠ ERROR: " $errorString -}} + {{- $errorString = print $errorString "\n\nIf you are sure you want to proceed with non-standard containers, you can skip container image verification by setting the global parameter 'global.security.allowInsecureImages' to true." -}} + {{- $errorString = print $errorString "\nFurther information can be obtained at https://github.com/bitnami/charts/issues/30850" -}} + {{- print $errorString | fail -}} + {{- else if gt (len $replacedImages) 0 -}} + {{- $errorString = print "\n\n⚠ WARNING: " $errorString -}} + {{- print $errorString -}} + {{- end -}} +{{- else if gt (len $retaggedImages) 0 -}} + {{- $warnString := "\n\n⚠ WARNING: Original containers have been retagged. Please note this Helm chart was tested, and validated on multiple platforms using a specific set of Bitnami and Bitnami Secure Images containers. Substituting original image tags could cause unexpected behavior." -}} + {{- $warnString = print $warnString "\n\nRetagged images:" -}} + {{- range $retaggedImages -}} + {{- $warnString = print $warnString "\n - " . -}} + {{- end -}} + {{- print $warnString -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_images.tpl b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_images.tpl new file mode 100644 index 0000000..76bb7ce --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_images.tpl @@ -0,0 +1,115 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Return the proper image name. +If image tag and digest are not defined, termination fallbacks to chart appVersion. +{{ include "common.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" .Values.global "chart" .Chart ) }} +*/}} +{{- define "common.images.image" -}} +{{- $registryName := default .imageRoot.registry ((.global).imageRegistry) -}} +{{- $repositoryName := .imageRoot.repository -}} +{{- $separator := ":" -}} +{{- $termination := .imageRoot.tag | toString -}} + +{{- if not .imageRoot.tag }} + {{- if .chart }} + {{- $termination = .chart.AppVersion | toString -}} + {{- end -}} +{{- end -}} +{{- if .imageRoot.digest }} + {{- $separator = "@" -}} + {{- $termination = .imageRoot.digest | toString -}} +{{- end -}} +{{- if $registryName }} + {{- printf "%s/%s%s%s" $registryName $repositoryName $separator $termination -}} +{{- else -}} + {{- printf "%s%s%s" $repositoryName $separator $termination -}} +{{- end -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead) +{{ include "common.images.pullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global) }} +*/}} +{{- define "common.images.pullSecrets" -}} + {{- $pullSecrets := list }} + + {{- range ((.global).imagePullSecrets) -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end }} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) -}} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names evaluating values as templates +{{ include "common.images.renderPullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $) }} +*/}} +{{- define "common.images.renderPullSecrets" -}} + {{- $pullSecrets := list }} + {{- $context := .context }} + + {{- range (($context.Values.global).imagePullSecrets) -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) -}} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper image version (ingores image revision/prerelease info & fallbacks to chart appVersion) +{{ include "common.images.version" ( dict "imageRoot" .Values.path.to.the.image "chart" .Chart ) }} +*/}} +{{- define "common.images.version" -}} +{{- $imageTag := .imageRoot.tag | toString -}} +{{/* regexp from https://github.com/Masterminds/semver/blob/23f51de38a0866c5ef0bfc42b3f735c73107b700/version.go#L41-L44 */}} +{{- if regexMatch `^([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?$` $imageTag -}} + {{- $version := semver $imageTag -}} + {{- printf "%d.%d.%d" $version.Major $version.Minor $version.Patch -}} +{{- else -}} + {{- print .chart.AppVersion -}} +{{- end -}} +{{- end -}} + diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_ingress.tpl b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_ingress.tpl new file mode 100644 index 0000000..2d0dbf1 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_ingress.tpl @@ -0,0 +1,41 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Generate backend entry that is compatible with all Kubernetes API versions. + +Usage: +{{ include "common.ingress.backend" (dict "serviceName" "backendName" "servicePort" "backendPort" "context" $) }} + +Params: + - serviceName - String. Name of an existing service backend + - servicePort - String/Int. Port name (or number) of the service. It will be translated to different yaml depending if it is a string or an integer. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.ingress.backend" -}} +service: + name: {{ .serviceName }} + port: + {{- if typeIs "string" .servicePort }} + name: {{ .servicePort }} + {{- else if or (typeIs "int" .servicePort) (typeIs "float64" .servicePort) }} + number: {{ .servicePort | int }} + {{- end }} +{{- end -}} + +{{/* +Return true if cert-manager required annotations for TLS signed +certificates are set in the Ingress annotations +Ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations +Usage: +{{ include "common.ingress.certManagerRequest" ( dict "annotations" .Values.path.to.the.ingress.annotations ) }} +*/}} +{{- define "common.ingress.certManagerRequest" -}} +{{ if or (hasKey .annotations "cert-manager.io/cluster-issuer") (hasKey .annotations "cert-manager.io/issuer") (hasKey .annotations "kubernetes.io/tls-acme") }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_labels.tpl b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_labels.tpl new file mode 100644 index 0000000..0a0cc54 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_labels.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Kubernetes standard labels +{{ include "common.labels.standard" (dict "customLabels" .Values.commonLabels "context" $) -}} +*/}} +{{- define "common.labels.standard" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{- $default := dict "app.kubernetes.io/name" (include "common.names.name" .context) "helm.sh/chart" (include "common.names.chart" .context) "app.kubernetes.io/instance" .context.Release.Name "app.kubernetes.io/managed-by" .context.Release.Service -}} +{{- with .context.Chart.AppVersion -}} +{{- $_ := set $default "app.kubernetes.io/version" . -}} +{{- end -}} +{{ template "common.tplvalues.merge" (dict "values" (list .customLabels $default) "context" .context) }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +helm.sh/chart: {{ include "common.names.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Chart.AppVersion }} +app.kubernetes.io/version: {{ . | quote }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Labels used on immutable fields such as deploy.spec.selector.matchLabels or svc.spec.selector +{{ include "common.labels.matchLabels" (dict "customLabels" .Values.podLabels "context" $) -}} + +We don't want to loop over custom labels appending them to the selector +since it's very likely that it will break deployments, services, etc. +However, it's important to overwrite the standard labels if the user +overwrote them on metadata.labels fields. +*/}} +{{- define "common.labels.matchLabels" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{ merge (pick (include "common.tplvalues.render" (dict "value" .customLabels "context" .context) | fromYaml) "app.kubernetes.io/name" "app.kubernetes.io/instance") (dict "app.kubernetes.io/name" (include "common.names.name" .context) "app.kubernetes.io/instance" .context.Release.Name ) | toYaml }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_names.tpl b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_names.tpl new file mode 100644 index 0000000..d5d0ae4 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_names.tpl @@ -0,0 +1,72 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "common.names.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "common.names.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "common.names.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- $releaseName := regexReplaceAll "(-?[^a-z\\d\\-])+-?" (lower .Release.Name) "-" -}} +{{- if contains $name $releaseName -}} +{{- $releaseName | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" $releaseName $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified dependency name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +Usage: +{{ include "common.names.dependency.fullname" (dict "chartName" "dependency-chart-name" "chartValues" .Values.dependency-chart "context" $) }} +*/}} +{{- define "common.names.dependency.fullname" -}} +{{- if .chartValues.fullnameOverride -}} +{{- .chartValues.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .chartName .chartValues.nameOverride -}} +{{- if contains $name .context.Release.Name -}} +{{- .context.Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .context.Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts. +*/}} +{{- define "common.names.namespace" -}} +{{- default .Release.Namespace .Values.namespaceOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a fully qualified app name adding the installation's namespace. +*/}} +{{- define "common.names.fullname.namespace" -}} +{{- printf "%s-%s" (include "common.names.fullname" .) (include "common.names.namespace" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_resources.tpl b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_resources.tpl new file mode 100644 index 0000000..d8a43e1 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_resources.tpl @@ -0,0 +1,50 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a resource request/limit object based on a given preset. +These presets are for basic testing and not meant to be used in production +{{ include "common.resources.preset" (dict "type" "nano") -}} +*/}} +{{- define "common.resources.preset" -}} +{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} +{{- $presets := dict + "nano" (dict + "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "2Gi") + ) + "micro" (dict + "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "2Gi") + ) + "small" (dict + "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "2Gi") + ) + "medium" (dict + "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "2Gi") + ) + "large" (dict + "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "2Gi") + ) + "xlarge" (dict + "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "2Gi") + ) + "2xlarge" (dict + "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "2Gi") + ) + }} +{{- if hasKey $presets .type -}} +{{- index $presets .type | toYaml -}} +{{- else -}} +{{- printf "ERROR: Preset key '%s' invalid. Allowed values are %s" .type (join "," (keys $presets)) | fail -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_secrets.tpl b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_secrets.tpl new file mode 100644 index 0000000..7868c00 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_secrets.tpl @@ -0,0 +1,192 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Generate secret name. + +Usage: +{{ include "common.secrets.name" (dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $) }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - defaultNameSuffix - String - Optional. It is used only if we have several secrets in the same deployment. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.secrets.name" -}} +{{- $name := (include "common.names.fullname" .context) -}} + +{{- if .defaultNameSuffix -}} +{{- $name = printf "%s-%s" $name .defaultNameSuffix | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- with .existingSecret -}} +{{- if not (typeIs "string" .) -}} +{{- with .name -}} +{{- $name = . -}} +{{- end -}} +{{- else -}} +{{- $name = . -}} +{{- end -}} +{{- end -}} + +{{- printf "%s" $name -}} +{{- end -}} + +{{/* +Generate secret key. + +Usage: +{{ include "common.secrets.key" (dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName") }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - key - String - Required. Name of the key in the secret. +*/}} +{{- define "common.secrets.key" -}} +{{- $key := .key -}} + +{{- if .existingSecret -}} + {{- if not (typeIs "string" .existingSecret) -}} + {{- if .existingSecret.keyMapping -}} + {{- $key = index .existingSecret.keyMapping $.key -}} + {{- end -}} + {{- end }} +{{- end -}} + +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Generate secret password or retrieve one if already created. + +Usage: +{{ include "common.secrets.passwords.manage" (dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "honorProvidedValues" false "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - providedValues - List - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - length - int - Optional - Length of the generated random password. + - strong - Boolean - Optional - Whether to add symbols to the generated random password. + - chartName - String - Optional - Name of the chart used when said chart is deployed as a subchart. + - context - Context - Required - Parent context. + - failOnNew - Boolean - Optional - Default to true. If set to false, skip errors adding new keys to existing secrets. + - skipB64enc - Boolean - Optional - Default to false. If set to true, no the secret will not be base64 encrypted. + - skipQuote - Boolean - Optional - Default to false. If set to true, no quotes will be added around the secret. + - honorProvidedValues - Boolean - Optional - Default to false. If set to true, the values in providedValues have higher priority than an existing secret +The order in which this function returns a secret password: + 1. Password provided via the values.yaml if honorProvidedValues = true + (If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned) + 2. Already existing 'Secret' resource + (If a 'Secret' resource is found under the name provided to the 'secret' parameter to this function and that 'Secret' resource contains a key with the name passed as the 'key' parameter to this function then the value of this existing secret password will be returned) + 3. Password provided via the values.yaml if honorProvidedValues = false + (If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned) + 4. Randomly generated secret password + (A new random secret password with the length specified in the 'length' parameter will be generated and returned) + +*/}} +{{- define "common.secrets.passwords.manage" -}} + +{{- $password := "" }} +{{- $subchart := "" }} +{{- $chartName := default "" .chartName }} +{{- $passwordLength := default 10 .length }} +{{- $providedPasswordKey := include "common.utils.getKeyFromList" (dict "keys" .providedValues "context" $.context) }} +{{- $providedPasswordValue := include "common.utils.getValueFromKey" (dict "key" $providedPasswordKey "context" $.context) }} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data }} +{{- if $secretData }} + {{- if hasKey $secretData .key }} + {{- $password = index $secretData .key | b64dec }} + {{- else if not (eq .failOnNew false) }} + {{- printf "\nPASSWORDS ERROR: The secret \"%s\" does not contain the key \"%s\"\n" .secret .key | fail -}} + {{- end -}} +{{- end }} + +{{- if and $providedPasswordValue .honorProvidedValues }} + {{- $password = tpl ($providedPasswordValue | toString) .context }} +{{- end }} + +{{- if not $password }} + {{- if $providedPasswordValue }} + {{- $password = tpl ($providedPasswordValue | toString) .context }} + {{- else }} + {{- if .context.Values.enabled }} + {{- $subchart = $chartName }} + {{- end -}} + + {{- if not (eq .failOnNew false) }} + {{- $requiredPassword := dict "valueKey" $providedPasswordKey "secret" .secret "field" .key "subchart" $subchart "context" $.context -}} + {{- $requiredPasswordError := include "common.validations.values.single.empty" $requiredPassword -}} + {{- $passwordValidationErrors := list $requiredPasswordError -}} + {{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" $passwordValidationErrors "context" $.context) -}} + {{- end }} + + {{- if .strong }} + {{- $subStr := list (lower (randAlpha 1)) (randNumeric 1) (upper (randAlpha 1)) | join "_" }} + {{- $password = randAscii $passwordLength }} + {{- $password = regexReplaceAllLiteral "\\W" $password "@" | substr 5 $passwordLength }} + {{- $password = printf "%s%s" $subStr $password | toString | shuffle }} + {{- else }} + {{- $password = randAlphaNum $passwordLength }} + {{- end }} + {{- end -}} +{{- end -}} +{{- if not .skipB64enc }} +{{- $password = $password | b64enc }} +{{- end -}} +{{- if .skipQuote -}} +{{- printf "%s" $password -}} +{{- else -}} +{{- printf "%s" $password | quote -}} +{{- end -}} +{{- end -}} + +{{/* +Reuses the value from an existing secret, otherwise sets its value to a default value. + +Usage: +{{ include "common.secrets.lookup" (dict "secret" "secret-name" "key" "keyName" "defaultValue" .Values.myValue "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - defaultValue - String - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - context - Context - Required - Parent context. + +*/}} +{{- define "common.secrets.lookup" -}} +{{- $value := "" -}} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data -}} +{{- if and $secretData (hasKey $secretData .key) -}} + {{- $value = index $secretData .key -}} +{{- else if .defaultValue -}} + {{- $value = .defaultValue | toString | b64enc -}} +{{- end -}} +{{- if $value -}} +{{- printf "%s" $value -}} +{{- end -}} +{{- end -}} + +{{/* +Returns whether a previous generated secret already exists + +Usage: +{{ include "common.secrets.exists" (dict "secret" "secret-name" "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - context - Context - Required - Parent context. +*/}} +{{- define "common.secrets.exists" -}} +{{- $secret := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret) }} +{{- if $secret }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_storage.tpl b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_storage.tpl new file mode 100644 index 0000000..aa75856 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_storage.tpl @@ -0,0 +1,21 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the proper Storage Class +{{ include "common.storage.class" ( dict "persistence" .Values.path.to.the.persistence "global" $) }} +*/}} +{{- define "common.storage.class" -}} +{{- $storageClass := (.global).storageClass | default .persistence.storageClass | default (.global).defaultStorageClass | default "" -}} +{{- if $storageClass -}} + {{- if (eq "-" $storageClass) -}} + {{- printf "storageClassName: \"\"" -}} + {{- else -}} + {{- printf "storageClassName: %s" $storageClass -}} + {{- end -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_tplvalues.tpl b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_tplvalues.tpl new file mode 100644 index 0000000..a04f4c1 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_tplvalues.tpl @@ -0,0 +1,52 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Renders a value that contains template perhaps with scope if the scope is present. +Usage: +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ ) }} +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ "scope" $app ) }} +*/}} +{{- define "common.tplvalues.render" -}} +{{- $value := typeIs "string" .value | ternary .value (.value | toYaml) }} +{{- if contains "{{" (toJson .value) }} + {{- if .scope }} + {{- tpl (cat "{{- with $.RelativeScope -}}" $value "{{- end }}") (merge (dict "RelativeScope" .scope) .context) }} + {{- else }} + {{- tpl $value .context }} + {{- end }} +{{- else }} + {{- $value }} +{{- end }} +{{- end -}} + +{{/* +Merge a list of values that contains template after rendering them. +Merge precedence is consistent with http://masterminds.github.io/sprig/dicts.html#merge-mustmerge +Usage: +{{ include "common.tplvalues.merge" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }} +*/}} +{{- define "common.tplvalues.merge" -}} +{{- $dst := dict -}} +{{- range .values -}} +{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | merge $dst -}} +{{- end -}} +{{ $dst | toYaml }} +{{- end -}} + +{{/* +Merge a list of values that contains template after rendering them. +Merge precedence is consistent with https://masterminds.github.io/sprig/dicts.html#mergeoverwrite-mustmergeoverwrite +Usage: +{{ include "common.tplvalues.merge-overwrite" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }} +*/}} +{{- define "common.tplvalues.merge-overwrite" -}} +{{- $dst := dict -}} +{{- range .values -}} +{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | mergeOverwrite $dst -}} +{{- end -}} +{{ $dst | toYaml }} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_utils.tpl b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_utils.tpl new file mode 100644 index 0000000..d53c74a --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_utils.tpl @@ -0,0 +1,77 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Print instructions to get a secret value. +Usage: +{{ include "common.utils.secret.getvalue" (dict "secret" "secret-name" "field" "secret-value-field" "context" $) }} +*/}} +{{- define "common.utils.secret.getvalue" -}} +{{- $varname := include "common.utils.fieldToEnvVar" . -}} +export {{ $varname }}=$(kubectl get secret --namespace {{ include "common.names.namespace" .context | quote }} {{ .secret }} -o jsonpath="{.data.{{ .field }}}" | base64 -d) +{{- end -}} + +{{/* +Build env var name given a field +Usage: +{{ include "common.utils.fieldToEnvVar" dict "field" "my-password" }} +*/}} +{{- define "common.utils.fieldToEnvVar" -}} + {{- $fieldNameSplit := splitList "-" .field -}} + {{- $upperCaseFieldNameSplit := list -}} + + {{- range $fieldNameSplit -}} + {{- $upperCaseFieldNameSplit = append $upperCaseFieldNameSplit ( upper . ) -}} + {{- end -}} + + {{ join "_" $upperCaseFieldNameSplit }} +{{- end -}} + +{{/* +Gets a value from .Values given +Usage: +{{ include "common.utils.getValueFromKey" (dict "key" "path.to.key" "context" $) }} +*/}} +{{- define "common.utils.getValueFromKey" -}} +{{- $splitKey := splitList "." .key -}} +{{- $value := "" -}} +{{- $latestObj := $.context.Values -}} +{{- range $splitKey -}} + {{- if not $latestObj -}} + {{- printf "please review the entire path of '%s' exists in values" $.key | fail -}} + {{- end -}} + {{- $value = ( index $latestObj . ) -}} + {{- $latestObj = $value -}} +{{- end -}} +{{- printf "%v" (default "" $value) -}} +{{- end -}} + +{{/* +Returns first .Values key with a defined value or first of the list if all non-defined +Usage: +{{ include "common.utils.getKeyFromList" (dict "keys" (list "path.to.key1" "path.to.key2") "context" $) }} +*/}} +{{- define "common.utils.getKeyFromList" -}} +{{- $key := first .keys -}} +{{- $reverseKeys := reverse .keys }} +{{- range $reverseKeys }} + {{- $value := include "common.utils.getValueFromKey" (dict "key" . "context" $.context ) }} + {{- if $value -}} + {{- $key = . }} + {{- end -}} +{{- end -}} +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Checksum a template at "path" containing a *single* resource (ConfigMap,Secret) for use in pod annotations, excluding the metadata (see #18376). +Usage: +{{ include "common.utils.checksumTemplate" (dict "path" "/configmap.yaml" "context" $) }} +*/}} +{{- define "common.utils.checksumTemplate" -}} +{{- $obj := include (print .context.Template.BasePath .path) .context | fromYaml -}} +{{ omit $obj "apiVersion" "kind" "metadata" | toYaml | sha256sum }} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_warnings.tpl b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_warnings.tpl new file mode 100644 index 0000000..62c44df --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/_warnings.tpl @@ -0,0 +1,109 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Warning about using rolling tag. +Usage: +{{ include "common.warnings.rollingTag" .Values.path.to.the.imageRoot }} +*/}} +{{- define "common.warnings.rollingTag" -}} + +{{- if and (contains "bitnami/" .repository) (not (.tag | toString | regexFind "-r\\d+$|sha256:")) }} +WARNING: Rolling tag detected ({{ .repository }}:{{ .tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. ++info https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-understand-rolling-tags-containers-index.html +{{- end }} +{{- end -}} + +{{/* +Warning about replaced images from the original. +Usage: +{{ include "common.warnings.modifiedImages" (dict "images" (list .Values.path.to.the.imageRoot) "context" $) }} +*/}} +{{- define "common.warnings.modifiedImages" -}} +{{- $affectedImages := list -}} +{{- $printMessage := false -}} +{{- $originalImages := .context.Chart.Annotations.images -}} +{{- range .images -}} + {{- $fullImageName := printf (printf "%s/%s:%s" .registry .repository .tag) -}} + {{- if not (contains $fullImageName $originalImages) }} + {{- $affectedImages = append $affectedImages (printf "%s/%s:%s" .registry .repository .tag) -}} + {{- $printMessage = true -}} + {{- end -}} +{{- end -}} +{{- if $printMessage }} + +⚠ SECURITY WARNING: Original containers have been substituted. This Helm chart was designed, tested, and validated on multiple platforms using a specific set of Bitnami and Tanzu Application Catalog containers. Substituting other containers is likely to cause degraded security and performance, broken chart features, and missing environment variables. + +Substituted images detected: +{{- range $affectedImages }} + - {{ . }} +{{- end }} +{{- end -}} +{{- end -}} + +{{/* +Warning about not setting the resource object in all deployments. +Usage: +{{ include "common.warnings.resources" (dict "sections" (list "path1" "path2") context $) }} +Example: +{{- include "common.warnings.resources" (dict "sections" (list "csiProvider.provider" "server" "volumePermissions" "") "context" $) }} +The list in the example assumes that the following values exist: + - csiProvider.provider.resources + - server.resources + - volumePermissions.resources + - resources +*/}} +{{- define "common.warnings.resources" -}} +{{- $values := .context.Values -}} +{{- $printMessage := false -}} +{{ $affectedSections := list -}} +{{- range .sections -}} + {{- if eq . "" -}} + {{/* Case where the resources section is at the root (one main deployment in the chart) */}} + {{- if not (index $values "resources") -}} + {{- $affectedSections = append $affectedSections "resources" -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Case where the are multiple resources sections (more than one main deployment in the chart) */}} + {{- $keys := split "." . -}} + {{/* We iterate through the different levels until arriving to the resource section. Example: a.b.c.resources */}} + {{- $section := $values -}} + {{- range $keys -}} + {{- $section = index $section . -}} + {{- end -}} + {{- if not (index $section "resources") -}} + {{/* If the section has enabled=false or replicaCount=0, do not include it */}} + {{- if and (hasKey $section "enabled") -}} + {{- if index $section "enabled" -}} + {{/* enabled=true */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else if and (hasKey $section "replicaCount") -}} + {{/* We need a casting to int because number 0 is not treated as an int by default */}} + {{- if (gt (index $section "replicaCount" | int) 0) -}} + {{/* replicaCount > 0 */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Default case, add it to the affected sections */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- if $printMessage }} + +WARNING: There are "resources" sections in the chart not set. Using "resourcesPreset" is not recommended for production. For production installations, please set the following values according to your workload needs: +{{- range $affectedSections }} + - {{ . }} +{{- end }} ++info https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/templates/validations/_cassandra.tpl b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/validations/_cassandra.tpl new file mode 100644 index 0000000..f8fd213 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/validations/_cassandra.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.cassandra.values.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.cassandra.dbUser.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.dbUser.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled cassandra. + +Usage: +{{ include "common.cassandra.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.cassandra.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.cassandra.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key dbUser + +Usage: +{{ include "common.cassandra.values.key.dbUser" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.key.dbUser" -}} + {{- if .subchart -}} + cassandra.dbUser + {{- else -}} + dbUser + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/templates/validations/_mariadb.tpl b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/validations/_mariadb.tpl new file mode 100644 index 0000000..6ea8c0f --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/validations/_mariadb.tpl @@ -0,0 +1,108 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MariaDB required passwords are not empty. + +Usage: +{{ include "common.validations.values.mariadb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MariaDB values are stored, e.g: "mysql-passwords-secret" + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mariadb.passwords" -}} + {{- $existingSecret := include "common.mariadb.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mariadb.values.enabled" . -}} + {{- $architecture := include "common.mariadb.values.architecture" . -}} + {{- $authPrefix := include "common.mariadb.values.key.auth" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mariadb-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- if not (empty $valueUsername) -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mariadb-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replication") -}} + {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mariadb-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mariadb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mariadb. + +Usage: +{{ include "common.mariadb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mariadb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mariadb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mariadb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mariadb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.key.auth" -}} + {{- if .subchart -}} + mariadb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/templates/validations/_mongodb.tpl b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/validations/_mongodb.tpl new file mode 100644 index 0000000..e678a6d --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/validations/_mongodb.tpl @@ -0,0 +1,67 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mongodb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDb is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mongodb. + +Usage: +{{ include "common.mongodb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mongodb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mongodb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mongodb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.key.auth" -}} + {{- if .subchart -}} + mongodb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mongodb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/templates/validations/_mysql.tpl b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/validations/_mysql.tpl new file mode 100644 index 0000000..fbb65c3 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/validations/_mysql.tpl @@ -0,0 +1,67 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mysql.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mysql. + +Usage: +{{ include "common.mysql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mysql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mysql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mysql.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mysql.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.key.auth" -}} + {{- if .subchart -}} + mysql.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/templates/validations/_postgresql.tpl b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/validations/_postgresql.tpl new file mode 100644 index 0000000..51d4716 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/validations/_postgresql.tpl @@ -0,0 +1,105 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to decide whether evaluate global values. + +Usage: +{{ include "common.postgresql.values.use.global" (dict "key" "key-of-global" "context" $) }} +Params: + - key - String - Required. Field to be evaluated within global, e.g: "existingSecret" +*/}} +{{- define "common.postgresql.values.use.global" -}} + {{- if .context.Values.global -}} + {{- if .context.Values.global.postgresql -}} + {{- index .context.Values.global.postgresql .key | quote -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.postgresql.values.existingSecret" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.existingSecret" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "existingSecret" "context" .context) -}} + + {{- if .subchart -}} + {{- default (.context.Values.postgresql.existingSecret | quote) $globalValue -}} + {{- else -}} + {{- default (.context.Values.existingSecret | quote) $globalValue -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled postgresql. + +Usage: +{{ include "common.postgresql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key postgressPassword. + +Usage: +{{ include "common.postgresql.values.key.postgressPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.postgressPassword" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "postgresqlUsername" "context" .context) -}} + + {{- if not $globalValue -}} + {{- if .subchart -}} + postgresql.postgresqlPassword + {{- else -}} + postgresqlPassword + {{- end -}} + {{- else -}} + global.postgresql.postgresqlPassword + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled.replication. + +Usage: +{{ include "common.postgresql.values.enabled.replication" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.enabled.replication" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.replication.enabled -}} + {{- else -}} + {{- printf "%v" .context.Values.replication.enabled -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key replication.password. + +Usage: +{{ include "common.postgresql.values.key.replicationPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.replicationPassword" -}} + {{- if .subchart -}} + postgresql.replication.password + {{- else -}} + replication.password + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/templates/validations/_redis.tpl b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/validations/_redis.tpl new file mode 100644 index 0000000..9fedfef --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/validations/_redis.tpl @@ -0,0 +1,48 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for enabled redis. + +Usage: +{{ include "common.redis.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.redis.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.redis.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right prefix path for the values + +Usage: +{{ include "common.redis.values.key.prefix" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false +*/}} +{{- define "common.redis.values.keys.prefix" -}} + {{- if .subchart -}}redis.{{- else -}}{{- end -}} +{{- end -}} + +{{/* +Checks whether the redis chart's includes the standarizations (version >= 14) + +Usage: +{{ include "common.redis.values.standarized.version" (dict "context" $) }} +*/}} +{{- define "common.redis.values.standarized.version" -}} + + {{- $standarizedAuth := printf "%s%s" (include "common.redis.values.keys.prefix" .) "auth" -}} + {{- $standarizedAuthValues := include "common.utils.getValueFromKey" (dict "key" $standarizedAuth "context" .context) }} + + {{- if $standarizedAuthValues -}} + {{- true -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/templates/validations/_validations.tpl b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/validations/_validations.tpl new file mode 100644 index 0000000..7cdee61 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/templates/validations/_validations.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate values must not be empty. + +Usage: +{{- $validateValueConf00 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-01") -}} +{{ include "common.validations.values.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" +*/}} +{{- define "common.validations.values.multiple.empty" -}} + {{- range .required -}} + {{- include "common.validations.values.single.empty" (dict "valueKey" .valueKey "secret" .secret "field" .field "context" $.context) -}} + {{- end -}} +{{- end -}} + +{{/* +Validate a value must not be empty. + +Usage: +{{ include "common.validations.value.empty" (dict "valueKey" "mariadb.password" "secret" "secretName" "field" "my-password" "subchart" "subchart" "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" + - subchart - String - Optional - Name of the subchart that the validated password is part of. +*/}} +{{- define "common.validations.values.single.empty" -}} + {{- $value := include "common.utils.getValueFromKey" (dict "key" .valueKey "context" .context) }} + {{- $subchart := ternary "" (printf "%s." .subchart) (empty .subchart) }} + + {{- if not $value -}} + {{- $varname := "my-value" -}} + {{- $getCurrentValue := "" -}} + {{- if and .secret .field -}} + {{- $varname = include "common.utils.fieldToEnvVar" . -}} + {{- $getCurrentValue = printf " To get the current value:\n\n %s\n" (include "common.utils.secret.getvalue" .) -}} + {{- end -}} + {{- printf "\n '%s' must not be empty, please add '--set %s%s=$%s' to the command.%s" .valueKey $subchart .valueKey $varname $getCurrentValue -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/charts/common/values.yaml b/backing-services/gitea/charts/postgresql-ha/charts/common/values.yaml new file mode 100644 index 0000000..de2cac5 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/charts/common/values.yaml @@ -0,0 +1,8 @@ +# Copyright Broadcom, Inc. All Rights Reserved. +# SPDX-License-Identifier: APACHE-2.0 + +## bitnami/common +## It is required by CI/CD tools and processes. +## @skip exampleValue +## +exampleValue: common-chart diff --git a/backing-services/gitea/charts/postgresql-ha/templates/NOTES.txt b/backing-services/gitea/charts/postgresql-ha/templates/NOTES.txt new file mode 100644 index 0000000..d87d966 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/NOTES.txt @@ -0,0 +1,98 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +{{- $releaseNamespace := include "common.names.namespace" . }} +{{- $clusterDomain := .Values.clusterDomain }} +{{- $postgresqlSecretName := include "postgresql-ha.postgresqlSecretName" . }} +{{- $postgresqlUsername := include "postgresql-ha.postgresqlUsername" . }} +{{- $postgresqlDatabase := include "postgresql-ha.postgresqlDatabase" . }} +{{- $postgresqlCredentials := printf "-U %s%s" $postgresqlUsername (ternary "" (printf " -d %s" $postgresqlDatabase) (empty $postgresqlDatabase)) }} +{{- $pgpoolSvcName := include "postgresql-ha.pgpool" . }} + +⚠ WARNING: Since August 28th, 2025, only a limited subset of images/charts are available for free. + Subscribe to Bitnami Secure Images to receive continued support and security updates. + More info at https://bitnami.com and https://github.com/bitnami/containers/issues/83267 + +** Please be patient while the chart is being deployed ** + +{{- if .Values.diagnosticMode.enabled }} +The chart has been deployed in diagnostic mode. All probes have been disabled and the command has been overwritten with: + + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" .) | nindent 4 }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" .) | nindent 4 }} + +Get the list of pods by executing: + + kubectl get pods --namespace {{ $releaseNamespace }} -l app.kubernetes.io/instance={{ .Release.Name }} + +Access the pod you want to debug by executing + + kubectl exec --namespace {{ $releaseNamespace }} -ti -- bash + +In order to replicate the container startup scripts, check the /opt/bitnami/scripts folder. + + Default PostgreSQL startup command + + /opt/bitnami/scripts/postgresql-repmgr/entrypoint.sh /opt/bitnami/scripts/postgresql-repmgr/run.sh + + Default Pgpool-II startup command + + /opt/bitnami/scripts/pgpool/entrypoint.sh /opt/bitnami/scripts/pgpool/run.sh + +{{- else }} +PostgreSQL can be accessed through Pgpool-II via port {{ .Values.service.ports.postgresql }} on the following DNS name from within your cluster: + + {{ $pgpoolSvcName }}.{{ $releaseNamespace }}.svc.{{ $clusterDomain }} + +Pgpool-II acts as a load balancer for PostgreSQL and forward read/write connections to the primary node while read-only connections are forwarded to standby nodes. + +To get the password for {{ $postgresqlUsername | quote }} user run: + + {{ include "common.utils.secret.getvalue" (dict "secret" $postgresqlSecretName "field" "password" "context" $) }} + +To connect to your database run the following command: + + kubectl run {{ include "common.names.fullname" . }}-client --rm --tty -i --restart='Never' --namespace {{ $releaseNamespace }} \ + --image {{ include "postgresql-ha.postgresql.image" . }} --env="PGPASSWORD=$PASSWORD" {{ if and (.Values.pgpool.networkPolicy.enabled) (not .Values.pgpool.networkPolicy.allowExternal) }}--labels="{{ include "common.names.fullname" . }}-client=true" {{- end }} \ + --command -- psql -h {{ $pgpoolSvcName }} -p {{ .Values.service.ports.postgresql }} {{ $postgresqlCredentials }} + +{{- if and .Values.pgpool.networkPolicy.enabled (not .Values.pgpool.networkPolicy.allowExternal) }} + +Note: Since NetworkPolicy is enabled, only pods with label "{{ $pgpoolSvcName }}-client=true" will be able to connect Pgpool-II. + +{{- 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 {{ $releaseNamespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get --namespace {{ $releaseNamespace }} -o jsonpath="{.spec.ports[0].nodePort}" svc {{ $pgpoolSvcName }}) + PGPASSWORD="$PASSWORD" psql -h $NODE_IP -p $NODE_PORT {{ $postgresqlCredentials }} + +{{- 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 {{ $releaseNamespace }} -w {{ $pgpoolSvcName }} + + export SERVICE_IP=$(kubectl get svc --namespace {{ $releaseNamespace }} {{ $pgpoolSvcName }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") + PGPASSWORD="$PASSWORD" psql -h $SERVICE_IP -p {{ .Values.service.ports.postgresql }} {{ $postgresqlCredentials }} + +{{- else if contains "ClusterIP" .Values.service.type }} + + kubectl port-forward --namespace {{ $releaseNamespace }} svc/{{ $pgpoolSvcName }} {{ .Values.service.ports.postgresql }}:{{ .Values.service.ports.postgresql }} & + psql -h 127.0.0.1 -p {{ .Values.service.ports.postgresql }} {{ $postgresqlCredentials }} + +{{- end }} +{{- end }} + +{{- include "postgresql-ha.validateValues" . }} +{{- $resourcesSections := list "postgresql" "pgpool" }} +{{- if .Values.witness.create }} + {{- $resourcesSections = append $resourcesSections "witness" }} +{{- end }} +{{- include "postgresql-ha.checkRollingTags" . }} +{{- include "common.warnings.resources" (dict "sections" $resourcesSections "context" .) }} +{{- include "common.warnings.modifiedImages" (dict "images" (list .Values.postgresql.image .Values.pgpool.image .Values.metrics.image .Values.volumePermissions.image) "context" .) }} +{{- include "common.errors.insecureImages" (dict "images" (list .Values.postgresql.image .Values.pgpool.image .Values.metrics.image .Values.volumePermissions.image) "context" .) }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/_helpers.tpl b/backing-services/gitea/charts/postgresql-ha/templates/_helpers.tpl new file mode 100644 index 0000000..55fc25a --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/_helpers.tpl @@ -0,0 +1,452 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Fully qualified app name for PostgreSQL +*/}} +{{- define "postgresql-ha.postgresql" -}} +{{- printf "%s-postgresql" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Fully qualified app name for Pgpool-II +*/}} +{{- define "postgresql-ha.pgpool" -}} +{{- printf "%s-pgpool" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Fully qualified app name for LDAP +*/}} +{{- define "postgresql-ha.ldap" -}} +{{- printf "%s-ldap" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "postgresql-ha.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "common.names.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Return the proper PostgreSQL image name +*/}} +{{- define "postgresql-ha.postgresql.image" -}} +{{- include "common.images.image" ( dict "imageRoot" .Values.postgresql.image "global" .Values.global ) -}} +{{- end -}} + +{{/* +Return the proper Pgpool-II image name +*/}} +{{- define "postgresql-ha.pgpool.image" -}} +{{- include "common.images.image" ( dict "imageRoot" .Values.pgpool.image "global" .Values.global ) -}} +{{- end -}} + +{{/* +Return the proper PostgreSQL Prometheus exporter image name +*/}} +{{- define "postgresql-ha.volumePermissions.image" -}} +{{- include "common.images.image" ( dict "imageRoot" .Values.volumePermissions.image "global" .Values.global ) -}} +{{- end -}} + +{{/* +Return the proper PostgreSQL Prometheus exporter image name +*/}} +{{- define "postgresql-ha.metrics.image" -}} +{{- include "common.images.image" ( dict "imageRoot" .Values.metrics.image "global" .Values.global ) -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "postgresql-ha.image.pullSecrets" -}} +{{- include "common.images.renderPullSecrets" (dict "images" (list .Values.postgresql.image .Values.pgpool.image .Values.volumePermissions.image .Values.metrics.image) "context" $) -}} +{{- end -}} + +{{/* +Return the PostgreSQL username +*/}} +{{- define "postgresql-ha.postgresqlUsername" -}} +{{- coalesce ((.Values.global).postgresql).username .Values.postgresql.username | default "" -}} +{{- end -}} + +{{/* +Return the PostgreSQL database to create +*/}} +{{- define "postgresql-ha.postgresqlDatabase" -}} +{{- coalesce ((.Values.global).postgresql).database .Values.postgresql.database "postgres" -}} +{{- end -}} + +{{/* +Return the Pgpool Admin username +*/}} +{{- define "postgresql-ha.pgpoolAdminUsername" -}} +{{- coalesce ((.Values.global).pgpool).adminUsername .Values.pgpool.adminUsername | default "" -}} +{{- end -}} + + +{{/* +Return the Pgpool-II SR Check username +*/}} +{{- define "postgresql-ha.pgoolSrCheckUsername" -}} +{{- coalesce ((.Values.global).pgpool).srCheckUsername .Values.pgpool.srCheckUsername | default "" -}} +{{- end -}} + +{{/* +Get the metrics ConfigMap name. +*/}} +{{- define "postgresql.metricsCM" -}} +{{- printf "%s-metrics" (include "common.names.fullname" .) -}} +{{- end -}} + +{{/* +Return the PostgreSQL Repmgr username +*/}} +{{- define "postgresql-ha.postgresqlRepmgrUsername" -}} +{{- coalesce ((.Values.global).postgresql).repmgrUsername .Values.postgresql.repmgrUsername | default "" -}} +{{- end -}} + +{{/* +Return the database to use for Repmgr +*/}} +{{- define "postgresql-ha.repmgrDatabase" -}} +{{- coalesce ((.Values.global).postgresql).repmgrDatabase .Values.postgresql.repmgrDatabase | default "" -}} +{{- end -}} + +{{/* +Return true if the PostgreSQL credential secret has a separate entry for the postgres user +*/}} +{{- define "postgresql-ha.postgresqlSeparatePostgresPassword" -}} +{{- if (include "postgresql-ha.postgresqlCreateSecret" .) -}} + {{- if not (eq (include "postgresql-ha.postgresqlUsername" .) "postgres") }} + {{- true -}} + {{- end -}} +{{- else -}} + {{- $pgSecret := index (lookup "v1" "Secret" (include "common.names.namespace" .) (include "postgresql-ha.postgresqlSecretName" .)) "data" -}} + {{- if and $pgSecret (index $pgSecret "postgres-password") -}} + {{- true -}} + {{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a secret object should be created for PostgreSQL +*/}} +{{- define "postgresql-ha.postgresqlCreateSecret" -}} +{{- if empty (coalesce ((.Values.global).postgresql).existingSecret .Values.postgresql.existingSecret | default "") -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the PostgreSQL credentials secret. +*/}} +{{- define "postgresql-ha.postgresqlSecretName" -}} +{{- if include "postgresql-ha.postgresqlCreateSecret" . -}} + {{- print (include "postgresql-ha.postgresql" .) -}} +{{- else }} + {{- print (tpl (coalesce ((.Values.global).postgresql).existingSecret .Values.postgresql.existingSecret) .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a secret object should be created for Pgpool-II +*/}} +{{- define "postgresql-ha.pgpoolCreateSecret" -}} +{{- if empty (coalesce ((.Values.global).pgpool).existingSecret .Values.pgpool.existingSecret | default "") -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the Pgpool credentials secret. +*/}} +{{- define "postgresql-ha.pgpoolSecretName" -}} +{{- if include "postgresql-ha.pgpoolCreateSecret" . -}} + {{- print (include "postgresql-ha.pgpool" .) -}} +{{- else }} + {{- print (tpl (coalesce ((.Values.global).pgpool).existingSecret .Values.pgpool.existingSecret) .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return the PostgreSQL configuration ConfigMap +*/}} +{{- define "postgresql-ha.postgresqlConfigurationCM" -}} +{{- if .Values.postgresql.configurationCM -}} + {{- print (tpl .Values.postgresql.configurationCM .) -}} +{{- else -}} + {{- printf "%s-configuration" (include "postgresql-ha.postgresql" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return the PostgreSQL extended configuration ConfigMap +*/}} +{{- define "postgresql-ha.postgresqlExtendedConfCM" -}} +{{- if .Values.postgresql.extendedConfCM -}} + {{- print (tpl .Values.postgresql.extendedConfCM .) -}} +{{- else -}} + {{- printf "%s-extended-configuration" (include "postgresql-ha.postgresql" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return the Pgpool-II configuration ConfigMap +*/}} +{{- define "postgresql-ha.pgpoolConfigurationCM" -}} +{{- if .Values.pgpool.configurationCM -}} + {{- print (tpl .Values.pgpool.configurationCM .) -}} +{{- else -}} + {{- printf "%s-configuration" (include "postgresql-ha.pgpool" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return the PostgreSQL initdb scripts ConfigMap +*/}} +{{- define "postgresql-ha.postgresqlInitdbScriptsCM" -}} +{{- if .Values.postgresql.initdbScriptsCM -}} + {{- print (tpl .Values.postgresql.initdbScriptsCM .) -}} +{{- else -}} + {{- printf "%s-initdb-scripts" (include "postgresql-ha.postgresql" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Get the initialization scripts Secret name. +*/}} +{{- define "postgresql-ha.postgresqlInitdbScriptsSecret" -}} +{{- if .Values.postgresql.initdbScriptsSecret -}} +{{- include "common.tplvalues.render" (dict "value" .Values.postgresql.initdbScriptsSecret "context" $) -}} +{{- end -}} +{{- end -}} + +{{/* +Return the Pgpool-II initdb scripts configmap. +*/}} +{{- define "postgresql-ha.pgpoolInitdbScriptsCM" -}} +{{- if .Values.pgpool.initdbScriptsCM -}} +{{- printf "%s" (tpl .Values.pgpool.initdbScriptsCM $) -}} +{{- else -}} +{{- printf "%s-initdb-scripts" (include "postgresql-ha.pgpool" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Get the pgpool initialization scripts Secret name. +*/}} +{{- define "postgresql-ha.pgpoolInitdbScriptsSecret" -}} +{{- if .Values.pgpool.initdbScriptsSecret -}} +{{- include "common.tplvalues.render" (dict "value" .Values.pgpool.initdbScriptsSecret "context" $) -}} +{{- end -}} +{{- end -}} + +{{/* +Return the LDAP bind password +*/}} +{{- define "postgresql-ha.ldapPassword" -}} +{{- coalesce ((.Values.global).ldap).bindpw .Values.ldap.bindpw (randAlphaNum 10) -}} +{{- end -}} + +{{/* +Return true if a secret object should be created for LDAP +*/}} +{{- define "postgresql-ha.ldapCreateSecret" -}} +{{- if empty (coalesce ((.Values.global).ldap).existingSecret .Values.ldap.existingSecret | default "") -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the LDAP credentials secret. +*/}} +{{- define "postgresql-ha.ldapSecretName" -}} +{{- if include "postgresql-ha.ldapCreateSecret" . -}} + {{- print (include "postgresql-ha.ldap" .) -}} +{{- else }} + {{- print (tpl (coalesce ((.Values.global).ldap).existingSecret .Values.ldap.existingSecret) .) -}} +{{- end -}} +{{- end -}} + +{{/* Check if there are rolling tags in the images */}} +{{- define "postgresql-ha.checkRollingTags" -}} +{{- include "common.warnings.rollingTag" .Values.postgresql.image -}} +{{- include "common.warnings.rollingTag" .Values.pgpool.image -}} +{{- include "common.warnings.rollingTag" .Values.metrics.image -}} +{{- include "common.warnings.rollingTag" .Values.volumePermissions.image -}} +{{- end -}} + +{{/* +Compile all warnings into a single message, and call fail. +*/}} +{{- define "postgresql-ha.validateValues" -}} +{{- $messages := list -}} +{{- $messages := append $messages (include "postgresql-ha.validateValues.nodesHostnames" .) -}} +{{- $messages := append $messages (include "postgresql-ha.validateValues.ldap" .) -}} +{{- $messages := append $messages (include "postgresql-ha.validateValues.ldapPgHba" .) -}} +{{- $messages := append $messages (include "postgresql-ha.validateValues.upgradeRepmgrExtension" .) -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}} +{{- end -}} +{{- end -}} + +{{/* Validate values of PostgreSQL HA - PostgreSQL nodes hostnames cannot be longer than 128 characters */}} +{{- define "postgresql-ha.validateValues.nodesHostnames" -}} +{{- $postgresqlFullname := include "postgresql-ha.postgresql" . }} +{{- $postgresqlHeadlessServiceName := printf "%s-headless" (include "postgresql-ha.postgresql" .) }} +{{- $nodeHostname := printf "%s-00.%s" $postgresqlFullname $postgresqlHeadlessServiceName }} +{{- if gt (len $nodeHostname) 128 -}} +postgresql-ha: Nodes hostnames + PostgreSQL nodes hostnames ({{ $nodeHostname }}) exceeds the characters limit for Pgpool: 128. + Consider using a shorter release name or namespace. +{{- end -}} +{{- end -}} + +{{/* Validate values of PostgreSQL HA - must provide mandatory LDAP parameters when LDAP is enabled */}} +{{- define "postgresql-ha.validateValues.ldap" -}} +{{- if and .Values.ldap.enabled (or (empty .Values.ldap.uri) (empty .Values.ldap.basedn) (empty .Values.ldap.binddn) (and (empty .Values.ldap.bindpw) (empty .Values.ldap.existingSecret))) -}} +postgresql-ha: LDAP + Invalid LDAP configuration. When enabling LDAP support, the parameters "ldap.uri", + "ldap.basedn", "ldap.binddn", and "ldap.bindpw" are mandatory. Please provide them: + + $ helm install {{ .Release.Name }} oci://registry-1.docker.io/bitnamicharts/postgresql-ha \ + --set ldap.enabled=true \ + --set ldap.uri="ldap://my_ldap_server" \ + --set ldap.basedn="dc=example\,dc=org" \ + --set ldap.binddn="cn=admin\,dc=example\,dc=org" \ + --set ldap.bindpw="admin" +{{- end -}} +{{- end -}} + +{{/* Validate values of PostgreSQL HA - PostgreSQL HBA configuration must trust every user when LDAP is enabled */}} +{{- define "postgresql-ha.validateValues.ldapPgHba" -}} +{{- if and .Values.ldap.enabled (not .Values.postgresql.pgHbaTrustAll) }} +postgresql-ha: LDAP & pg_hba.conf + PostgreSQL HBA configuration must trust every user when LDAP is enabled. + Please configure HBA to trust every user (--set postgresql.pgHbaTrustAll=true) +{{- end -}} +{{- end -}} + +{{/* Validate values of PostgreSQL HA - There must be an unique replica when upgrading repmgr extension */}} +{{- define "postgresql-ha.validateValues.upgradeRepmgrExtension" -}} +{{- $postgresqlReplicaCount := int .Values.postgresql.replicaCount }} +{{- if and .Values.postgresql.upgradeRepmgrExtension (gt $postgresqlReplicaCount 1) }} +postgresql-ha: Upgrade repmgr extension + There must be only one replica when upgrading repmgr extension: + + $ helm upgrade {{ .Release.Name }} oci://registry-1.docker.io/bitnamicharts/postgresql-ha \ + --set postgresql.replicaCount=1 \ + --set postgresql.upgradeRepmgrExtension=true +{{- end -}} +{{- end -}} + +{{/* Set PostgreSQL PGPASSWORD as environment variable depends on configuration */}} +{{- define "postgresql-ha.pgpassword" -}} +{{- if .Values.postgresql.usePasswordFiles -}} +PGPASSWORD=$(< $POSTGRES_PASSWORD_FILE) +{{- else -}} +PGPASSWORD=$POSTGRES_PASSWORD +{{- end -}} +{{- end -}} + +{{/* Set Pgpool-II PGPASSWORD as environment variable depends on configuration */}} +{{- define "postgresql-ha.pgpoolPostgresPassword" -}} +{{- if .Values.postgresql.usePasswordFiles -}} +PGPASSWORD=$(< $PGPOOL_POSTGRES_PASSWORD_FILE) +{{- else -}} +PGPASSWORD=$PGPOOL_POSTGRES_PASSWORD +{{- end -}} +{{- end -}} + +{{/* +Return the Pgpool-II secret containing custom users to be added to pool_passwd file. +*/}} +{{- define "postgresql-ha.pgpoolCustomUsersSecretName" -}} +{{- if .Values.pgpool.customUsersSecret -}} + {{- print (tpl .Values.pgpool.customUsersSecret .) -}} +{{- else -}} + {{- printf "%s-custom-users" (include "postgresql-ha.pgpool" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the cert file. +*/}} +{{- define "postgresql-ha.pgpool.tlsCert" -}} +{{- if and .Values.pgpool.tls.enabled .Values.pgpool.tls.autoGenerated }} + {{- printf "/opt/bitnami/pgpool/certs/tls.crt" -}} +{{- else -}} + {{- required "Certificate filename is required when TLS in enabled" .Values.pgpool.tls.certFilename | printf "/opt/bitnami/pgpool/certs/%s" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the cert key file. +*/}} +{{- define "postgresql-ha.pgpool.tlsCertKey" -}} +{{- if and .Values.pgpool.tls.enabled .Values.pgpool.tls.autoGenerated }} + {{- printf "/opt/bitnami/pgpool/certs/tls.key" -}} +{{- else -}} + {{- required "Certificate Key filename is required when TLS in enabled" .Values.pgpool.tls.certKeyFilename | printf "/opt/bitnami/pgpool/certs/%s" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the CA cert file. +*/}} +{{- define "postgresql-ha.pgpool.tlsCACert" -}} +{{- if and .Values.pgpool.tls.enabled .Values.pgpool.tls.autoGenerated }} + {{- printf "/opt/bitnami/pgpool/certs/ca.crt" -}} +{{- else -}} + {{- printf "/opt/bitnami/pgpool/certs/%s" .Values.pgpool.tls.certCAFilename -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a TLS credentials secret object should be created +*/}} +{{- define "postgresql-ha.createTlsSecret" -}} +{{- if and .Values.pgpool.tls.enabled .Values.pgpool.tls.autoGenerated (not .Values.pgpool.tls.certificatesSecret) }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the CA cert file. +*/}} +{{- define "postgresql-ha.tlsSecretName" -}} +{{- if .Values.pgpool.tls.enabled }} +{{- if .Values.pgpool.tls.autoGenerated }} + {{- printf "%s-crt" (include "postgresql-ha.pgpool" .) -}} +{{- else -}} + {{ required "A secret containing TLS certificates is required when TLS is enabled" (tpl .Values.pgpool.tls.certificatesSecret $) }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the cert file. +*/}} +{{- define "postgresql-ha.postgresql.tlsCert" -}} +{{- required "Certificate filename is required when TLS in enabled" .Values.postgresql.tls.certFilename | printf "/opt/bitnami/postgresql/certs/%s" -}} +{{- end -}} + +{{/* +Return the path to the cert key file. +*/}} +{{- define "postgresql-ha.postgresql.tlsCertKey" -}} +{{- required "Certificate Key filename is required when TLS in enabled" .Values.postgresql.tls.certKeyFilename | printf "/opt/bitnami/postgresql/certs/%s" -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/backup/cronjob.yaml b/backing-services/gitea/charts/postgresql-ha/templates/backup/cronjob.yaml new file mode 100644 index 0000000..65f2239 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/backup/cronjob.yaml @@ -0,0 +1,156 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.backup.enabled }} +apiVersion: batch/v1 +kind: CronJob +metadata: + name: {{ include "postgresql-ha.postgresql" . }}-pgdumpall + namespace: {{ .Release.Namespace | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.backup.cronjob.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: pg_dumpall + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.backup.cronjob.annotations .Values.commonAnnotations ) "context" . ) }} + {{- if $annotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + schedule: {{ .Values.backup.cronjob.schedule | quote }} + {{- if .Values.backup.cronjob.timezone }} + timeZone: {{ .Values.backup.cronjob.timezone | quote }} + {{- end }} + concurrencyPolicy: {{ .Values.backup.cronjob.concurrencyPolicy }} + failedJobsHistoryLimit: {{ .Values.backup.cronjob.failedJobsHistoryLimit }} + successfulJobsHistoryLimit: {{ .Values.backup.cronjob.successfulJobsHistoryLimit }} + {{- if .Values.backup.cronjob.startingDeadlineSeconds }} + startingDeadlineSeconds: {{ .Values.backup.cronjob.startingDeadlineSeconds }} + {{- end }} + jobTemplate: + spec: + {{- if .Values.backup.cronjob.ttlSecondsAfterFinished }} + ttlSecondsAfterFinished: {{ .Values.backup.cronjob.ttlSecondsAfterFinished }} + {{- end }} + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 12 }} + app.kubernetes.io/component: pg_dumpall + {{- if $annotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 12 }} + {{- end }} + spec: + {{- include "postgresql-ha.image.pullSecrets" . | nindent 10 }} + {{- if .Values.backup.cronjob.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.nodeSelector "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.backup.cronjob.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.tolerations "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.backup.cronjob.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.affinity "context" $) | nindent 12 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.backup.cronjob.podAffinityPreset "component" "backup" "customLabels" $labels "context" $) | nindent 14 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.backup.cronjob.nodeAffinityPreset.type "key" .Values.backup.cronjob.nodeAffinityPreset.key "values" .Values.backup.cronjob.nodeAffinityPreset.values) | nindent 14 }} + {{- end }} + containers: + - name: {{ include "postgresql-ha.postgresql" . }}-pgdumpall + image: {{ include "postgresql-ha.postgresql.image" . }} + imagePullPolicy: {{ .Values.postgresql.image.pullPolicy | quote }} + env: + - name: PGUSER + value: "postgres" + {{- if .Values.postgresql.usePasswordFiles }} + - name: PGPASSWORD_FILE + {{- if (include "postgresql-ha.postgresqlSeparatePostgresPassword" .) }} + value: "/opt/bitnami/postgresql/secrets/postgres-password" + {{- else }} + value: "/opt/bitnami/postgresql/secrets/password" + {{- end }} + {{- else }} + - name: PGPASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql-ha.postgresqlSecretName" . }} + {{- if (include "postgresql-ha.postgresqlSeparatePostgresPassword" .) }} + key: postgres-password + {{- else }} + key: password + {{- end }} + {{- end }} + - name: PGHOST + value: {{ include "postgresql-ha.postgresql" . }} + - name: PGPORT + value: {{ .Values.service.ports.postgresql | quote }} + - name: PGDUMP_DIR + value: {{ .Values.backup.cronjob.storage.mountPath }} + {{- if .Values.postgresql.tls.enabled }} + - name: PGSSLROOTCERT + values: {{ include "postgresql-ha.pgpool.tlsCACert" . }} + {{- end }} + {{- if .Values.backup.cronjob.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.extraEnvVars "context" $) | nindent 14 }} + {{- end }} + envFrom: + {{- if .Values.backup.cronjob.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.backup.cronjob.extraEnvVarsCM }} + {{- end }} + {{- if .Values.backup.cronjob.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.backup.cronjob.extraEnvVarsSecret }} + {{- end }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.command "context" $) | nindent 14 }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if .Values.postgresql.tls.enabled }} + - name: certs + mountPath: /certs + {{- end }} + - name: datadir + mountPath: {{ .Values.backup.cronjob.storage.mountPath }} + subPath: {{ .Values.backup.cronjob.storage.subPath }} + {{- if .Values.postgresql.usePasswordFiles }} + - name: password + mountPath: /opt/bitnami/postgresql/secrets/ + {{- end }} + {{- if .Values.backup.cronjob.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.extraVolumeMounts "context" $) | nindent 14 }} + {{- end }} + {{- if .Values.backup.cronjob.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.backup.cronjob.containerSecurityContext "context" $) | nindent 14 }} + {{- end }} + {{- if .Values.backup.cronjob.resources }} + resources: {{- toYaml .Values.backup.cronjob.resources | nindent 14 }} + {{- else if ne .Values.backup.cronjob.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.backup.cronjob.resourcesPreset) | nindent 14 }} + {{- end }} + restartPolicy: {{ .Values.backup.cronjob.restartPolicy }} + {{- if .Values.backup.cronjob.podSecurityContext.enabled }} + securityContext: + fsGroup: {{ .Values.backup.cronjob.podSecurityContext.fsGroup }} + {{- end }} + volumes: + - name: empty-dir + emptyDir: {} + {{- if .Values.backup.cronjob.storage.existingClaim }} + - name: datadir + persistentVolumeClaim: + claimName: {{ printf "%s" (tpl .Values.backup.cronjob.storage.existingClaim .) }} + {{- else }} + - name: datadir + persistentVolumeClaim: + claimName: {{ include "postgresql-ha.postgresql" . }}-pgdumpall + {{- end }} + {{- if .Values.postgresql.usePasswordFiles }} + - name: password + secret: + secretName: {{ include "postgresql-ha.postgresqlSecretName" . }} + {{- end }} + {{- if .Values.backup.cronjob.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.extraVolumes "context" $) | nindent 12 }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/backup/pvc.yaml b/backing-services/gitea/charts/postgresql-ha/templates/backup/pvc.yaml new file mode 100644 index 0000000..50e9b1d --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/backup/pvc.yaml @@ -0,0 +1,34 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.backup.enabled (not .Values.backup.cronjob.storage.existingClaim) -}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "postgresql-ha.postgresql" . }}-pgdumpall + namespace: {{ .Release.Namespace | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.backup.cronjob.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: pg_dumpall + {{- if or .Values.backup.cronjob.annotations .Values.commonAnnotations .Values.backup.cronjob.storage.resourcePolicy }} + annotations: + {{- if or .Values.backup.cronjob.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.backup.cronjob.annotations .Values.commonAnnotations ) "context" . ) }} + {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.backup.cronjob.storage.resourcePolicy }} + helm.sh/resource-policy: {{ .Values.backup.cronjob.storage.resourcePolicy | quote }} + {{- end }} + {{- end }} +spec: + accessModes: + {{- range .Values.backup.cronjob.storage.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.backup.cronjob.storage.size | quote }} + {{ include "common.storage.class" (dict "persistence" .Values.backup.cronjob.storage "global" .Values.global) }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/extra-list.yaml b/backing-services/gitea/charts/postgresql-ha/templates/extra-list.yaml new file mode 100644 index 0000000..329f5c6 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/extra-list.yaml @@ -0,0 +1,9 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/ldap-secrets.yaml b/backing-services/gitea/charts/postgresql-ha/templates/ldap-secrets.yaml new file mode 100644 index 0000000..51f4418 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/ldap-secrets.yaml @@ -0,0 +1,19 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.ldap.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "postgresql-ha.ldap" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + bind-password: {{ (include "postgresql-ha.ldapPassword" .) | b64enc | quote }} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/metrics-configmap.yaml b/backing-services/gitea/charts/postgresql-ha/templates/metrics-configmap.yaml new file mode 100644 index 0000000..b79d676 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/metrics-configmap.yaml @@ -0,0 +1,18 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.customMetrics }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "postgresql.metricsCM" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + custom-metrics.yaml: {{ toYaml .Values.metrics.customMetrics | quote }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/pgpool/configmap.yaml b/backing-services/gitea/charts/postgresql-ha/templates/pgpool/configmap.yaml new file mode 100644 index 0000000..3786be8 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/pgpool/configmap.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (or .Values.pgpool.configuration .Values.pgpool.poolHbaConfiguration) (not .Values.pgpool.configurationCM) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-configuration" (include "postgresql-ha.pgpool" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.pgpool.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: pgpool + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + {{- if .Values.pgpool.configuration }} + pgpool.conf: |- + {{- include "common.tplvalues.render" (dict "value" .Values.pgpool.configuration "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.pgpool.poolHbaConfiguration }} + pool_hba.conf: |- + {{- include "common.tplvalues.render" (dict "value" .Values.pgpool.poolHbaConfiguration "context" $) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/pgpool/custom-users-secrets.yaml b/backing-services/gitea/charts/postgresql-ha/templates/pgpool/custom-users-secrets.yaml new file mode 100644 index 0000000..173f81c --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/pgpool/custom-users-secrets.yaml @@ -0,0 +1,23 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (not .Values.pgpool.customUsersSecret) .Values.pgpool.customUsers.usernames }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ printf "%s-custom-users" (include "postgresql-ha.pgpool" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.pgpool.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: pgpool + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + usernames: {{ .Values.pgpool.customUsers.usernames | b64enc | quote }} + passwords: {{ .Values.pgpool.customUsers.passwords | b64enc | quote }} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/pgpool/deployment.yaml b/backing-services/gitea/charts/postgresql-ha/templates/pgpool/deployment.yaml new file mode 100644 index 0000000..830e34d --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/pgpool/deployment.yaml @@ -0,0 +1,463 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} +kind: Deployment +metadata: + name: {{ include "postgresql-ha.pgpool" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.pgpool.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.pgpool.labels .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: pgpool + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- if and (not .Values.pgpool.customUsersSecret) .Values.pgpool.customUsers.usernames }} + checksum/custom-users-secrets: {{ include (print $.Template.BasePath "/pgpool/custom-users-secrets.yaml") . | sha256sum }} + {{- end }} + {{- end }} +spec: + replicas: {{ .Values.pgpool.replicaCount }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.pgpool.podLabels .Values.commonLabels $versionLabel ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: pgpool + {{- if .Values.pgpool.updateStrategy }} + strategy: {{- toYaml .Values.pgpool.updateStrategy | nindent 4 }} + {{- end }} + {{- if .Values.pgpool.minReadySeconds }} + minReadySeconds: {{ .Values.pgpool.minReadySeconds }} + {{- end }} + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: pgpool + annotations: + {{- if and (or .Values.pgpool.configuration .Values.pgpool.poolHbaConfiguration) (not .Values.pgpool.configurationCM) }} + checksum/configuration: {{ include (print $.Template.BasePath "/pgpool/configmap.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.pgpool.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.pgpool.podAnnotations "context" $) | nindent 8 }} + {{- end }} + spec: + {{- include "postgresql-ha.image.pullSecrets" . | nindent 6 }} + automountServiceAccountToken: {{ .Values.pgpool.automountServiceAccountToken }} + {{- if .Values.pgpool.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.pgpool.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.pgpool.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.pgpool.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.pgpool.podAffinityPreset "component" "pgpool" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.pgpool.podAntiAffinityPreset "component" "pgpool" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.pgpool.nodeAffinityPreset.type "key" .Values.pgpool.nodeAffinityPreset.key "values" .Values.pgpool.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.pgpool.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.pgpool.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.pgpool.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.pgpool.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.pgpool.priorityClassName }} + priorityClassName: {{ .Values.pgpool.priorityClassName }} + {{- end }} + {{- if .Values.pgpool.schedulerName }} + schedulerName: {{ .Values.pgpool.schedulerName | quote }} + {{- end }} + {{- if .Values.pgpool.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.pgpool.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.pgpool.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.pgpool.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.pgpool.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.pgpool.terminationGracePeriodSeconds }} + {{- end }} + serviceAccountName: {{ include "postgresql-ha.serviceAccountName" . }} + {{- if or .Values.pgpool.tls.enabled .Values.pgpool.initContainers }} + initContainers: + {{- if .Values.pgpool.tls.enabled }} + - name: init-chmod-data + image: {{ template "postgresql-ha.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/sh + - -cx + - | + cp /tmp/certs/* /opt/bitnami/pgpool/certs/ + {{- if eq ( toString ( .Values.volumePermissions.podSecurityContext.runAsUser )) "auto" }} + chown -R `id -u`:`id -G | cut -d " " -f2` /opt/bitnami/pgpool/certs/ + {{- else }} + chown -R {{ .Values.pgpool.containerSecurityContext.runAsUser }}:{{ .Values.pgpool.podSecurityContext.fsGroup }} /opt/bitnami/pgpool/certs/ + {{- end }} + chmod 600 {{ template "postgresql-ha.pgpool.tlsCertKey" . }} + {{- if eq ( toString ( .Values.volumePermissions.podSecurityContext.runAsUser )) "auto" }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" (omit .Values.volumePermissions.podSecurityContext "runAsUser") "context" $) | nindent 12 }} + {{- else }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.volumePermissions.podSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- else if ne .Values.volumePermissions.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.volumePermissions.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: raw-certificates + mountPath: /tmp/certs + - name: pgpool-certificates + mountPath: /opt/bitnami/pgpool/certs + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- end }} + {{- if .Values.pgpool.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.pgpool.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- end }} + # Auxiliary vars to populate environment variables + {{- $postgresqlReplicaCount := int .Values.postgresql.replicaCount }} + {{- $postgresqlFullname := include "postgresql-ha.postgresql" . }} + {{- $postgresalContainerPort := int .Values.postgresql.containerPorts.postgresql }} + {{- $postgresqlHeadlessServiceName := printf "%s-headless" (include "postgresql-ha.postgresql" .) }} + containers: + - name: pgpool + image: {{ include "postgresql-ha.pgpool.image" . }} + imagePullPolicy: {{ .Values.pgpool.image.pullPolicy | quote }} + {{- if .Values.pgpool.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.pgpool.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.pgpool.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.pgpool.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.pgpool.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.pgpool.args "context" $) | nindent 12 }} + {{- end }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.pgpool.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.pgpool.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + {{- end }} + {{- $clusterDomain:= .Values.clusterDomain }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.pgpool.image.debug .Values.diagnosticMode.enabled) | quote }} + {{- if or .Values.pgpool.customUsersSecret .Values.pgpool.customUsers.usernames }} + - name: PGPOOL_POSTGRES_CUSTOM_USERS + valueFrom: + secretKeyRef: + name: {{ include "postgresql-ha.pgpoolCustomUsersSecretName" . }} + key: usernames + - name: PGPOOL_POSTGRES_CUSTOM_PASSWORDS + valueFrom: + secretKeyRef: + name: {{ include "postgresql-ha.pgpoolCustomUsersSecretName" . }} + key: passwords + {{- end }} + - name: REPMGR_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: PGPOOL_BACKEND_NODES + value: {{ range $e, $i := until $postgresqlReplicaCount }}{{ $i }}:{{ $postgresqlFullname }}-{{ $i }}.{{ $postgresqlHeadlessServiceName }}.$(REPMGR_NAMESPACE).svc.{{ $clusterDomain }}:{{ $postgresalContainerPort }},{{ end }} + - name: PGPOOL_SR_CHECK_USER + value: {{ (include "postgresql-ha.pgoolSrCheckUsername" .) | quote }} + {{- if .Values.pgpool.usePasswordFiles }} + - name: PGPOOL_SR_CHECK_PASSWORD_FILE + value: "/opt/bitnami/pgpool/secrets/sr-check-password" + {{- else }} + - name: PGPOOL_SR_CHECK_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql-ha.pgpoolSecretName" . }} + key: sr-check-password + {{- end }} + - name: PGPOOL_SR_CHECK_DATABASE + value: {{ .Values.pgpool.srCheckDatabase | quote }} + - name: PGPOOL_ENABLE_LDAP + value: {{ ternary "yes" "no" .Values.ldap.enabled | quote }} + {{- if .Values.ldap.enabled }} + - name: LDAP_URI + value: {{ .Values.ldap.uri | quote }} + - name: LDAP_BASE + value: {{ .Values.ldap.basedn | quote }} + - name: LDAP_BIND_DN + value: {{ .Values.ldap.binddn | quote }} + - name: LDAP_BIND_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql-ha.ldapSecretName" . }} + key: bind-password + {{- if .Values.ldap.bslookup }} + - name: LDAP_BASE_LOOKUP + value: {{ .Values.ldap.bslookup | quote }} + {{- end }} + {{- if .Values.ldap.scope }} + - name: LDAP_SCOPE + value: {{ .Values.ldap.scope | quote }} + {{- end }} + {{- if .Values.ldap.searchfilter }} + - name: LDAP_SEARCH_FILTER + value: {{ .Values.ldap.searchfilter | quote }} + {{- end }} + {{- if .Values.ldap.searchmap }} + - name: LDAP_SEARCH_MAP + value: {{ .Values.ldap.searchmap | quote }} + {{- end }} + {{- if .Values.ldap.tlsReqcert }} + - name: LDAP_TLS_REQCERT + value: {{ .Values.ldap.tlsReqcert | quote }} + {{- end }} + - name: LDAP_NSS_INITGROUPS_IGNOREUSERS + value: {{ .Values.ldap.nssInitgroupsIgnoreusers | quote }} + {{- end }} + - name: PGPOOL_POSTGRES_USERNAME + value: {{ (include "postgresql-ha.postgresqlUsername" .) | quote }} + {{- if .Values.pgpool.usePasswordFiles }} + - name: PGPOOL_POSTGRES_PASSWORD_FILE + value: "/opt/bitnami/pgpool/secrets/pgpool-password" + {{- else }} + - name: PGPOOL_POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql-ha.postgresqlSecretName" . }} + {{- if not (eq (include "postgresql-ha.postgresqlUsername" .) "postgres") }} + key: postgres-password + {{- else }} + key: password + {{- end }} + {{- end }} + - name: PGPOOL_ADMIN_USERNAME + value: {{ (include "postgresql-ha.pgpoolAdminUsername" .) | quote }} + {{- if .Values.pgpool.usePasswordFiles }} + - name: PGPOOL_ADMIN_PASSWORD_FILE + value: "/opt/bitnami/pgpool/secrets/admin-password" + {{- else }} + - name: PGPOOL_ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql-ha.pgpoolSecretName" . }} + key: admin-password + {{- end }} + - name: PGPOOL_AUTHENTICATION_METHOD + value: {{ .Values.pgpool.authenticationMethod | quote }} + - name: PGPOOL_ENABLE_LOAD_BALANCING + value: {{ ternary "yes" "no" .Values.pgpool.useLoadBalancing | quote }} + - name: PGPOOL_ENABLE_CONNECTION_CACHE + value: {{ ternary "yes" "no" .Values.pgpool.useConnectionCache | quote }} + {{- if .Values.pgpool.useLoadBalancing }} + - name: PGPOOL_DISABLE_LOAD_BALANCE_ON_WRITE + value: {{ .Values.pgpool.disableLoadBalancingOnWrite | quote }} + {{- end }} + - name: PGPOOL_ENABLE_LOG_CONNECTIONS + value: {{ ternary "yes" "no" .Values.pgpool.logConnections | quote }} + - name: PGPOOL_ENABLE_LOG_HOSTNAME + value: {{ ternary "yes" "no" .Values.pgpool.logHostname | quote }} + - name: PGPOOL_ENABLE_LOG_PCP_PROCESSES + value: {{ ternary "yes" "no" .Values.pgpool.logPcpProcesses | quote }} + - name: PGPOOL_ENABLE_LOG_PER_NODE_STATEMENT + value: {{ ternary "yes" "no" .Values.pgpool.logPerNodeStatement | quote }} + {{- if .Values.pgpool.logLinePrefix }} + - name: PGPOOL_LOG_LINE_PREFIX + value: {{ .Values.pgpool.logLinePrefix | quote }} + {{- end }} + {{- if .Values.pgpool.numInitChildren }} + - name: PGPOOL_NUM_INIT_CHILDREN + value: {{ .Values.pgpool.numInitChildren | quote }} + {{- end }} + {{- if .Values.pgpool.reservedConnections }} + - name: PGPOOL_RESERVED_CONNECTIONS + value: '{{ .Values.pgpool.reservedConnections }}' + {{- end }} + {{- if .Values.pgpool.maxPool }} + - name: PGPOOL_MAX_POOL + value: {{ .Values.pgpool.maxPool | quote }} + {{- end }} + {{- if .Values.pgpool.childMaxConnections }} + - name: PGPOOL_CHILD_MAX_CONNECTIONS + value: {{ .Values.pgpool.childMaxConnections | quote }} + {{- end }} + {{- $childlifetime := .Values.pgpool.childLifeTime | quote }} + {{- if or $childlifetime (eq "0" $childlifetime) }} + - name: PGPOOL_CHILD_LIFE_TIME + value: {{ $childlifetime }} + {{- end }} + {{- if .Values.pgpool.clientIdleLimit }} + - name: PGPOOL_CLIENT_IDLE_LIMIT + value: {{ .Values.pgpool.clientIdleLimit | quote }} + {{- end }} + {{- if .Values.pgpool.connectionLifeTime }} + - name: PGPOOL_CONNECTION_LIFE_TIME + value: {{ .Values.pgpool.connectionLifeTime | quote }} + {{- end }} + {{- if or .Values.pgpool.configuration .Values.pgpool.configurationCM }} + - name: PGPOOL_USER_CONF_FILE + value: "/opt/bitnami/pgpool/user_config/pgpool.conf" + {{- end }} + {{- if or .Values.pgpool.poolHbaConfiguration .Values.pgpool.configurationCM }} + - name: PGPOOL_USER_HBA_FILE + value: "/opt/bitnami/pgpool/user_config/pool_hba.conf" + {{- end }} + - name: PGPOOL_ENABLE_TLS + value: {{ ternary "yes" "no" .Values.pgpool.tls.enabled | quote }} + {{- if .Values.pgpool.tls.enabled }} + - name: PGPOOL_TLS_PREFER_SERVER_CIPHERS + value: {{ ternary "yes" "no" .Values.pgpool.tls.preferServerCiphers | quote }} + - name: PGPOOL_TLS_CERT_FILE + value: {{ template "postgresql-ha.pgpool.tlsCert" . }} + - name: PGPOOL_TLS_KEY_FILE + value: {{ template "postgresql-ha.pgpool.tlsCertKey" . }} + {{- if .Values.pgpool.tls.certCAFilename }} + - name: PGPOOL_TLS_CA_FILE + value: {{ template "postgresql-ha.pgpool.tlsCACert" . }} + {{- end }} + {{- end }} + - name: PGPOOL_HEALTH_CHECK_PSQL_TIMEOUT + {{- if .Values.pgpool.customLivenessProbe }} + value: {{ add 1 (default 1 .Values.pgpool.customLivenessProbe.timeoutSeconds) | quote }} + {{- else }} + value: {{ add 1 (default 1 .Values.pgpool.livenessProbe.timeoutSeconds) | quote }} + {{- end }} + {{- if .Values.pgpool.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.pgpool.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.pgpool.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.pgpool.extraEnvVarsCM }} + {{- end }} + {{- if .Values.pgpool.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.pgpool.extraEnvVarsSecret }} + {{- end }} + ports: + - name: postgresql + containerPort: {{ .Values.pgpool.containerPorts.postgresql }} + protocol: TCP + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.pgpool.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.pgpool.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.pgpool.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.pgpool.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /opt/bitnami/scripts/pgpool/healthcheck.sh + {{- end }} + {{- if .Values.pgpool.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.pgpool.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.pgpool.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.pgpool.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - bash + - -ec + - '{{ include "postgresql-ha.pgpoolPostgresPassword" . }} psql -U {{ (include "postgresql-ha.postgresqlUsername" .) | quote }} {{- if not (empty (include "postgresql-ha.postgresqlDatabase" .)) }} -d {{ (include "postgresql-ha.postgresqlDatabase" .) | quote }}{{- end }} -h /opt/bitnami/pgpool/tmp -tA -c "SELECT 1" >/dev/null' + {{- end }} + {{- if .Values.pgpool.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.pgpool.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.pgpool.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.pgpool.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /opt/bitnami/scripts/pgpool/healthcheck.sh + {{- end }} + {{- end }} + {{- if .Values.pgpool.resources }} + resources: {{- toYaml .Values.pgpool.resources | nindent 12 }} + {{- else if ne .Values.pgpool.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.pgpool.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/pgpool/etc + subPath: app-etc-dir + - name: empty-dir + mountPath: /opt/bitnami/pgpool/conf + subPath: app-conf-dir + - name: empty-dir + mountPath: /opt/bitnami/pgpool/tmp + subPath: app-tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/pgpool/logs + subPath: app-logs-dir + {{- if or .Values.pgpool.configuration .Values.pgpool.poolHbaConfiguration .Values.pgpool.configurationCM }} + - name: pgpool-config + mountPath: /opt/bitnami/pgpool/user_config + {{- end }} + {{- if or .Values.pgpool.initdbScripts .Values.pgpool.initdbScriptsCM }} + - name: custom-init-scripts + mountPath: /docker-entrypoint-initdb.d/ + {{- end }} + {{- if .Values.pgpool.initdbScriptsSecret }} + - name: custom-init-scripts-secret + mountPath: /docker-entrypoint-initdb.d/secret + {{- end }} + {{- if .Values.pgpool.usePasswordFiles }} + - name: postgresql-creds + subPath: pgpool-password + mountPath: /opt/bitnami/pgpool/secrets/pgpool-password + - name: pgpool-creds + subPath: admin-password + mountPath: /opt/bitnami/pgpool/secrets/admin-password + - name: pgpool-creds + subPath: sr-check-password + mountPath: /opt/bitnami/pgpool/secrets/sr-check-password + {{- end }} + {{- if .Values.pgpool.tls.enabled }} + - name: pgpool-certificates + mountPath: /opt/bitnami/pgpool/certs + {{- end }} + {{- if .Values.pgpool.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.pgpool.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.pgpool.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.pgpool.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: empty-dir + emptyDir: {} + {{- if or .Values.pgpool.configuration .Values.pgpool.poolHbaConfiguration .Values.pgpool.configurationCM }} + - name: pgpool-config + configMap: + name: {{ include "postgresql-ha.pgpoolConfigurationCM" . }} + {{- end }} + {{- if or .Values.pgpool.initdbScripts .Values.pgpool.initdbScriptsCM }} + - name: custom-init-scripts + configMap: + name: {{ template "postgresql-ha.pgpoolInitdbScriptsCM" . }} + {{- end }} + {{- if .Values.pgpool.initdbScriptsSecret }} + - name: custom-init-scripts-secret + secret: + secretName: {{ template "postgresql-ha.pgpoolInitdbScriptsSecret" . }} + {{- end }} + {{- if .Values.pgpool.usePasswordFiles }} + - name: postgresql-creds + secret: + secretName: {{ include "postgresql-ha.postgresqlSecretName" . }} + items: + - key: password + path: pgpool-password + - name: pgpool-creds + secret: + secretName: {{ include "postgresql-ha.pgpoolSecretName" . }} + {{- end }} + {{- if .Values.pgpool.tls.enabled }} + - name: raw-certificates + secret: + secretName: {{ include "postgresql-ha.tlsSecretName" . }} + - name: pgpool-certificates + emptyDir: {} + {{- end }} + {{- if .Values.pgpool.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.pgpool.extraVolumes "context" $) | nindent 8 }} + {{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/pgpool/initdb-scripts-configmap.yaml b/backing-services/gitea/charts/postgresql-ha/templates/pgpool/initdb-scripts-configmap.yaml new file mode 100644 index 0000000..0c85dac --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/pgpool/initdb-scripts-configmap.yaml @@ -0,0 +1,21 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.pgpool.initdbScripts (not .Values.pgpool.initdbScriptsCM) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-initdb-scripts" (include "postgresql-ha.pgpool" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.pgpool.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: pgpool + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + {{- include "common.tplvalues.render" (dict "value" .Values.pgpool.initdbScripts "context" $) | nindent 4 }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/pgpool/networkpolicy.yaml b/backing-services/gitea/charts/postgresql-ha/templates/pgpool/networkpolicy.yaml new file mode 100644 index 0000000..85e959e --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/pgpool/networkpolicy.yaml @@ -0,0 +1,88 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.pgpool.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ include "common.capabilities.networkPolicy.apiVersion" . }} +metadata: + name: {{ include "postgresql-ha.pgpool" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: pgpool + role: data + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.pgpool.podLabels .Values.commonLabels ) "context" . ) }} + podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: pgpool + policyTypes: + - Ingress + - Egress + {{- if .Values.pgpool.networkPolicy.allowExternalEgress }} + egress: + - {} + {{- else }} + egress: + # Allow dns resolution + - ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + # Allow outbound connections to other cluster pods + - ports: + - port: {{ .Values.service.ports.postgresql }} + - port: {{ .Values.pgpool.containerPorts.postgresql }} + to: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }} + app.kubernetes.io/component: pgpool + # Allow outbound connections to other postgresql pods + - ports: + - port: {{ .Values.service.ports.postgresql }} + - port: {{ .Values.postgresql.containerPorts.postgresql }} + to: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }} + app.kubernetes.io/component: postgresql + {{- if .Values.pgpool.networkPolicy.extraEgress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.pgpool.networkPolicy.extraEgress "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} + ingress: + - ports: + - port: {{ .Values.pgpool.containerPorts.postgresql }} + {{- if .Values.metrics.enabled }} + - port: {{ .Values.metrics.containerPorts.http }} + {{- end }} + {{- if not .Values.pgpool.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 14 }} + - podSelector: + matchLabels: + {{ template "postgresql-ha.pgpool" . }}-client: "true" + {{- if .Values.pgpool.networkPolicy.ingressNSMatchLabels }} + - namespaceSelector: + matchLabels: + {{- range $key, $value := .Values.pgpool.networkPolicy.ingressNSMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{- if .Values.pgpool.networkPolicy.ingressNSPodMatchLabels }} + podSelector: + matchLabels: + {{- range $key, $value := .Values.pgpool.networkPolicy.ingressNSPodMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.pgpool.networkPolicy.extraIngress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.pgpool.networkPolicy.extraIngress "context" $ ) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/pgpool/pdb.yaml b/backing-services/gitea/charts/postgresql-ha/templates/pgpool/pdb.yaml new file mode 100644 index 0000000..39e6096 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/pgpool/pdb.yaml @@ -0,0 +1,30 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.pgpool.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "postgresql-ha.pgpool" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.pgpool.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: pgpool + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.pgpool.pdb.minAvailable }} + minAvailable: {{ .Values.pgpool.pdb.minAvailable }} + {{- end }} + {{- if or .Values.pgpool.pdb.maxUnavailable (not .Values.pgpool.pdb.minAvailable) }} + maxUnavailable: {{ .Values.pgpool.pdb.maxUnavailable | default 1 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.pgpool.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: pgpool +{{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/pgpool/secrets.yaml b/backing-services/gitea/charts/postgresql-ha/templates/pgpool/secrets.yaml new file mode 100644 index 0000000..5b8fd8f --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/pgpool/secrets.yaml @@ -0,0 +1,23 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "postgresql-ha.pgpoolCreateSecret" .) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "postgresql-ha.pgpool" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.pgpool.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" . ) | nindent 4 }} + app.kubernetes.io/component: pgpool + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" . ) | nindent 4 }} + {{- end }} +type: Opaque +data: + admin-password: {{ include "common.secrets.passwords.manage" (dict "secret" (include "postgresql-ha.pgpool" .) "key" "admin-password" "providedValues" (list "global.pgpool.adminPassword" "pgpool.adminPassword") "length" 10 "context" .) }} + sr-check-password: {{ include "common.secrets.passwords.manage" (dict "secret" (include "postgresql-ha.pgpool" .) "key" "sr-check-password" "providedValues" (list "global.pgpool.srCheckPassword" "pgpool.srCheckPassword") "length" 10 "failOnNew" false "context" .) }} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/pgpool/service.yaml b/backing-services/gitea/charts/postgresql-ha/templates/pgpool/service.yaml new file mode 100644 index 0000000..c3f1460 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/pgpool/service.yaml @@ -0,0 +1,54 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ include "postgresql-ha.pgpool" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.pgpool.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.pgpool.serviceLabels .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: pgpool + {{- if or .Values.pgpool.serviceAnnotations .Values.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.pgpool.serviceAnnotations .Values.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + {{- if .Values.service.sessionAffinity }} + sessionAffinity: {{ .Values.service.sessionAffinity }} + {{- end }} + {{- if .Values.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + {{- if or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{- toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + {{- if and (not (empty .Values.service.loadBalancerIP)) (eq .Values.service.type "LoadBalancer") }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.service.type "ClusterIP") .Values.service.clusterIP }} + clusterIP: {{ .Values.service.clusterIP }} + {{- end }} + ports: + - name: {{ .Values.service.portName | quote }} + port: {{ .Values.service.ports.postgresql }} + targetPort: postgresql + protocol: TCP + {{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.postgresql)) }} + nodePort: {{ .Values.service.nodePorts.postgresql }} + {{- else if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.pgpool.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: pgpool diff --git a/backing-services/gitea/charts/postgresql-ha/templates/podsecuritypolicy.yaml b/backing-services/gitea/charts/postgresql-ha/templates/podsecuritypolicy.yaml new file mode 100644 index 0000000..bba0041 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/podsecuritypolicy.yaml @@ -0,0 +1,44 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (include "common.capabilities.psp.supported" .) .Values.psp.create }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + privileged: false + allowedCapabilities: + - CHOWN + volumes: + - 'configMap' + - 'secret' + - 'persistentVolumeClaim' + - 'emptyDir' + - 'projected' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + - min: 1 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 1 + max: 65535 + readOnlyRootFilesystem: false +{{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/postgresql/configmap.yaml b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/configmap.yaml new file mode 100644 index 0000000..322097d --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/configmap.yaml @@ -0,0 +1,30 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (or .Values.postgresql.repmgrConfiguration .Values.postgresql.configuration .Values.postgresql.pgHbaConfiguration) (not .Values.postgresql.configurationCM) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-configuration" (include "postgresql-ha.postgresql" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: postgresql + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + {{- if .Values.postgresql.repmgrConfiguration }} + repmgr.conf: |- + {{- include "common.tplvalues.render" ( dict "value" .Values.postgresql.repmgrConfiguration "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.postgresql.configuration }} + postgresql.conf: |- + {{- include "common.tplvalues.render" ( dict "value" .Values.postgresql.configuration "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.postgresql.pgHbaConfiguration }} + pg_hba.conf: |- + {{- include "common.tplvalues.render" ( dict "value" .Values.postgresql.pgHbaConfiguration "context" $ ) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/postgresql/extended-configmap.yaml b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/extended-configmap.yaml new file mode 100644 index 0000000..66655df --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/extended-configmap.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.postgresql.extendedConf (not .Values.postgresql.extendedConfCM) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-extended-configuration" (include "postgresql-ha.postgresql" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: postgresql + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + override.conf: |- + {{- include "common.tplvalues.render" ( dict "value" .Values.postgresql.extendedConf "context" $ ) | nindent 4 }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/postgresql/initdb-scripts-configmap.yaml b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/initdb-scripts-configmap.yaml new file mode 100644 index 0000000..e379b4e --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/initdb-scripts-configmap.yaml @@ -0,0 +1,19 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.postgresql.initdbScripts (not .Values.postgresql.initdbScriptsCM) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-initdb-scripts" (include "postgresql-ha.postgresql" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: postgresql + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + {{- include "common.tplvalues.render" (dict "value" .Values.postgresql.initdbScripts "context" $) | nindent 4 }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/postgresql/metrics-service.yaml b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/metrics-service.yaml new file mode 100644 index 0000000..42d6c27 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/metrics-service.yaml @@ -0,0 +1,47 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.service.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-metrics" (include "postgresql-ha.postgresql" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: postgresql + {{- if .Values.metrics.serviceMonitor.selector }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.serviceMonitor.selector "context" $) | nindent 4 }} + {{- end }} + {{- if or .Values.metrics.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.metrics.service.type }} + {{- if (or (eq .Values.metrics.service.type "LoadBalancer") (eq .Values.metrics.service.type "NodePort")) }} + externalTrafficPolicy: {{ .Values.metrics.service.externalTrafficPolicy | quote }} + {{- end }} + {{ if .Values.metrics.service.clusterIP }} + clusterIP: {{ .Values.metrics.service.clusterIP }} + {{ end }} + {{ if eq .Values.metrics.service.type "LoadBalancer" }} + loadBalancerSourceRanges: {{ .Values.metrics.service.loadBalancerSourceRanges }} + {{ end }} + {{- if (and (eq .Values.metrics.service.type "LoadBalancer") (not (empty .Values.metrics.service.loadBalancerIP))) }} + loadBalancerIP: {{ .Values.metrics.service.loadBalancerIP }} + {{- end }} + ports: + - name: metrics + port: {{ .Values.metrics.service.ports.metrics }} + targetPort: metrics + {{- if (and (or (eq .Values.metrics.service.type "NodePort") (eq .Values.metrics.service.type "LoadBalancer")) (not (empty .Values.metrics.service.nodePorts.metrics))) }} + nodePort: {{ .Values.metrics.service.nodePorts.metrics }} + {{- else if eq .Values.metrics.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.postgresql.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: postgresql +{{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/postgresql/networkpolicy.yaml b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/networkpolicy.yaml new file mode 100644 index 0000000..971212d --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/networkpolicy.yaml @@ -0,0 +1,80 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.postgresql.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ include "common.capabilities.networkPolicy.apiVersion" . }} +metadata: + name: {{ include "postgresql-ha.postgresql" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: postgresql + role: data + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.postgresql.podLabels .Values.commonLabels ) "context" . ) }} + podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: postgresql + policyTypes: + - Ingress + - Egress + {{- if .Values.postgresql.networkPolicy.allowExternalEgress }} + egress: + - {} + {{- else }} + egress: + # Allow dns resolution + - ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + # Allow outbound connections to other cluster pods + - ports: + - port: {{ .Values.service.ports.postgresql }} + - port: {{ .Values.postgresql.containerPorts.postgresql }} + to: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }} + app.kubernetes.io/component: postgresql + {{- if .Values.postgresql.networkPolicy.extraEgress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.postgresql.networkPolicy.extraEgress "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} + ingress: + - ports: + - port: {{ .Values.postgresql.containerPorts.postgresql }} + {{- if .Values.metrics.enabled }} + - port: {{ .Values.metrics.containerPorts.http }} + {{- end }} + {{- if not .Values.postgresql.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 14 }} + - podSelector: + matchLabels: + {{ template "postgresql-ha.postgresql" . }}-client: "true" + {{- if .Values.postgresql.networkPolicy.ingressNSMatchLabels }} + - namespaceSelector: + matchLabels: + {{- range $key, $value := .Values.postgresql.networkPolicy.ingressNSMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{- if .Values.postgresql.networkPolicy.ingressNSPodMatchLabels }} + podSelector: + matchLabels: + {{- range $key, $value := .Values.postgresql.networkPolicy.ingressNSPodMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.postgresql.networkPolicy.extraIngress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.postgresql.networkPolicy.extraIngress "context" $ ) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/postgresql/pdb.yaml b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/pdb.yaml new file mode 100644 index 0000000..cd9ce4f --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/pdb.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.postgresql.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "postgresql-ha.postgresql" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: postgresql + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.postgresql.pdb.minAvailable }} + minAvailable: {{ .Values.postgresql.pdb.minAvailable }} + {{- end }} + {{- if or .Values.postgresql.pdb.maxUnavailable (not .Values.postgresql.pdb.minAvailable) }} + maxUnavailable: {{ .Values.postgresql.pdb.maxUnavailable | default 1 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.postgresql.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: postgresql +{{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/postgresql/scripts-configmap.yaml b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/scripts-configmap.yaml new file mode 100644 index 0000000..84fccb2 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/scripts-configmap.yaml @@ -0,0 +1,159 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-scripts" (include "postgresql-ha.postgresql" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" (dict "customLabels" .Values.commonLabels "context" .) | nindent 4 }} + app.kubernetes.io/component: postgresql + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" .) | nindent 4 }} + {{- end }} +data: + pre-stop.sh: |- + #!/bin/bash + + set -o errexit + set -o pipefail + set -o nounset + + # Debug section + exec 3>&1 + exec 4>&2 + + # Process input parameters + MIN_DELAY_AFTER_PG_STOP_SECONDS=$1 + + # Load Libraries + . /opt/bitnami/scripts/libpostgresql.sh + . /opt/bitnami/scripts/librepmgr.sh + + # Load PostgreSQL & repmgr environment variables + . /opt/bitnami/scripts/postgresql-env.sh + + # Auxiliary functions + is_new_primary_ready() { + local -a current_primary_node + readarray -t current_primary_node < <(repmgr_get_primary_node) + local current_primary_host="${current_primary_node[0]}" + + if [[ -n "$current_primary_host" ]] && [[ "$current_primary_host" != "$REPMGR_NODE_NETWORK_NAME" ]]; then + info "New primary detected, leaving the cluster..." + return 0 + fi + + info "Waiting for a new primary to be available..." + return 1 + } + + export MODULE="pre-stop-hook" + if ! is_boolean_yes "$BITNAMI_DEBUG"; then + exec 1>/dev/null + exec 2>/dev/null + fi + + postgresql_enable_nss_wrapper + + # Prepare env vars for managing roles + readarray -t primary_node < <(repmgr_get_upstream_node) + primary_host="${primary_node[0]}" + + # Stop postgresql for graceful exit. + PG_STOP_INIT=$EPOCHSECONDS + postgresql_stop + + if [[ -z "$primary_host" ]] || [[ "$primary_host" = "$REPMGR_NODE_NETWORK_NAME" ]]; then + info "Primary node need to wait for a new primary node before leaving the cluster" + retry_while is_new_primary_ready 10 5 + else + info "Standby node doesn't need to wait for a new primary switchover. Leaving the cluster" + fi + + # Make sure pre-stop hook waits at least 25 seconds after stop of PG to make sure Pgpool-II detects node is down. + # default terminationGracePeriodSeconds=30 seconds + PG_STOP_DURATION=$((EPOCHSECONDS - PG_STOP_INIT)) + if (( PG_STOP_DURATION < MIN_DELAY_AFTER_PG_STOP_SECONDS )); then + WAIT_TO_PG_POOL_TIME=$((MIN_DELAY_AFTER_PG_STOP_SECONDS - PG_STOP_DURATION)) + info "Waiting additional $WAIT_TO_PG_POOL_TIME seconds for Pgpool-II to detect node is down" + sleep $WAIT_TO_PG_POOL_TIME + fi + liveness-probe.sh: |- + #!/bin/bash + + set -o errexit + set -o pipefail + set -o nounset + + # Load Libraries + . /opt/bitnami/scripts/libpostgresql.sh + . /opt/bitnami/scripts/librepmgr.sh + + # Load PostgreSQL & repmgr environment variables + . /opt/bitnami/scripts/postgresql-env.sh + + # Check if PG is ready + pg_isready_args=("-U" "postgres" "-p" "$POSTGRESQL_PORT_NUMBER" "-h" "127.0.0.1") + is_boolean_yes "$POSTGRESQL_ENABLE_TLS" && pg_isready_args+=("-d" "sslcert=$POSTGRESQL_TLS_CERT_FILE sslkey=$POSTGRESQL_TLS_KEY_FILE") + debug_execute pg_isready "${pg_isready_args[@]}" + + # Check if repmgr has split-brain issues + postgresql_enable_nss_wrapper + repmgr_check_status + readiness-probe.sh: |- + #!/bin/bash + + set -o errexit + set -o pipefail + set -o nounset + + # Load Libraries + . /opt/bitnami/scripts/libpostgresql.sh + . /opt/bitnami/scripts/librepmgr.sh + + # Load PostgreSQL & repmgr environment variables + . /opt/bitnami/scripts/postgresql-env.sh + + # We should not proceed if a standby clone is in progress + if ps waux | grep "data standby clone" | grep -qv grep; then + echo "standby clone in progress" + exit 1 + fi + + # Then, let's check if PG is responding to queries +{{- if .Values.postgresql.headlessWithNotReadyAddresses }} + MIN_DELAY_AFTER_POD_READY_FIRST_TIME={{ add .Values.pgpool.livenessProbe.periodSeconds .Values.pgpool.livenessProbe.timeoutSeconds }} + FIRST_READY_TS_FILE="/tmp/.first-ready.epoch" + DELAY_SEMAPHORE="/tmp/.delay" +{{- end }} + if [[ $(PGPASSWORD="$POSTGRESQL_PASSWORD" psql -w -U "$POSTGRESQL_USERNAME" -d $POSTGRESQL_DATABASE -h 127.0.0.1 -p "$POSTGRESQL_PORT_NUMBER" -tA -c "SELECT 1" 2> /dev/null || true) = 1 ]]; then +{{- if .Values.postgresql.headlessWithNotReadyAddresses }} + # DB up, but initial readiness delay not applied + if [[ ! -f "$DELAY_SEMAPHORE" ]] && [[ -f "$FIRST_READY_TS_FILE" ]]; then + # calculate delay from the first readiness success + FIRST_READY_TS=$(cat $FIRST_READY_TS_FILE) + CURRENT_DELAY_SECONDS=$((EPOCHSECONDS - FIRST_READY_TS)) + # Wait for the minimal delay after the first readiness state + if (( CURRENT_DELAY_SECONDS > MIN_DELAY_AFTER_POD_READY_FIRST_TIME )); then + # mark delay as applied + touch "$DELAY_APPLIED_FILE" + else + echo "minimal delay not met" + exit 1 + fi + # first ever readiness test success - store timestamp and report failure + elif [[ ! -f "$DELAY_SEMAPHORE" ]]; then + echo $EPOCHSECONDS > $FIRST_READY_TS_FILE + exit 1 + fi +{{- end }} + # Finally, check if repmgr has split-brain issues + postgresql_enable_nss_wrapper + repmgr_check_status + else + echo "connection to database failed" + exit 1 + fi diff --git a/backing-services/gitea/charts/postgresql-ha/templates/postgresql/secrets.yaml b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/secrets.yaml new file mode 100644 index 0000000..b6b3e3e --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/secrets.yaml @@ -0,0 +1,24 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "postgresql-ha.postgresqlCreateSecret" .) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "postgresql-ha.postgresql" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" . ) | nindent 4 }} + app.kubernetes.io/component: postgresql + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" . ) | nindent 4 }} + {{- end }} +type: Opaque +data: + {{- if not (eq (include "postgresql-ha.postgresqlUsername" .) "postgres") }} + postgres-password: {{ include "common.secrets.passwords.manage" (dict "secret" (include "postgresql-ha.postgresql" .) "key" "postgres-password" "providedValues" (list "global.postgresql.postgresPassword" "postgresql.postgresPassword") "length" 10 "context" .) }} + {{- end }} + password: {{ include "common.secrets.passwords.manage" (dict "secret" (include "postgresql-ha.postgresql" .) "key" "password" "providedValues" (list "global.postgresql.password" "postgresql.password") "length" 10 "context" .) }} + repmgr-password: {{ include "common.secrets.passwords.manage" (dict "secret" (include "postgresql-ha.postgresql" .) "key" "repmgr-password" "providedValues" (list "global.postgresql.repmgrPassword" "postgresql.repmgrPassword") "length" 10 "context" .) }} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/postgresql/service-headless.yaml b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/service-headless.yaml new file mode 100644 index 0000000..de4bf8f --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/service-headless.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-headless" (include "postgresql-ha.postgresql" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.commonAnnotations .Values.service.headless.annotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonAnnotations .Values.service.headless.annotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + publishNotReadyAddresses: {{ .Values.postgresql.headlessWithNotReadyAddresses }} + ports: + - name: {{ .Values.service.portName | quote }} + port: {{ .Values.postgresql.containerPorts.postgresql }} + targetPort: postgresql + protocol: TCP + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.postgresql.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: postgresql + role: data diff --git a/backing-services/gitea/charts/postgresql-ha/templates/postgresql/service-witness.yaml b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/service-witness.yaml new file mode 100644 index 0000000..cc2524c --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/service-witness.yaml @@ -0,0 +1,29 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.witness.create }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-witness" (include "postgresql-ha.postgresql" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.commonAnnotations .Values.service.headless.annotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.service.headless.serviceAnnotations .Values.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + ports: + - name: {{ .Values.service.portName | quote }} + port: {{ .Values.postgresql.containerPorts.postgresql }} + targetPort: postgresql + protocol: TCP + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.witness.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: postgresql + role: witness +{{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/postgresql/service.yaml b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/service.yaml new file mode 100644 index 0000000..d03d48a --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/service.yaml @@ -0,0 +1,31 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ include "postgresql-ha.postgresql" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.service.serviceLabels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: postgresql + {{- if or .Values.postgresql.serviceAnnotations .Values.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.postgresql.serviceAnnotations .Values.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + ports: + - name: {{ .Values.service.portName | quote }} + port: {{ .Values.service.ports.postgresql }} + targetPort: postgresql + protocol: TCP + {{- if .Values.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.postgresql.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: postgresql + role: data diff --git a/backing-services/gitea/charts/postgresql-ha/templates/postgresql/servicemonitor.yaml b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/servicemonitor.yaml new file mode 100644 index 0000000..11e9817 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/servicemonitor.yaml @@ -0,0 +1,49 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "postgresql-ha.postgresql" . }} + namespace: {{ coalesce .Values.metrics.serviceMonitor.namespace (include "common.names.namespace" .) | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.serviceMonitor.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: postgresql + {{- if or .Values.commonAnnotations .Values.metrics.serviceMonitor.annotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.serviceMonitor.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.metrics.serviceMonitor.jobLabel }} + jobLabel: {{ .Values.metrics.serviceMonitor.jobLabel }} + {{- end }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + {{- if .Values.metrics.serviceMonitor.selector }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.serviceMonitor.selector "context" $) | nindent 6 }} + {{- end }} + app.kubernetes.io/component: postgresql + endpoints: + - port: metrics + {{- if .Values.metrics.serviceMonitor.interval }} + interval: {{ .Values.metrics.serviceMonitor.interval }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.honorLabels }} + honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.metricRelabelings "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.relabelings }} + relabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.relabelings "context" $) | nindent 8 }} + {{- end }} + namespaceSelector: + matchNames: + - {{ include "common.names.namespace" . | quote }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/postgresql/statefulset.yaml b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/statefulset.yaml new file mode 100644 index 0000000..52ec8d3 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/statefulset.yaml @@ -0,0 +1,701 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ include "postgresql-ha.postgresql" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.postgresql.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: postgresql + role: data + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.postgresql.replicaCount }} + podManagementPolicy: {{ .Values.postgresql.podManagementPolicy | quote }} + serviceName: {{ printf "%s-headless" (include "postgresql-ha.postgresql" .) }} + updateStrategy: {{- toYaml .Values.postgresql.updateStrategy | nindent 4 }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.postgresql.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: postgresql + role: data + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: postgresql + role: data + annotations: + {{- if and (or .Values.postgresql.repmgrConfiguration .Values.postgresql.configuration .Values.postgresql.pgHbaConfiguration) (not .Values.postgresql.configurationCM) }} + checksum/configuration: {{ include (print $.Template.BasePath "/postgresql/configmap.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.postgresql.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.postgresql.podAnnotations "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.annotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.annotations "context" $) | nindent 8 }} + {{- end }} + spec: + {{- include "postgresql-ha.image.pullSecrets" . | nindent 6 }} + automountServiceAccountToken: {{ .Values.postgresql.automountServiceAccountToken }} + {{- if .Values.postgresql.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.postgresql.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.postgresql.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.postgresql.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.postgresql.podAffinityPreset "component" "postgresql" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.postgresql.podAntiAffinityPreset "component" "postgresql" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.postgresql.nodeAffinityPreset.type "key" .Values.postgresql.nodeAffinityPreset.key "values" .Values.postgresql.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.postgresql.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.postgresql.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.postgresql.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.postgresql.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.postgresql.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.postgresql.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.postgresql.priorityClassName }} + priorityClassName: {{ .Values.postgresql.priorityClassName | quote }} + {{- end }} + {{- if .Values.postgresql.schedulerName }} + schedulerName: {{ .Values.postgresql.schedulerName }} + {{- end }} + {{- if .Values.postgresql.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.postgresql.terminationGracePeriodSeconds }} + {{- end }} + {{- if .Values.postgresql.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.postgresql.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "postgresql-ha.serviceAccountName" . }} + hostNetwork: {{ .Values.postgresql.hostNetwork }} + hostIPC: {{ .Values.postgresql.hostIPC }} + {{- if or .Values.postgresql.tls.enabled .Values.postgresql.initContainers .Values.postgresql.extraInitContainers (and .Values.volumePermissions.enabled (or (or (not (empty .Values.postgresql.extendedConf)) (not (empty .Values.postgresql.extendedConfCM))) .Values.persistence.enabled)) }} + initContainers: + {{- if .Values.postgresql.tls.enabled }} + - name: init-chmod-tls + image: {{ template "postgresql-ha.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/sh + - -cx + - | + cp /tmp/certs/* /opt/bitnami/postgresql/certs/ + {{- if eq ( toString ( .Values.volumePermissions.podSecurityContext.runAsUser )) "auto" }} + chown -R `id -u`:`id -G | cut -d " " -f2` /opt/bitnami/postgresql/certs/ + {{- else }} + chown -R {{ .Values.postgresql.containerSecurityContext.runAsUser }}:{{ .Values.postgresql.podSecurityContext.fsGroup }} /opt/bitnami/postgresql/certs/ + {{- end }} + chmod 600 {{ template "postgresql-ha.postgresql.tlsCertKey" . }} + {{- if eq ( toString ( .Values.volumePermissions.podSecurityContext.runAsUser )) "auto" }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" (omit .Values.volumePermissions.podSecurityContext "runAsUser") "context" $) | nindent 12 }} + {{- else }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.volumePermissions.podSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- else if ne .Values.volumePermissions.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.volumePermissions.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: raw-certificates + mountPath: /tmp/certs + - name: postgresql-certificates + mountPath: /opt/bitnami/postgresql/certs + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- end }} + {{- if and .Values.volumePermissions.enabled (or (or (not (empty .Values.postgresql.extendedConf)) (not (empty .Values.postgresql.extendedConfCM))) .Values.persistence.enabled) }} + - name: init-chmod-data + image: {{ include "postgresql-ha.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - sh + - -c + - | + mkdir -p {{ .Values.persistence.mountPath }}/conf {{ .Values.persistence.mountPath }}/data {{ .Values.persistence.mountPath }}/lock + chmod 700 {{ .Values.persistence.mountPath }}/conf {{ .Values.persistence.mountPath }}/data {{ .Values.persistence.mountPath }}/lock + chown {{ .Values.postgresql.containerSecurityContext.runAsUser }}:{{ .Values.postgresql.podSecurityContext.fsGroup }} {{ .Values.persistence.mountPath }} + find {{ .Values.persistence.mountPath }} -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | \ + xargs -r chown -R {{ .Values.postgresql.containerSecurityContext.runAsUser }}:{{ .Values.postgresql.podSecurityContext.fsGroup }} + {{- if .Values.volumePermissions.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.volumePermissions.podSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- else if ne .Values.volumePermissions.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.volumePermissions.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: data + mountPath: {{ .Values.persistence.mountPath }} + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- end }} + {{- if or .Values.postgresql.initContainers .Values.postgresql.extraInitContainers }} + {{- include "common.tplvalues.render" ( dict "value" (coalesce .Values.postgresql.initContainers .Values.postgresql.extraInitContainers) "context" $ ) | nindent 8 }} + {{- end }} + {{- end }} + containers: + - name: postgresql + image: {{ include "postgresql-ha.postgresql.image" . }} + imagePullPolicy: {{ .Values.postgresql.image.pullPolicy | quote }} + {{- if .Values.postgresql.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.postgresql.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.postgresql.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.postgresql.lifecycleHooks "context" $) | nindent 12 }} + {{- else }} + lifecycle: + preStop: + exec: + command: + - /pre-stop.sh + - {{ .Values.postgresql.preStopDelayAfterPgStopSeconds | quote }} + {{- end }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.postgresql.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.postgresql.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.postgresql.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.postgresql.args "context" $) | nindent 12 }} + {{- end }} + # Auxiliary vars to populate environment variables + {{- $postgresqlReplicaCount := int .Values.postgresql.replicaCount }} + {{- $postgresqlFullname := include "postgresql-ha.postgresql" . }} + {{- $postgresqlHeadlessServiceName := printf "%s-headless" (include "postgresql-ha.postgresql" .) }} + {{- $clusterDomain:= .Values.clusterDomain }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.postgresql.image.debug .Values.diagnosticMode.enabled) | quote }} + # PostgreSQL configuration + - name: POSTGRESQL_VOLUME_DIR + value: {{ .Values.persistence.mountPath | quote }} + - name: PGDATA + value: {{ printf "%s/%s" .Values.persistence.mountPath "data" | quote }} + {{- if not (eq (include "postgresql-ha.postgresqlUsername" .) "postgres") }} + {{- if .Values.postgresql.usePasswordFiles }} + - name: POSTGRES_POSTGRES_PASSWORD_FILE + value: "/opt/bitnami/postgresql/secrets/postgres-password" + {{- else }} + - name: POSTGRES_POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "postgresql-ha.postgresqlSecretName" . }} + key: postgres-password + {{- end }} + {{- end }} + - name: POSTGRES_USER + value: {{ (include "postgresql-ha.postgresqlUsername" .) | quote }} + {{- if .Values.postgresql.usePasswordFiles }} + - name: POSTGRES_PASSWORD_FILE + value: "/opt/bitnami/postgresql/secrets/password" + {{- else }} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql-ha.postgresqlSecretName" . }} + {{- if (include "postgresql-ha.postgresqlCreateSecret" .) }} + key: password + {{- else }} + {{- if ( index ( lookup "v1" "Secret" (include "common.names.namespace" .) (include "postgresql-ha.postgresqlSecretName" .) ) ".data.postgres-password" ) }} + key: postgres-password + {{- else }} + key: password + {{- end }} + {{- end }} + {{- end }} + {{- if not (empty (include "postgresql-ha.postgresqlDatabase" .)) }} + - name: POSTGRES_DB + value: {{ (include "postgresql-ha.postgresqlDatabase" .) | quote }} + {{- end }} + - name: POSTGRESQL_LOG_HOSTNAME + value: {{ .Values.postgresql.audit.logHostname | quote }} + - name: POSTGRESQL_LOG_CONNECTIONS + value: {{ .Values.postgresql.audit.logConnections | quote }} + - name: POSTGRESQL_LOG_DISCONNECTIONS + value: {{ .Values.postgresql.audit.logDisconnections | quote }} + {{- if .Values.postgresql.audit.logLinePrefix }} + - name: POSTGRESQL_LOG_LINE_PREFIX + value: {{ .Values.postgresql.audit.logLinePrefix | quote }} + {{- end }} + {{- if .Values.postgresql.audit.logTimezone }} + - name: POSTGRESQL_LOG_TIMEZONE + value: {{ .Values.postgresql.audit.logTimezone | quote }} + {{- end }} + {{- if .Values.postgresql.audit.pgAuditLog }} + - name: POSTGRESQL_PGAUDIT_LOG + value: {{ .Values.postgresql.audit.pgAuditLog | quote }} + {{- end }} + - name: POSTGRESQL_PGAUDIT_LOG_CATALOG + value: {{ .Values.postgresql.audit.pgAuditLogCatalog | quote }} + - name: POSTGRESQL_CLIENT_MIN_MESSAGES + value: {{ .Values.postgresql.audit.clientMinMessages | quote }} + - name: POSTGRESQL_SHARED_PRELOAD_LIBRARIES + value: {{ .Values.postgresql.sharedPreloadLibraries | quote }} + {{- if .Values.postgresql.maxConnections }} + - name: POSTGRESQL_MAX_CONNECTIONS + value: {{ .Values.postgresql.maxConnections | quote }} + {{- end }} + {{- if .Values.postgresql.usePgRewind }} + - name: REPMGR_USE_PGREWIND + value: {{ .Values.postgresql.usePgRewind | quote }} + {{- end }} + {{- if .Values.postgresql.postgresConnectionLimit }} + - name: POSTGRESQL_POSTGRES_CONNECTION_LIMIT + value: {{ .Values.postgresql.postgresConnectionLimit | quote }} + {{- end }} + {{- if .Values.postgresql.dbUserConnectionLimit }} + - name: POSTGRESQL_USERNAME_CONNECTION_LIMIT + value: {{ .Values.postgresql.dbUserConnectionLimit | quote }} + {{- end }} + {{- if .Values.postgresql.tcpKeepalivesInterval }} + - name: POSTGRESQL_TCP_KEEPALIVES_INTERVAL + value: {{ .Values.postgresql.tcpKeepalivesInterval | quote }} + {{- end }} + {{- if .Values.postgresql.tcpKeepalivesIdle }} + - name: POSTGRESQL_TCP_KEEPALIVES_IDLE + value: {{ .Values.postgresql.tcpKeepalivesIdle | quote }} + {{- end }} + {{- if .Values.postgresql.tcpKeepalivesCount }} + - name: POSTGRESQL_TCP_KEEPALIVES_COUNT + value: {{ .Values.postgresql.tcpKeepalivesCount | quote }} + {{- end }} + {{- if .Values.postgresql.statementTimeout }} + - name: POSTGRESQL_STATEMENT_TIMEOUT + value: {{ .Values.postgresql.statementTimeout | quote }} + {{- end }} + {{- if .Values.postgresql.pghbaRemoveFilters }} + - name: POSTGRESQL_PGHBA_REMOVE_FILTERS + value: {{ .Values.postgresql.pghbaRemoveFilters | quote }} + {{- end }} + - name: POSTGRESQL_ENABLE_TLS + value: {{ ternary "yes" "no" .Values.postgresql.tls.enabled | quote }} + {{- if .Values.postgresql.tls.enabled }} + - name: POSTGRESQL_TLS_PREFER_SERVER_CIPHERS + value: {{ ternary "yes" "no" .Values.postgresql.tls.preferServerCiphers | quote }} + - name: POSTGRESQL_TLS_CERT_FILE + value: {{ template "postgresql-ha.postgresql.tlsCert" . }} + - name: POSTGRESQL_TLS_KEY_FILE + value: {{ template "postgresql-ha.postgresql.tlsCertKey" . }} + {{- end }} + - name: POSTGRESQL_PORT_NUMBER + value: {{ .Values.postgresql.containerPorts.postgresql | quote }} + # Repmgr configuration + - name: REPMGR_PORT_NUMBER + value: {{ .Values.postgresql.containerPorts.postgresql | quote }} + - name: REPMGR_PRIMARY_PORT + value: {{ .Values.postgresql.containerPorts.postgresql | quote }} + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: REPMGR_UPGRADE_EXTENSION + value: {{ ternary "yes" "no" .Values.postgresql.upgradeRepmgrExtension | quote }} + - name: REPMGR_PGHBA_TRUST_ALL + value: {{ ternary "yes" "no" .Values.postgresql.pgHbaTrustAll | quote }} + - name: REPMGR_MOUNTED_CONF_DIR + value: "/bitnami/repmgr/conf" + - name: REPMGR_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: REPMGR_PARTNER_NODES + value: {{ range $e, $i := until $postgresqlReplicaCount }}{{ $postgresqlFullname }}-{{ $i }}.{{ $postgresqlHeadlessServiceName }}.$(REPMGR_NAMESPACE).svc.{{ $clusterDomain }},{{ end }} + - name: REPMGR_PRIMARY_HOST + value: {{ printf "%s-0.%s.$(REPMGR_NAMESPACE).svc.%s" $postgresqlFullname $postgresqlHeadlessServiceName $clusterDomain | quote }} + - name: REPMGR_NODE_NAME + value: "$(MY_POD_NAME)" + - name: REPMGR_NODE_NETWORK_NAME + value: "$(MY_POD_NAME).{{ $postgresqlHeadlessServiceName }}.$(REPMGR_NAMESPACE).svc.{{ $clusterDomain }}" + - name: REPMGR_NODE_TYPE + value: "data" + - name: REPMGR_LOG_LEVEL + value: {{ .Values.postgresql.repmgrLogLevel | quote }} + - name: REPMGR_CONNECT_TIMEOUT + value: {{ .Values.postgresql.repmgrConnectTimeout | quote }} + - name: REPMGR_RECONNECT_ATTEMPTS + value: {{ .Values.postgresql.repmgrReconnectAttempts | quote }} + - name: REPMGR_RECONNECT_INTERVAL + value: {{ .Values.postgresql.repmgrReconnectInterval | quote }} + - name: REPMGR_USERNAME + value: {{ (include "postgresql-ha.postgresqlRepmgrUsername" .) | quote }} + {{- if .Values.postgresql.usePasswordFiles }} + - name: REPMGR_PASSWORD_FILE + value: "/opt/bitnami/postgresql/secrets/repmgr-password" + {{- else }} + - name: REPMGR_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql-ha.postgresqlSecretName" . }} + key: repmgr-password + {{- end }} + {{- if .Values.postgresql.repmgrUsePassfile }} + - name: REPMGR_USE_PASSFILE + value: {{ ternary "true" "false" .Values.postgresql.repmgrUsePassfile | quote }} + - name: REPMGR_PASSFILE_PATH + value: {{ default "/opt/bitnami/repmgr/conf/.pgpass" .Values.postgresql.repmgrPassfilePath }} + {{- end }} + {{- if (include "postgresql-ha.repmgrDatabase" .) }} + - name: REPMGR_DATABASE + value: {{ (include "postgresql-ha.repmgrDatabase" .) | quote }} + {{- end }} + - name: REPMGR_FENCE_OLD_PRIMARY + value: {{ ternary "yes" "no" .Values.postgresql.repmgrFenceOldPrimary | quote }} + {{- if .Values.postgresql.repmgrChildNodesCheckInterval }} + - name: REPMGR_CHILD_NODES_CHECK_INTERVAL + value: {{ .Values.postgresql.repmgrChildNodesCheckInterval | quote }} + {{- end }} + {{- if .Values.postgresql.repmgrChildNodesConnectedMinCount }} + - name: REPMGR_CHILD_NODES_CONNECTED_MIN_COUNT + value: {{ .Values.postgresql.repmgrChildNodesConnectedMinCount | quote }} + {{- end }} + {{- if .Values.postgresql.repmgrChildNodesDisconnectTimeout }} + - name: REPMGR_CHILD_NODES_DISCONNECT_TIMEOUT + value: {{ .Values.postgresql.repmgrChildNodesDisconnectTimeout | quote }} + {{- end }} + {{- if .Values.postgresql.syncReplication }} + - name: POSTGRESQL_NUM_SYNCHRONOUS_REPLICAS + value: {{ sub (int .Values.postgresql.replicaCount) 1 | quote }} + {{- end }} + {{- if .Values.postgresql.syncReplicationMode }} + - name: POSTGRESQL_SYNCHRONOUS_REPLICAS_MODE + value: {{ .Values.postgresql.syncReplicationMode | quote }} + {{- end }} + - name: POSTGRESQL_SR_CHECK + value: "yes" + - name: POSTGRESQL_SR_CHECK_USERNAME + value: {{ (include "postgresql-ha.pgoolSrCheckUsername" .) | quote }} + - name: POSTGRESQL_SR_CHECK_DATABASE + value: {{ .Values.pgpool.srCheckDatabase | quote }} + {{- if .Values.postgresql.usePasswordFiles }} + - name: POSTGRESQL_SR_CHECK_PASSWORD_FILE + value: "/opt/bitnami/postgresql/secrets/sr-check-password" + {{- else }} + - name: POSTGRESQL_SR_CHECK_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql-ha.pgpoolSecretName" . }} + key: sr-check-password + {{- end }} + {{- if .Values.postgresql.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.postgresql.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.postgresql.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.postgresql.extraEnvVarsCM }} + {{- end }} + {{- if .Values.postgresql.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.postgresql.extraEnvVarsSecret }} + {{- end }} + ports: + - name: postgresql + containerPort: {{ .Values.postgresql.containerPorts.postgresql }} + protocol: TCP + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.postgresql.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.postgresql.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.postgresql.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.postgresql.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /liveness-probe.sh + {{- end }} + {{- if .Values.postgresql.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.postgresql.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.postgresql.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.postgresql.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /readiness-probe.sh + {{- end }} + {{- if .Values.postgresql.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.postgresql.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.postgresql.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.postgresql.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - bash + - -ec + - '{{ include "postgresql-ha.pgpassword" . }} psql -w -U {{ include "postgresql-ha.postgresqlUsername" . | quote }} -d {{ (include "postgresql-ha.postgresqlDatabase" .) | quote }} -h 127.0.0.1 -p {{ .Values.postgresql.containerPorts.postgresql }} -c "SELECT 1"' + {{- end }} + {{- end }} + {{- if .Values.postgresql.resources }} + resources: {{- toYaml .Values.postgresql.resources | nindent 12 }} + {{- else if ne .Values.postgresql.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.postgresql.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/postgresql/conf + subPath: app-conf-dir + - name: empty-dir + mountPath: /opt/bitnami/postgresql/tmp + subPath: app-tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/repmgr/conf + subPath: repmgr-conf-dir + - name: empty-dir + mountPath: /opt/bitnami/repmgr/tmp + subPath: repmgr-tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/repmgr/logs + subPath: repmgr-logs-dir + {{- if or .Values.postgresql.repmgrConfiguration .Values.postgresql.configuration .Values.postgresql.pgHbaConfiguration .Values.postgresql.configurationCM }} + - name: postgresql-config + mountPath: /bitnami/repmgr/conf + {{- end }} + {{- if or .Values.postgresql.extendedConf .Values.postgresql.extendedConfCM }} + - name: postgresql-extended-config + mountPath: /bitnami/postgresql/conf/conf.d/ + {{- end }} + {{- if or .Values.postgresql.initdbScriptsCM .Values.postgresql.initdbScripts }} + - name: custom-init-scripts + mountPath: /docker-entrypoint-initdb.d/ + {{- end }} + {{- if .Values.postgresql.initdbScriptsSecret }} + - name: custom-init-scripts-secret + mountPath: /docker-entrypoint-initdb.d/secret + {{- end }} + {{- if .Values.postgresql.usePasswordFiles }} + {{- if not (eq (include "postgresql-ha.postgresqlUsername" .) "postgres") }} + - name: postgresql-creds + mountPath: /opt/bitnami/postgresql/secrets/postgres-password + subPath: postgres-password + {{- end }} + - name: postgresql-creds + subPath: password + mountPath: /opt/bitnami/postgresql/secrets/password + - name: postgresql-creds + subPath: repmgr-password + mountPath: /opt/bitnami/postgresql/secrets/repmgr-password + - name: pgpool-creds + subPath: sr-check-password + mountPath: /opt/bitnami/postgresql/secrets/sr-check-password + {{- end }} + {{- if .Values.postgresql.tls.enabled }} + - name: postgresql-certificates + mountPath: /opt/bitnami/postgresql/certs + {{- end }} + - name: data + mountPath: {{ .Values.persistence.mountPath }} + - name: scripts + mountPath: /pre-stop.sh + subPath: pre-stop.sh + - name: scripts + mountPath: /liveness-probe.sh + subPath: liveness-probe.sh + - name: scripts + mountPath: /readiness-probe.sh + subPath: readiness-probe.sh + {{- if .Values.postgresql.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.postgresql.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ include "postgresql-ha.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.metrics.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.metrics.podSecurityContext "context" $) | nindent 12 }} + {{- end }} + env: + - name: PG_EXPORTER_WEB_LISTEN_ADDRESS + value: :{{ .Values.metrics.containerPorts.http }} + - name: DATA_SOURCE_URI + value: {{ printf "127.0.0.1:%d/%s?sslmode=disable" (.Values.postgresql.containerPorts.postgresql | int64) (include "postgresql-ha.postgresqlDatabase" .) | quote }} + {{- if .Values.postgresql.usePasswordFiles }} + - name: DATA_SOURCE_PASS_FILE + value: "/opt/bitnami/postgresql/secrets/password" + {{- else }} + - name: DATA_SOURCE_PASS + valueFrom: + secretKeyRef: + name: {{ include "postgresql-ha.postgresqlSecretName" . }} + key: password + {{- end }} + - name: DATA_SOURCE_USER + value: {{ (include "postgresql-ha.postgresqlUsername" .) | quote }} + {{- if .Values.metrics.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.metrics.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.metrics.extraEnvVarsCM }} + {{- end }} + {{- if .Values.metrics.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.metrics.extraEnvVarsSecret }} + {{- end }} + ports: + - name: metrics + containerPort: {{ .Values.metrics.containerPorts.http }} + protocol: TCP + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- else if ne .Values.metrics.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.metrics.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if or .Values.postgresql.usePasswordFiles .Values.metrics.customMetrics }} + {{- if .Values.postgresql.usePasswordFiles }} + - name: postgresql-creds + mountPath: /opt/bitnami/postgresql/secrets/ + {{- end }} + {{- if .Values.metrics.customMetrics }} + - name: custom-metrics + mountPath: /conf + readOnly: true + {{- end }} + {{- end }} + {{- if .Values.metrics.customMetrics }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else }} + args: ["--extend.query-path", "/conf/custom-metrics.yaml"] + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.postgresql.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.postgresql.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + {{- if .Values.postgresql.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.postgresql.extraVolumes "context" $) | nindent 8 }} + {{- end }} + - name: empty-dir + emptyDir: {} + {{- if and .Values.metrics.enabled .Values.metrics.customMetrics }} + - name: custom-metrics + configMap: + name: {{ include "postgresql.metricsCM" . }} + {{- end }} + - name: scripts + configMap: + name: {{ printf "%s-scripts" (include "postgresql-ha.postgresql" .) }} + defaultMode: 0755 + {{- if or .Values.postgresql.repmgrConfiguration .Values.postgresql.configuration .Values.postgresql.pgHbaConfiguration .Values.postgresql.configurationCM }} + - name: postgresql-config + configMap: + name: {{ include "postgresql-ha.postgresqlConfigurationCM" . }} + {{- end }} + {{- if or .Values.postgresql.extendedConf .Values.postgresql.extendedConfCM }} + - name: postgresql-extended-config + configMap: + name: {{ template "postgresql-ha.postgresqlExtendedConfCM" . }} + {{- end }} + {{- if .Values.postgresql.initdbScriptsSecret }} + - name: custom-init-scripts-secret + secret: + secretName: {{ template "postgresql-ha.postgresqlInitdbScriptsSecret" . }} + {{- end }} + {{- if .Values.postgresql.usePasswordFiles }} + - name: postgresql-creds + secret: + secretName: {{ include "postgresql-ha.postgresqlSecretName" . }} + - name: pgpool-creds + secret: + secretName: {{ include "postgresql-ha.pgpoolSecretName" . }} + {{- end }} + {{- if or .Values.postgresql.initdbScriptsCM .Values.postgresql.initdbScripts }} + - name: custom-init-scripts + configMap: + name: {{ template "postgresql-ha.postgresqlInitdbScriptsCM" . }} + {{- end }} + {{- if .Values.postgresql.tls.enabled }} + - name: raw-certificates + secret: + secretName: {{ required "A secret containing TLS certificates is required when TLS is enabled" (tpl .Values.postgresql.tls.certificatesSecret .) }} + - name: postgresql-certificates + emptyDir: {} + {{- 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) }} + {{- if .Values.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: data + {{- if .Values.persistence.annotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.annotations "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.persistence.labels }} + labels: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.labels "context" $) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- if .Values.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.selector "context" $) | nindent 10 }} + {{- end -}} + {{- include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) | nindent 8 }} + {{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/postgresql/witness-pdb.yaml b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/witness-pdb.yaml new file mode 100644 index 0000000..e74873a --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/witness-pdb.yaml @@ -0,0 +1,30 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.witness.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ printf "%s-witness" (include "postgresql-ha.postgresql" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: postgresql + role: witness + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.witness.pdb.minAvailable }} + minAvailable: {{ .Values.witness.pdb.minAvailable }} + {{- end }} + {{- if or .Values.witness.pdb.maxUnavailable (not .Values.witness.pdb.minAvailable) }} + maxUnavailable: {{ .Values.witness.pdb.maxUnavailable | default 1 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.postgresql.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: postgresql + role: witness +{{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/postgresql/witness-statefulset.yaml b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/witness-statefulset.yaml new file mode 100644 index 0000000..b1dc3c9 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/postgresql/witness-statefulset.yaml @@ -0,0 +1,631 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.witness.create }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ printf "%s-witness" (include "postgresql-ha.postgresql" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.witness.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: postgresql + role: witness + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.witness.replicaCount }} + podManagementPolicy: Parallel + serviceName: {{ printf "%s-witness" (include "postgresql-ha.postgresql" .) }} + updateStrategy: {{- toYaml .Values.witness.updateStrategy | nindent 4 }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.witness.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: postgresql + role: witness + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: postgresql + role: witness + {{- if or .Values.witness.podAnnotations (and .Values.metrics.enabled .Values.metrics.annotations) }} + annotations: + {{- if .Values.witness.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.witness.podAnnotations "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.annotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.annotations "context" $) | nindent 8 }} + {{- end }} + {{- end }} + spec: + {{- include "postgresql-ha.image.pullSecrets" . | nindent 6 }} + automountServiceAccountToken: {{ .Values.witness.automountServiceAccountToken }} + {{- if .Values.witness.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.witness.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.witness.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.witness.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.witness.podAffinityPreset "component" "postgresql" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.witness.podAntiAffinityPreset "component" "postgresql" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.witness.nodeAffinityPreset.type "key" .Values.witness.nodeAffinityPreset.key "values" .Values.witness.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.witness.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.witness.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.witness.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.witness.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.witness.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.witness.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.witness.priorityClassName }} + priorityClassName: {{ .Values.witness.priorityClassName | quote }} + {{- end }} + {{- if .Values.witness.schedulerName }} + schedulerName: {{ .Values.witness.schedulerName }} + {{- end }} + {{- if .Values.witness.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.witness.terminationGracePeriodSeconds }} + {{- end }} + {{- if .Values.witness.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.witness.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "postgresql-ha.serviceAccountName" . }} + hostNetwork: {{ .Values.witness.hostNetwork }} + hostIPC: {{ .Values.witness.hostIPC }} + initContainers: + {{- if .Values.postgresql.tls.enabled }} + - name: init-chmod-tls + image: {{ template "postgresql-ha.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/sh + - -cx + - | + cp /tmp/certs/* /opt/bitnami/postgresql/certs/ + {{- if eq ( toString ( .Values.volumePermissions.podSecurityContext.runAsUser )) "auto" }} + chown -R `id -u`:`id -G | cut -d " " -f2` /opt/bitnami/postgresql/certs/ + {{- else }} + chown -R {{ .Values.witness.containerSecurityContext.runAsUser }}:{{ .Values.witness.podSecurityContext.fsGroup }} /opt/bitnami/postgresql/certs/ + {{- end }} + chmod 600 {{ template "postgresql-ha.postgresql.tlsCertKey" . }} + {{- if eq ( toString ( .Values.volumePermissions.podSecurityContext.runAsUser )) "auto" }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" (omit .Values.volumePermissions.podSecurityContext "runAsUser") "context" $) | nindent 12 }} + {{- else }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.volumePermissions.podSecurityContext "context" $) | nindent 12 }} + {{- end }} + volumeMounts: + - name: raw-certificates + mountPath: /tmp/certs + - name: postgresql-certificates + mountPath: /opt/bitnami/postgresql/certs + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- end }} + {{- if and .Values.volumePermissions.enabled (or (or (not (empty .Values.witness.extendedConf)) (not (empty .Values.witness.extendedConfCM))) .Values.persistence.enabled) }} + - name: init-chmod-data + image: {{ include "postgresql-ha.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - sh + - -c + - | + mkdir -p {{ .Values.persistence.mountPath }}/conf {{ .Values.persistence.mountPath }}/data {{ .Values.persistence.mountPath }}/lock + chmod 700 {{ .Values.persistence.mountPath }}/conf {{ .Values.persistence.mountPath }}/data {{ .Values.persistence.mountPath }}/lock + chown {{ .Values.witness.containerSecurityContext.runAsUser }}:{{ .Values.witness.podSecurityContext.fsGroup }} {{ .Values.persistence.mountPath }} + find {{ .Values.persistence.mountPath }} -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | \ + xargs -r chown -R {{ .Values.witness.containerSecurityContext.runAsUser }}:{{ .Values.witness.podSecurityContext.fsGroup }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.volumePermissions.podSecurityContext "context" $) | nindent 12 }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- else if ne .Values.volumePermissions.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.volumePermissions.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: data + mountPath: {{ .Values.persistence.mountPath }} + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- end }} + {{- if or .Values.witness.initContainers .Values.witness.extraInitContainers }} + {{- include "common.tplvalues.render" ( dict "value" (coalesce .Values.witness.initContainers .Values.witness.extraInitContainers) "context" $ ) | nindent 8 }} + {{- end }} + containers: + - name: postgresql + image: {{ include "postgresql-ha.postgresql.image" . }} + imagePullPolicy: {{ .Values.postgresql.image.pullPolicy | quote }} + {{- if .Values.witness.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.witness.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.witness.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.witness.lifecycleHooks "context" $) | nindent 12 }} + {{- else }} + lifecycle: + preStop: + exec: + command: + - /pre-stop.sh + {{- end }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.witness.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.witness.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.witness.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.witness.args "context" $) | nindent 12 }} + {{- end }} + # Auxiliary vars to populate environment variables + {{- $postgresqlReplicaCount := int .Values.witness.replicaCount }} + {{- $postgresqlFullname := include "postgresql-ha.postgresql" . }} + {{- $postgresqlHeadlessServiceName := printf "%s-headless" (include "postgresql-ha.postgresql" .) }} + {{- $postgresqlWitnessServiceName := printf "%s-witness" (include "postgresql-ha.postgresql" .) }} + {{- $clusterDomain:= .Values.clusterDomain }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.postgresql.image.debug .Values.diagnosticMode.enabled) | quote }} + # PostgreSQL configuration + - name: POSTGRESQL_VOLUME_DIR + value: {{ .Values.persistence.mountPath | quote }} + - name: PGDATA + value: {{ printf "%s/%s" .Values.persistence.mountPath "data" | quote }} + {{- if not (eq (include "postgresql-ha.postgresqlUsername" .) "postgres") }} + {{- if .Values.postgresql.usePasswordFiles }} + - name: POSTGRES_POSTGRES_PASSWORD_FILE + value: "/opt/bitnami/postgresql/secrets/postgres-password" + {{- else }} + - name: POSTGRES_POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "postgresql-ha.postgresqlSecretName" . }} + key: postgres-password + {{- end }} + {{- end }} + - name: POSTGRES_USER + value: {{ (include "postgresql-ha.postgresqlUsername" .) | quote }} + {{- if .Values.postgresql.usePasswordFiles }} + - name: POSTGRES_PASSWORD_FILE + value: "/opt/bitnami/postgresql/secrets/password" + {{- else }} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql-ha.postgresqlSecretName" . }} + {{- if (include "postgresql-ha.postgresqlCreateSecret" .) }} + key: password + {{- else }} + {{- if ( index ( lookup "v1" "Secret" (include "common.names.namespace" .) (include "postgresql-ha.postgresqlSecretName" .) ) ".data.postgres-password" ) }} + key: postgres-password + {{- else }} + key: password + {{- end }} + {{- end }} + {{- end }} + {{- if not (empty (include "postgresql-ha.postgresqlDatabase" .)) }} + - name: POSTGRES_DB + value: {{ (include "postgresql-ha.postgresqlDatabase" .) | quote }} + {{- end }} + - name: POSTGRESQL_LOG_HOSTNAME + value: {{ .Values.witness.audit.logHostname | quote }} + - name: POSTGRESQL_LOG_CONNECTIONS + value: {{ .Values.witness.audit.logConnections | quote }} + - name: POSTGRESQL_LOG_DISCONNECTIONS + value: {{ .Values.witness.audit.logDisconnections | quote }} + {{- if .Values.witness.audit.logLinePrefix }} + - name: POSTGRESQL_LOG_LINE_PREFIX + value: {{ .Values.witness.audit.logLinePrefix | quote }} + {{- end }} + {{- if .Values.witness.audit.logTimezone }} + - name: POSTGRESQL_LOG_TIMEZONE + value: {{ .Values.witness.audit.logTimezone | quote }} + {{- end }} + {{- if .Values.witness.audit.pgAuditLog }} + - name: POSTGRESQL_PGAUDIT_LOG + value: {{ .Values.witness.audit.pgAuditLog | quote }} + {{- end }} + - name: POSTGRESQL_PGAUDIT_LOG_CATALOG + value: {{ .Values.witness.audit.pgAuditLogCatalog | quote }} + - name: POSTGRESQL_CLIENT_MIN_MESSAGES + value: {{ .Values.witness.audit.clientMinMessages | quote }} + - name: POSTGRESQL_SHARED_PRELOAD_LIBRARIES + value: {{ .Values.postgresql.sharedPreloadLibraries | quote }} + {{- if .Values.witness.maxConnections }} + - name: POSTGRESQL_MAX_CONNECTIONS + value: {{ .Values.witness.maxConnections | quote }} + {{- end }} + {{- if .Values.witness.postgresConnectionLimit }} + - name: POSTGRESQL_POSTGRES_CONNECTION_LIMIT + value: {{ .Values.witness.postgresConnectionLimit | quote }} + {{- end }} + {{- if .Values.witness.dbUserConnectionLimit }} + - name: POSTGRESQL_USERNAME_CONNECTION_LIMIT + value: {{ .Values.witness.dbUserConnectionLimit | quote }} + {{- end }} + {{- if .Values.witness.tcpKeepalivesInterval }} + - name: POSTGRESQL_TCP_KEEPALIVES_INTERVAL + value: {{ .Values.witness.tcpKeepalivesInterval | quote }} + {{- end }} + {{- if .Values.witness.tcpKeepalivesIdle }} + - name: POSTGRESQL_TCP_KEEPALIVES_IDLE + value: {{ .Values.witness.tcpKeepalivesIdle | quote }} + {{- end }} + {{- if .Values.witness.tcpKeepalivesCount }} + - name: POSTGRESQL_TCP_KEEPALIVES_COUNT + value: {{ .Values.witness.tcpKeepalivesCount | quote }} + {{- end }} + {{- if .Values.witness.statementTimeout }} + - name: POSTGRESQL_STATEMENT_TIMEOUT + value: {{ .Values.witness.statementTimeout | quote }} + {{- end }} + {{- if .Values.witness.pghbaRemoveFilters }} + - name: POSTGRESQL_PGHBA_REMOVE_FILTERS + value: {{ .Values.witness.pghbaRemoveFilters | quote }} + {{- end }} + - name: POSTGRESQL_ENABLE_TLS + value: {{ ternary "yes" "no" .Values.postgresql.tls.enabled | quote }} + {{- if .Values.postgresql.tls.enabled }} + - name: POSTGRESQL_TLS_PREFER_SERVER_CIPHERS + value: {{ ternary "yes" "no" .Values.postgresql.tls.preferServerCiphers | quote }} + - name: POSTGRESQL_TLS_CERT_FILE + value: {{ template "postgresql-ha.postgresql.tlsCert" . }} + - name: POSTGRESQL_TLS_KEY_FILE + value: {{ template "postgresql-ha.postgresql.tlsCertKey" . }} + {{- end }} + - name: POSTGRESQL_PORT_NUMBER + value: {{ .Values.witness.containerPorts.postgresql | quote }} + # Repmgr configuration + - name: REPMGR_PORT_NUMBER + value: {{ .Values.witness.containerPorts.postgresql | quote }} + - name: REPMGR_PRIMARY_PORT + value: {{ .Values.witness.containerPorts.postgresql | quote }} + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: REPMGR_UPGRADE_EXTENSION + value: {{ ternary "yes" "no" .Values.witness.upgradeRepmgrExtension | quote }} + - name: REPMGR_PGHBA_TRUST_ALL + value: {{ ternary "yes" "no" .Values.witness.pgHbaTrustAll | quote }} + - name: REPMGR_MOUNTED_CONF_DIR + value: "/bitnami/repmgr/conf" + - name: REPMGR_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: REPMGR_PARTNER_NODES + value: {{ range $e, $i := until $postgresqlReplicaCount }}{{ $postgresqlFullname }}-{{ $i }}.{{ $postgresqlHeadlessServiceName }}.$(REPMGR_NAMESPACE).svc.{{ $clusterDomain }},{{ end }} + - name: REPMGR_PRIMARY_HOST + value: {{ printf "%s-0.%s.$(REPMGR_NAMESPACE).svc.%s" $postgresqlFullname $postgresqlHeadlessServiceName $clusterDomain | quote }} + - name: REPMGR_NODE_NAME + value: "$(MY_POD_NAME)" + - name: REPMGR_NODE_NETWORK_NAME + value: "$(MY_POD_NAME).{{ $postgresqlWitnessServiceName }}.$(REPMGR_NAMESPACE).svc.{{ $clusterDomain }}" + - name: REPMGR_NODE_TYPE + value: "witness" + - name: REPMGR_NODE_ID_START_SEED + value: "2000" + - name: REPMGR_LOG_LEVEL + value: {{ .Values.witness.repmgrLogLevel | quote }} + - name: REPMGR_CONNECT_TIMEOUT + value: {{ .Values.witness.repmgrConnectTimeout | quote }} + - name: REPMGR_RECONNECT_ATTEMPTS + value: {{ .Values.witness.repmgrReconnectAttempts | quote }} + - name: REPMGR_RECONNECT_INTERVAL + value: {{ .Values.witness.repmgrReconnectInterval | quote }} + - name: REPMGR_USERNAME + value: {{ (include "postgresql-ha.postgresqlRepmgrUsername" .) | quote }} + {{- if .Values.postgresql.usePasswordFiles }} + - name: REPMGR_PASSWORD_FILE + value: "/opt/bitnami/postgresql/secrets/repmgr-password" + {{- else }} + - name: REPMGR_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql-ha.postgresqlSecretName" . }} + key: repmgr-password + {{- end }} + {{- if .Values.postgresql.repmgrUsePassfile }} + - name: REPMGR_USE_PASSFILE + value: {{ ternary "true" "false" .Values.postgresql.repmgrUsePassfile | quote }} + - name: REPMGR_PASSFILE_PATH + value: {{ default "/opt/bitnami/repmgr/conf/.pgpass" .Values.postgresql.repmgrPassfilePath }} + {{- end }} + {{- if (include "postgresql-ha.repmgrDatabase" .) }} + - name: REPMGR_DATABASE + value: {{ (include "postgresql-ha.repmgrDatabase" .) | quote }} + {{- end }} + {{- if .Values.witness.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.witness.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.witness.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.witness.extraEnvVarsCM }} + {{- end }} + {{- if .Values.witness.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.witness.extraEnvVarsSecret }} + {{- end }} + ports: + - name: postgresql + containerPort: {{ .Values.witness.containerPorts.postgresql }} + protocol: TCP + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.witness.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.witness.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.witness.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.witness.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - pg_isready + - -U + - postgres + - -h + - "127.0.0.1" + - -p + - {{ .Values.witness.containerPorts.postgresql | quote }} + {{- end }} + {{- if .Values.witness.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.witness.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.witness.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.witness.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - bash + - -ec + - '{{ include "postgresql-ha.pgpassword" . }} psql -w -U {{ include "postgresql-ha.postgresqlUsername" . | quote }} -d {{ (include "postgresql-ha.postgresqlDatabase" .) | quote }} -h 127.0.0.1 -p {{ .Values.witness.containerPorts.postgresql }} -c "SELECT 1"' + {{- end }} + {{- if .Values.witness.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.witness.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.witness.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.witness.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - bash + - -ec + - '{{ include "postgresql-ha.pgpassword" . }} psql -w -U {{ include "postgresql-ha.postgresqlUsername" . | quote }} -d {{ (include "postgresql-ha.postgresqlDatabase" .) | quote }} -h 127.0.0.1 -p {{ .Values.witness.containerPorts.postgresql }} -c "SELECT 1"' + {{- end }} + {{- end }} + {{- if .Values.witness.resources }} + resources: {{- toYaml .Values.witness.resources | nindent 12 }} + {{- else if ne .Values.witness.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.witness.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/postgresql/conf + subPath: app-conf-dir + - name: empty-dir + mountPath: /opt/bitnami/postgresql/tmp + subPath: app-tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/repmgr/conf + subPath: repmgr-conf-dir + - name: empty-dir + mountPath: /opt/bitnami/repmgr/tmp + subPath: repmgr-tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/repmgr/logs + subPath: repmgr-logs-dir + {{- if or .Values.witness.repmgrConfiguration .Values.witness.configuration .Values.witness.pgHbaConfiguration .Values.witness.configurationCM }} + - name: postgresql-config + mountPath: /bitnami/repmgr/conf + {{- end }} + {{- if or .Values.witness.extendedConf .Values.witness.extendedConfCM }} + - name: postgresql-extended-config + mountPath: /bitnami/postgresql/conf/conf.d/ + {{- end }} + {{- if or .Values.witness.initdbScriptsCM .Values.witness.initdbScripts }} + - name: custom-init-scripts + mountPath: /docker-entrypoint-initdb.d/ + {{- end }} + {{- if .Values.witness.initdbScriptsSecret }} + - name: custom-init-scripts-secret + mountPath: /docker-entrypoint-initdb.d/secret + {{- end }} + {{- if .Values.postgresql.usePasswordFiles }} + - name: password + mountPath: /opt/bitnami/postgresql/secrets/ + {{- end }} + {{- if .Values.postgresql.tls.enabled }} + - name: postgresql-certificates + mountPath: /opt/bitnami/postgresql/certs + {{- end }} + - name: data + mountPath: {{ .Values.persistence.mountPath }} + - name: scripts + mountPath: /pre-stop.sh + subPath: pre-stop.sh + {{- if .Values.witness.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.witness.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ include "postgresql-ha.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.metrics.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.metrics.podSecurityContext "context" $) | nindent 12 }} + {{- end }} + env: + - name: PG_EXPORTER_WEB_LISTEN_ADDRESS + value: :{{ .Values.metrics.containerPorts.http }} + - name: DATA_SOURCE_URI + value: {{ printf "127.0.0.1:%d/%s?sslmode=disable" (.Values.witness.containerPorts.postgresql | int64) (include "postgresql-ha.postgresqlDatabase" .) | quote }} + {{- if .Values.postgresql.usePasswordFiles }} + - name: DATA_SOURCE_PASS_FILE + value: "/opt/bitnami/postgresql/secrets/password" + {{- else }} + - name: DATA_SOURCE_PASS + valueFrom: + secretKeyRef: + name: {{ include "postgresql-ha.postgresqlSecretName" . }} + key: password + {{- end }} + - name: DATA_SOURCE_USER + value: {{ (include "postgresql-ha.postgresqlUsername" .) | quote }} + {{- if .Values.metrics.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.metrics.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.metrics.extraEnvVarsCM }} + {{- end }} + {{- if .Values.metrics.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.metrics.extraEnvVarsSecret }} + {{- end }} + ports: + - name: metrics + containerPort: {{ .Values.metrics.containerPorts.http }} + protocol: TCP + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- else if ne .Values.metrics.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.metrics.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if .Values.postgresql.usePasswordFiles }} + - name: password + mountPath: /opt/bitnami/postgresql/secrets/ + {{- end }} + {{- if .Values.metrics.customMetrics }} + - name: custom-metrics + mountPath: /conf + readOnly: true + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else }} + args: ["--extend.query-path", "/conf/custom-metrics.yaml"] + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.witness.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.witness.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + {{- if .Values.witness.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.witness.extraVolumes "context" $) | nindent 8 }} + {{- end }} + - name: empty-dir + emptyDir: {} + {{- if and .Values.metrics.enabled .Values.metrics.customMetrics }} + - name: custom-metrics + configMap: + name: {{ include "postgresql.metricsCM" . }} + {{- end }} + - name: scripts + configMap: + name: {{ printf "%s-scripts" (include "postgresql-ha.postgresql" .) }} + defaultMode: 0755 + {{- if or .Values.witness.repmgrConfiguration .Values.witness.configuration .Values.witness.pgHbaConfiguration .Values.witness.configurationCM }} + - name: postgresql-config + configMap: + name: {{ include "postgresql-ha.postgresqlConfigurationCM" . }} + {{- end }} + {{- if or .Values.witness.extendedConf .Values.witness.extendedConfCM }} + - name: postgresql-extended-config + configMap: + name: {{ template "postgresql-ha.postgresqlExtendedConfCM" . }} + {{- end }} + {{- if .Values.witness.initdbScriptsSecret }} + - name: custom-init-scripts-secret + secret: + secretName: {{ template "postgresql-ha.postgresqlInitdbScriptsSecret" . }} + {{- end }} + {{- if .Values.postgresql.usePasswordFiles }} + - name: password + secret: + secretName: {{ include "postgresql-ha.postgresqlSecretName" . }} + {{- end }} + {{- if or .Values.witness.initdbScriptsCM .Values.witness.initdbScripts }} + - name: custom-init-scripts + configMap: + name: {{ template "postgresql-ha.postgresqlInitdbScriptsCM" . }} + {{- end }} + {{- if .Values.postgresql.tls.enabled }} + - name: raw-certificates + secret: + secretName: {{ required "A secret containing TLS certificates is required when TLS is enabled" (tpl .Values.postgresql.tls.certificatesSecret .) }} + - name: postgresql-certificates + emptyDir: {} + {{- 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: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: data + {{- if .Values.persistence.annotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.annotations "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.persistence.labels }} + labels: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.labels "context" $) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- if .Values.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.selector "context" $) | nindent 10 }} + {{- end -}} + {{- include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) | nindent 8 }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/role.yaml b/backing-services/gitea/charts/postgresql-ha/templates/role.yaml new file mode 100644 index 0000000..e196af0 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/role.yaml @@ -0,0 +1,27 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.rbac.create }} +kind: Role +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: + {{- if and (include "common.capabilities.psp.supported" .) .Values.psp.create }} + - apiGroups: ["extensions"] + resources: ["podsecuritypolicies"] + verbs: ["use"] + resourceNames: + - {{ template "common.names.fullname" . }} + {{- end }} + {{- if .Values.rbac.rules }} + {{- include "common.tplvalues.render" ( dict "value" .Values.rbac.rules "context" $ ) | nindent 2 }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/rolebinding.yaml b/backing-services/gitea/charts/postgresql-ha/templates/rolebinding.yaml new file mode 100644 index 0000000..b7b40a7 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/rolebinding.yaml @@ -0,0 +1,24 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.rbac.create }} +kind: RoleBinding +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + kind: Role + name: {{ template "common.names.fullname" . }} + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + name: {{ default (include "common.names.fullname" . ) .Values.serviceAccount.name }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/serviceaccount.yaml b/backing-services/gitea/charts/postgresql-ha/templates/serviceaccount.yaml new file mode 100644 index 0000000..505f6a2 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/serviceaccount.yaml @@ -0,0 +1,18 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "postgresql-ha.serviceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql-ha/templates/tls-secrets.yaml b/backing-services/gitea/charts/postgresql-ha/templates/tls-secrets.yaml new file mode 100644 index 0000000..1227240 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/templates/tls-secrets.yaml @@ -0,0 +1,29 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "postgresql-ha.createTlsSecret" . ) }} +{{- $secretName := printf "%s-crt" (include "postgresql-ha.pgpool" .) }} +{{- $ca := genCA "postgresql-ha-internal-ca" 365 }} +{{- $fullname := include "postgresql-ha.pgpool" . }} +{{- $releaseNamespace := .Release.Namespace }} +{{- $clusterDomain := .Values.clusterDomain }} +{{- $serviceName := include "postgresql-ha.pgpool" . }} +{{- $altNames := list (printf "*.%s.%s.svc.%s" $serviceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $serviceName $releaseNamespace $clusterDomain) $fullname }} +{{- $cert := genSignedCert $fullname nil $altNames 365 $ca }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.crt" "defaultValue" $cert.Cert "context" $) }} + tls.key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.key" "defaultValue" $cert.Key "context" $) }} + ca.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql-ha/values.yaml b/backing-services/gitea/charts/postgresql-ha/values.yaml new file mode 100644 index 0000000..a144b88 --- /dev/null +++ b/backing-services/gitea/charts/postgresql-ha/values.yaml @@ -0,0 +1,2345 @@ +# Copyright Broadcom, Inc. All Rights Reserved. +# SPDX-License-Identifier: APACHE-2.0 + +## @section Global parameters +## 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, imagePullSecrets and storageClass + +## @param global.imageRegistry Global Docker image registry +## @param global.imagePullSecrets Global Docker registry secret names as an array +## @param global.defaultStorageClass Global default StorageClass for Persistent Volume(s) +## @param global.postgresql.username PostgreSQL username (overrides `postgresql.username`) +## @param global.postgresql.password PostgreSQL password (overrides `postgresql.password`) +## @param global.postgresql.database PostgreSQL database (overrides `postgresql.database`) +## @param global.postgresql.repmgrUsername PostgreSQL repmgr username (overrides `postgresql.repmgrUsername`) +## @param global.postgresql.repmgrPassword PostgreSQL repmgr password (overrides `postgresql.repmgrpassword`) +## @param global.postgresql.repmgrDatabase PostgreSQL repmgr database (overrides `postgresql.repmgrDatabase`) +## @param global.postgresql.existingSecret Name of existing secret to use for PostgreSQL passwords (overrides `postgresql.existingSecret`) +## @param global.ldap.bindpw LDAP bind password (overrides `ldap.bindpw`) +## @param global.ldap.existingSecret Name of existing secret to use for LDAP passwords (overrides `ldap.existingSecret`) +## @param global.pgpool.adminUsername Pgpool-II Admin username (overrides `pgpool.adminUsername`) +## @param global.pgpool.adminPassword Pgpool-II Admin password (overrides `pgpool.adminPassword`) +## @param global.pgpool.srCheckUsername Pgpool-II SR Check username (overrides `pgpool.srCheckUsername`) +## @param global.pgpool.srCheckPassword Pgpool-II SR Check password (overrides `pgpool.srCheckPassword`) +## @param global.pgpool.existingSecret Pgpool-II existing secret +## +global: + imageRegistry: "" + ## E.g. + ## imagePullSecrets: + ## - myRegistryKeySecretName + ## + imagePullSecrets: [] + defaultStorageClass: "" + ## Security parameters + ## + security: + ## @param global.security.allowInsecureImages Allows skipping image verification + allowInsecureImages: false + postgresql: + username: "" + password: "" + database: "" + repmgrUsername: "" + repmgrPassword: "" + repmgrDatabase: "" + existingSecret: "" + ldap: + bindpw: "" + existingSecret: "" + pgpool: + adminUsername: "" + adminPassword: "" + srCheckUsername: "" + srCheckPassword: "" + existingSecret: "" + ## Compatibility adaptations for Kubernetes platforms + ## + compatibility: + ## Compatibility adaptations for Openshift + ## + openshift: + ## @param global.compatibility.openshift.adaptSecurityContext Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) + ## + adaptSecurityContext: auto + +## @section Common parameters + +## @param kubeVersion Override Kubernetes version +## +kubeVersion: "" +## @param nameOverride String to partially override common.names.fullname template (will maintain the release name) +## +nameOverride: "" +## @param fullnameOverride String to fully override common.names.fullname template +## +fullnameOverride: "" +## @param namespaceOverride String to fully override common.names.namespace +## +namespaceOverride: "" +## @param commonLabels Common labels to add to all resources (sub-charts are not considered). Evaluated as a template +## +commonLabels: {} +## @param commonAnnotations Common annotations to add to all resources (sub-charts are not considered). Evaluated as a template +## +commonAnnotations: {} +## @param clusterDomain Kubernetes Cluster Domain +## +clusterDomain: cluster.local +## @param extraDeploy Array of extra objects to deploy with the release (evaluated as a template) +## +extraDeploy: [] +## Diagnostic mode in the deployment +## +diagnosticMode: + ## @param diagnosticMode.enabled Enable diagnostic mode (all probes will be disabled and the command will be overridden) + ## + enabled: false + ## @param diagnosticMode.command [array] Command to override all containers in the deployment + ## + command: + - sleep + ## @param diagnosticMode.args [array] Args to override all containers in the deployment + ## + args: + - infinity + +## @section PostgreSQL with Repmgr parameters + +postgresql: + ## ref: https://hub.docker.com/r/bitnami/postgresql/tags/ + ## @param postgresql.image.registry [default: REGISTRY_NAME] PostgreSQL with Repmgr image registry + ## @param postgresql.image.repository [default: REPOSITORY_NAME/postgresql-repmgr] PostgreSQL with Repmgr image repository + ## @skip postgresql.image.tag PostgreSQL with Repmgr image tag + ## @param postgresql.image.digest PostgreSQL with Repmgr image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param postgresql.image.pullPolicy PostgreSQL with Repmgr image pull policy + ## @param postgresql.image.pullSecrets Specify docker-registry secret names as an array + ## @param postgresql.image.debug Specify if debug logs should be enabled + ## + image: + registry: docker.io + repository: bitnami/postgresql-repmgr + tag: 17.6.0-debian-12-r2 + digest: "" + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-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/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Set to true if you would like to see extra information on logs + ## + debug: false + ## @param postgresql.labels Labels to add to the StatefulSet. Evaluated as template + ## + labels: {} + ## @param postgresql.podLabels Labels to add to the StatefulSet pods. Evaluated as template + ## + podLabels: {} + ## @param postgresql.serviceAnnotations Provide any additional annotations for PostgreSQL service + ## + serviceAnnotations: {} + ## @param postgresql.replicaCount Number of replicas to deploy. Use an odd number. Having 3 replicas is the minimum to get quorum when promoting a new primary. + ## + replicaCount: 3 + ## @param postgresql.updateStrategy.type Postgresql StatefulSet strategy type + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## e.g: + ## updateStrategy: + ## type: RollingUpdate + ## rollingUpdate: + ## maxSurge: 25% + ## maxUnavailable: 25% + ## + updateStrategy: + type: RollingUpdate + ## @param postgresql.containerPorts.postgresql PostgreSQL port + ## + containerPorts: + postgresql: 5432 + ## @param postgresql.automountServiceAccountToken Mount Service Account token in pod + ## + automountServiceAccountToken: false + ## @param postgresql.hostAliases Deployment pod host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param postgresql.hostNetwork Specify if host network should be enabled for PostgreSQL pod + ## + hostNetwork: false + ## @param postgresql.hostIPC Specify if host IPC should be enabled for PostgreSQL pod + ## + hostIPC: false + ## @param postgresql.podAnnotations Additional pod annotations + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param postgresql.podAffinityPreset PostgreSQL pod affinity preset. Ignored if `postgresql.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param postgresql.podAntiAffinityPreset PostgreSQL pod anti-affinity preset. Ignored if `postgresql.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## PostgreSQL node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param postgresql.nodeAffinityPreset.type PostgreSQL node affinity preset type. Ignored if `postgresql.affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param postgresql.nodeAffinityPreset.key PostgreSQL node label key to match Ignored if `postgresql.affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param postgresql.nodeAffinityPreset.values PostgreSQL node label values to match. Ignored if `postgresql.affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param postgresql.affinity Affinity for PostgreSQL pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## Note: postgresql.podAffinityPreset, postgresql.podAntiAffinityPreset, and postgresql.nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## @param postgresql.nodeSelector Node labels for PostgreSQL pods assignment + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: {} + ## @param postgresql.tolerations Tolerations for PostgreSQL pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param postgresql.topologySpreadConstraints Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#spread-constraints-for-pods + ## + topologySpreadConstraints: [] + ## @param postgresql.priorityClassName Pod priority class + ## Ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ + ## + priorityClassName: "" + ## @param postgresql.schedulerName Use an alternate scheduler, e.g. "stork". + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param postgresql.terminationGracePeriodSeconds Seconds PostgreSQL pod needs to terminate gracefully + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods + ## + terminationGracePeriodSeconds: "" + ## K8s Security Context + ## https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + ## @param postgresql.podSecurityContext.enabled Enable security context for PostgreSQL with Repmgr + ## @param postgresql.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy + ## @param postgresql.podSecurityContext.sysctls Set kernel settings using the sysctl interface + ## @param postgresql.podSecurityContext.supplementalGroups Set filesystem extra groups + ## @param postgresql.podSecurityContext.fsGroup Group ID for the PostgreSQL with Repmgr filesystem + ## + podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + sysctls: [] + supplementalGroups: [] + fsGroup: 1001 + ## Container Security Context + ## https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + ## @param postgresql.containerSecurityContext.enabled Enabled containers' Security Context + ## @param postgresql.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param postgresql.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param postgresql.containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup + ## @param postgresql.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param postgresql.containerSecurityContext.privileged Set container's Security Context privileged + ## @param postgresql.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param postgresql.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param postgresql.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param postgresql.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## e.g: + ## containerSecurityContext: + ## enabled: true + ## capabilities: + ## drop: ["NET_RAW"] + ## readOnlyRootFilesystem: true + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## @param postgresql.command Override default container command (useful when using custom images) + ## + command: [] + ## @param postgresql.args Override default container args (useful when using custom images) + ## + args: [] + ## @param postgresql.lifecycleHooks LifecycleHook to set additional configuration at startup, e.g. LDAP settings via REST API. Evaluated as a template + ## + lifecycleHooks: {} + ## @param postgresql.extraEnvVars Array containing extra environment variables + ## For example: + ## - name: PG_EXPORTER_DISABLE_DEFAULT_METRICS + ## value: "true" + ## + extraEnvVars: [] + ## @param postgresql.extraEnvVarsCM ConfigMap with extra environment variables + ## + extraEnvVarsCM: "" + ## @param postgresql.extraEnvVarsSecret Secret with extra environment variables + ## + extraEnvVarsSecret: "" + ## @param postgresql.extraVolumes Extra volumes to add to the StatefulSet + ## + extraVolumes: [] + ## @param postgresql.extraVolumeMounts Extra volume mounts to add to the container. Normally used with `extraVolumes`. + ## + extraVolumeMounts: [] + ## @param postgresql.initContainers Extra init containers to add to the StatefulSet + ## + initContainers: [] + ## @param postgresql.sidecars Extra sidecar containers to add to the StatefulSet + ## + sidecars: [] + ## PostgreSQL containers' resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## 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:'. + ## @param postgresql.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if postgresql.resources is set (postgresql.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "micro" + ## @param postgresql.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## @param postgresql.podManagementPolicy Sets the pod management policy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#pod-management-policies + ## + podManagementPolicy: Parallel + ## PostgreSQL container's liveness probe + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param postgresql.livenessProbe.enabled Enable livenessProbe + ## @param postgresql.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param postgresql.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param postgresql.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param postgresql.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param postgresql.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 15 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 6 + ## PostgreSQL container's readiness probe + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param postgresql.readinessProbe.enabled Enable readinessProbe + ## @param postgresql.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param postgresql.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param postgresql.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param postgresql.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param postgresql.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 6 + ## PostgreSQL container's startup probe + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param postgresql.startupProbe.enabled Enable startupProbe + ## @param postgresql.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param postgresql.startupProbe.periodSeconds Period seconds for startupProbe + ## @param postgresql.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param postgresql.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param postgresql.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 10 + ## @param postgresql.customLivenessProbe Override default liveness probe + ## + customLivenessProbe: {} + ## @param postgresql.customReadinessProbe Override default readiness probe + ## + customReadinessProbe: {} + ## @param postgresql.customStartupProbe Override default startup probe + ## + customStartupProbe: {} + ## Network Policies + ## Ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ + ## + networkPolicy: + ## @param postgresql.networkPolicy.enabled Specifies whether a NetworkPolicy should be created + ## + enabled: true + ## @param postgresql.networkPolicy.allowExternal Don't require server label for connections + ## The Policy model to apply. When set to false, only pods with the correct + ## server label will have network access to the ports server is listening + ## on. When true, server will accept connections from any source + ## (with the correct destination port). + ## + allowExternal: true + ## @param postgresql.networkPolicy.allowExternalEgress Allow the pod to access any range of port and all destinations. + ## + allowExternalEgress: true + ## @param postgresql.networkPolicy.extraIngress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraIngress: + ## - ports: + ## - port: 1234 + ## from: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + extraIngress: [] + ## @param postgresql.networkPolicy.extraEgress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraEgress: + ## - ports: + ## - port: 1234 + ## to: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraEgress: [] + ## @param postgresql.networkPolicy.ingressNSMatchLabels [object] Labels to match to allow traffic from other namespaces + ## @param postgresql.networkPolicy.ingressNSPodMatchLabels [object] Pod labels to match to allow traffic from other namespaces + ## + ingressNSMatchLabels: {} + ingressNSPodMatchLabels: {} + ## Pod disruption budget configuration + ## @param postgresql.pdb.create Specifies whether to create a Pod disruption budget for PostgreSQL with Repmgr + ## @param postgresql.pdb.minAvailable Minimum number / percentage of pods that should remain scheduled + ## @param postgresql.pdb.maxUnavailable Maximum number/percentage of pods that may be made unavailable. Defaults to `1` if both `postgresql.pdb.minAvailable` and `postgresql.pdb.maxUnavailable` are empty. + ## + pdb: + create: true + minAvailable: "" + maxUnavailable: "" + ## PostgreSQL authentication parameters + ## @param postgresql.username PostgreSQL username + ## @param postgresql.password PostgreSQL password + ## @param postgresql.database PostgreSQL database + ## + username: postgres + password: "" + database: "" + ## @param postgresql.existingSecret PostgreSQL password using existing secret + ## + existingSecret: "" + ## @param postgresql.postgresPassword PostgreSQL password for the `postgres` user when `username` is not `postgres` + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql#creating-a-database-user-on-first-run (see note!) + ## + postgresPassword: "" + ## @param postgresql.usePasswordFiles Set to `true` to mount PostgreSQL secret as a file instead of passing environment variable + ## + usePasswordFiles: true + ## @param postgresql.pgHbaTrustAll Configures PostgreSQL HBA to trust every user + ## + pgHbaTrustAll: false + ## @param postgresql.syncReplication Enable synchronous replication synchronous, waiting until data is synchronized in every replica before other queries can be run + ## This ensures the data availability at the expenses of speed + ## + syncReplication: false + ## @param postgresql.syncReplicationMode This specifies the method to choose synchronous standbys from the listed servers. Valid values: empty, FIRST, ANY. + ## ref: https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-SYNCHRONOUS-STANDBY-NAMES + ## + syncReplicationMode: "" + ## Repmgr configuration parameters + ## @param postgresql.repmgrUsername PostgreSQL Repmgr username + ## @param postgresql.repmgrPassword PostgreSQL Repmgr password + ## @param postgresql.repmgrDatabase PostgreSQL Repmgr database + ## @param postgresql.repmgrUsePassfile Configure Repmgr to use `passfile` instead of `password` vars*:*:*:username:password" + ## @param postgresql.repmgrPassfilePath Custom path where `passfile` will be stored + ## @param postgresql.repmgrLogLevel Repmgr log level (DEBUG, INFO, NOTICE, WARNING, ERROR, ALERT, CRIT or EMERG) + ## @param postgresql.repmgrConnectTimeout Repmgr backend connection timeout (in seconds) + ## @param postgresql.repmgrReconnectAttempts Repmgr backend reconnection attempts + ## @param postgresql.repmgrReconnectInterval Repmgr backend reconnection interval (in seconds) + ## @param postgresql.repmgrFenceOldPrimary Set if fencing of old primary in multiple primary situation is desired + ## @param postgresql.repmgrChildNodesCheckInterval Repmgr child nodes check interval (in seconds) + ## @param postgresql.repmgrChildNodesConnectedMinCount Repmgr minimum number of connected child nodes before being considered as failed primary for fencing + ## @param postgresql.repmgrChildNodesDisconnectTimeout Repmgr time before node will be fenced when insufficient child nodes are detected (in seconds) + ## @param postgresql.upgradeRepmgrExtension Upgrade Repmgr extension in the database + ## + repmgrUsername: repmgr + repmgrPassword: "" + repmgrDatabase: repmgr + repmgrUsePassfile: true + repmgrPassfilePath: "" + repmgrLogLevel: NOTICE + repmgrConnectTimeout: 5 + repmgrReconnectAttempts: 2 + repmgrReconnectInterval: 3 + repmgrFenceOldPrimary: false + repmgrChildNodesCheckInterval: 5 + repmgrChildNodesConnectedMinCount: 1 + repmgrChildNodesDisconnectTimeout: 30 + upgradeRepmgrExtension: false + ## @param postgresql.usePgRewind Use pg_rewind for standby failover (experimental) + ## + usePgRewind: false + ## Audit settings + ## https://github.com/bitnami/containers/tree/main/bitnami/postgresql#auditing + ## + audit: + ## @param postgresql.audit.logHostname Add client hostnames to the log file + ## + logHostname: true + ## @param postgresql.audit.logConnections Add client log-in operations to the log file + ## + logConnections: false + ## @param postgresql.audit.logDisconnections Add client log-outs operations to the log file + ## + logDisconnections: false + ## @param postgresql.audit.pgAuditLog Add operations to log using the pgAudit extension + ## + pgAuditLog: "" + ## @param postgresql.audit.pgAuditLogCatalog Log catalog using pgAudit + ## + pgAuditLogCatalog: "off" + ## @param postgresql.audit.clientMinMessages Message log level to share with the user + ## + clientMinMessages: error + ## @param postgresql.audit.logLinePrefix Template string for the log line prefix + ## + logLinePrefix: "" + ## @param postgresql.audit.logTimezone Timezone for the log timestamps + ## + logTimezone: "" + ## @param postgresql.sharedPreloadLibraries Shared preload libraries (comma-separated list) + ## + sharedPreloadLibraries: "pgaudit, repmgr" + ## @param postgresql.maxConnections Maximum total connections + ## + maxConnections: "" + ## @param postgresql.postgresConnectionLimit Maximum connections for the postgres user + ## + postgresConnectionLimit: "" + ## @param postgresql.dbUserConnectionLimit Maximum connections for the created user + ## + dbUserConnectionLimit: "" + ## @param postgresql.tcpKeepalivesInterval TCP keepalives interval + ## + tcpKeepalivesInterval: "" + ## @param postgresql.tcpKeepalivesIdle TCP keepalives idle + ## + tcpKeepalivesIdle: "" + ## @param postgresql.tcpKeepalivesCount TCP keepalives count + ## + tcpKeepalivesCount: "" + ## @param postgresql.statementTimeout Statement timeout + ## + statementTimeout: "" + ## @param postgresql.pghbaRemoveFilters Comma-separated list of patterns to remove from the pg_hba.conf file + ## (cannot be used with custom pg_hba.conf) + ## + pghbaRemoveFilters: "" + ## @param postgresql.extraInitContainers Extra init containers + ## Example: + ## extraInitContainers: + ## - name: do-something + ## image: busybox + ## command: ['do', 'something'] + ## + extraInitContainers: [] + ## @param postgresql.repmgrConfiguration Repmgr configuration + ## You can use this parameter to specify the content for repmgr.conf + ## Otherwise, a repmgr.conf will be generated based on the environment variables + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql-repmgr#configuration + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql-repmgr#configuration-file + ## Example: + ## repmgrConfiguration: |- + ## ssh_options='-o "StrictHostKeyChecking no" -v' + ## use_replication_slots='1' + ## ... + ## + repmgrConfiguration: "" + ## @param postgresql.configuration PostgreSQL configuration + ## You can use this parameter to specify the content for postgresql.conf + ## Otherwise, a postgresql.conf will be generated based on the environment variables + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql-repmgr#configuration + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql-repmgr#configuration-file + ## Example: + ## configuration: |- + ## listen_addresses = '*' + ## port = '5432' + ## ... + ## + configuration: "" + ## @param postgresql.pgHbaConfiguration PostgreSQL client authentication configuration + ## You can use this parameter to specify the content for pg_hba.conf + ## Otherwise, a pg_hba.conf will be generated based on the environment variables + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql-repmgr#configuration + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql-repmgr#configuration-file + ## Example: + ## pgHbaConfiguration: |- + ## host all repmgr 0.0.0.0/0 md5 + ## host repmgr repmgr 0.0.0.0/0 md + ## ... + ## + pgHbaConfiguration: "" + ## @param postgresql.configurationCM Name of existing ConfigMap with configuration files + ## NOTE: This will override postgresql.repmgrConfiguration, postgresql.configuration and postgresql.pgHbaConfiguration + ## + configurationCM: "" + ## @param postgresql.extendedConf Extended PostgreSQL configuration (requires `volumePermissions.enabled` to be `true`) + ## Similar to postgresql.configuration, but _appended_ to the main configuration + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql-repmgr#allow-settings-to-be-loaded-from-files-other-than-the-default-postgresqlconf + ## Example: + ## extendedConf: |- + ## deadlock_timeout = 1s + ## max_locks_per_transaction = 64 + ## ... + ## + extendedConf: "" + ## @param postgresql.extendedConfCM ConfigMap with PostgreSQL extended configuration (requires `volumePermissions.enabled` to be `true`) + ## NOTE: This will override postgresql.extendedConf + ## + extendedConfCM: "" + ## @param postgresql.initdbScripts Dictionary of initdb scripts + ## Specify dictionary of scripts to be run at first boot + ## The allowed extensions are `.sh`, `.sql` and `.sql.gz` + ## ref: https://github.com/bitnami/charts/tree/main/bitnami/postgresql-ha#initialize-a-fresh-instance + ## e.g: + ## initdbScripts: + ## my_init_script.sh: | + ## #!/bin/sh + ## echo "Do something." + ## + initdbScripts: {} + ## @param postgresql.initdbScriptsCM ConfigMap with scripts to be run at first boot + ## NOTE: This will override initdbScripts + ## + initdbScriptsCM: "" + ## @param postgresql.initdbScriptsSecret Secret with scripts to be run at first boot + ## Note: can be used with initdbScriptsCM or initdbScripts + ## + initdbScriptsSecret: "" + ## TLS configuration + ## + tls: + ## @param postgresql.tls.enabled Enable TLS traffic support for end-client connections + ## + enabled: false + ## @param postgresql.tls.preferServerCiphers Whether to use the server's TLS cipher preferences rather than the client's + ## + preferServerCiphers: true + ## @param postgresql.tls.certificatesSecret Name of an existing secret that contains the certificates + ## + certificatesSecret: "" + ## @param postgresql.tls.certFilename Certificate filename + ## + certFilename: "" + ## @param postgresql.tls.certKeyFilename Certificate key filename + ## + certKeyFilename: "" + ## @param postgresql.preStopDelayAfterPgStopSeconds Minimal number of seconds preStop hook waits after PostgreSQL instance is stopped + ## It is used to delay PostgreSQL pod termination. It gives Pgpool-II time to detect that node goes down. Down up cycle in + ## Pgpool-II makes sure PostgreSQL node is registered correctly in Pgpool-II (mainly primary flag). + ## Note: it could be replaced with .spec.minReadySeconds for Kubernetes v1.25 or later once + ## https://github.com/kubernetes/kubernetes/issues/112066 is fixed. + ## Note: must be set to lower value than terminationGracePeriodSeconds (defaults to 30) so that preStop hook finishes + ## before grace period expires + ## + preStopDelayAfterPgStopSeconds: 25 + ## @param postgresql.headlessWithNotReadyAddresses set postgres headless service into publishNotReadyAddresses mode + ## It can be used to minimize/eliminate Pgpool-II restarts during PostgreSQL rolling upgrades or edge-case situations like + ## network split. It expects that no other external component will use PostgreSQL headless service to connect or that + ## such component implements re-try logic. + ## This mode also enables enriched readiness probe implementation which delays first switch of POD to READY state + ## after start/restart of container. It gives Pgpool-II time switch node back from DOWN to UP state during rolling + ## upgrade. + ## + headlessWithNotReadyAddresses: false +witness: + ## ref: https://hub.docker.com/r/bitnami/postgresql/tags/ + ## @param witness.create Create PostgreSQL witness nodes + ## + create: false + ## @param witness.labels Labels to add to the StatefulSet. Evaluated as template + ## + labels: {} + ## @param witness.podLabels Labels to add to the StatefulSet pods. Evaluated as template + ## + podLabels: {} + ## @param witness.replicaCount Number of replicas to deploy. + ## + replicaCount: 1 + ## @param witness.updateStrategy.type Postgresql StatefulSet strategy type + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## e.g: + ## updateStrategy: + ## type: RollingUpdate + ## rollingUpdate: + ## maxSurge: 25% + ## maxUnavailable: 25% + ## + updateStrategy: + type: RollingUpdate + ## @param witness.containerPorts.postgresql PostgreSQL witness port + ## + containerPorts: + postgresql: 5432 + ## @param witness.automountServiceAccountToken Mount Service Account token in pod + ## + automountServiceAccountToken: false + ## @param witness.hostAliases Deployment pod host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param witness.hostNetwork Specify if host network should be enabled for PostgreSQL witness pod + ## + hostNetwork: false + ## @param witness.hostIPC Specify if host IPC should be enabled for PostgreSQL witness pod + ## + hostIPC: false + ## @param witness.podAnnotations Additional pod annotations + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param witness.podAffinityPreset PostgreSQL witness pod affinity preset. Ignored if `witness.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param witness.podAntiAffinityPreset PostgreSQL witness pod anti-affinity preset. Ignored if `witness.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## PostgreSQL witness node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param witness.nodeAffinityPreset.type PostgreSQL witness node affinity preset type. Ignored if `witness.affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param witness.nodeAffinityPreset.key PostgreSQL witness node label key to match Ignored if `witness.affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param witness.nodeAffinityPreset.values PostgreSQL witness node label values to match. Ignored if `witness.affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param witness.affinity Affinity for PostgreSQL witness pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## Note: witness.podAffinityPreset, witness.podAntiAffinityPreset, and witness.nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## @param witness.nodeSelector Node labels for PostgreSQL witness pods assignment + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: {} + ## @param witness.tolerations Tolerations for PostgreSQL witness pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param witness.topologySpreadConstraints Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#spread-constraints-for-pods + ## + topologySpreadConstraints: [] + ## @param witness.priorityClassName Pod priority class + ## Ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ + ## + priorityClassName: "" + ## @param witness.schedulerName Use an alternate scheduler, e.g. "stork". + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param witness.terminationGracePeriodSeconds Seconds PostgreSQL witness pod needs to terminate gracefully + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods + ## + terminationGracePeriodSeconds: "" + ## K8s Security Context + ## https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + ## @param witness.podSecurityContext.enabled Enable security context for PostgreSQL witness with Repmgr + ## @param witness.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy + ## @param witness.podSecurityContext.sysctls Set kernel settings using the sysctl interface + ## @param witness.podSecurityContext.supplementalGroups Set filesystem extra groups + ## @param witness.podSecurityContext.fsGroup Group ID for the PostgreSQL witness with Repmgr filesystem + ## + podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + sysctls: [] + supplementalGroups: [] + fsGroup: 1001 + ## Container Security Context + ## https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + ## @param witness.containerSecurityContext.enabled Enabled containers' Security Context + ## @param witness.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param witness.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param witness.containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup + ## @param witness.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param witness.containerSecurityContext.privileged Set container's Security Context privileged + ## @param witness.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param witness.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param witness.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param witness.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## e.g: + ## containerSecurityContext: + ## enabled: true + ## capabilities: + ## drop: ["NET_RAW"] + ## readOnlyRootFilesystem: false + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## @param witness.command Override default container command (useful when using custom images) + ## + command: [] + ## @param witness.args Override default container args (useful when using custom images) + ## + args: [] + ## @param witness.lifecycleHooks LifecycleHook to set additional configuration at startup, e.g. LDAP settings via REST API. Evaluated as a template + ## + lifecycleHooks: {} + ## @param witness.extraEnvVars Array containing extra environment variables + ## For example: + ## - name: PG_EXPORTER_DISABLE_DEFAULT_METRICS + ## value: "true" + ## + extraEnvVars: [] + ## @param witness.extraEnvVarsCM ConfigMap with extra environment variables + ## + extraEnvVarsCM: "" + ## @param witness.extraEnvVarsSecret Secret with extra environment variables + ## + extraEnvVarsSecret: "" + ## @param witness.extraVolumes Extra volumes to add to the deployment + ## + extraVolumes: [] + ## @param witness.extraVolumeMounts Extra volume mounts to add to the container. Normally used with `extraVolumes`. + ## + extraVolumeMounts: [] + ## @param witness.initContainers Extra init containers to add to the deployment + ## + initContainers: [] + ## @param witness.sidecars Extra sidecar containers to add to the deployment + ## + sidecars: [] + ## PostgreSQL containers' resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## 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:'. + ## @param witness.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if witness.resources is set (witness.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "micro" + ## @param witness.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## PostgreSQL container's liveness probe + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param witness.livenessProbe.enabled Enable livenessProbe + ## @param witness.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param witness.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param witness.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param witness.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param witness.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 6 + ## PostgreSQL container's readiness probe + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param witness.readinessProbe.enabled Enable readinessProbe + ## @param witness.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param witness.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param witness.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param witness.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param witness.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 6 + ## PostgreSQL container's startup probe + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param witness.startupProbe.enabled Enable startupProbe + ## @param witness.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param witness.startupProbe.periodSeconds Period seconds for startupProbe + ## @param witness.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param witness.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param witness.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 10 + ## @param witness.customLivenessProbe Override default liveness probe + ## + customLivenessProbe: {} + ## @param witness.customReadinessProbe Override default readiness probe + ## + customReadinessProbe: {} + ## @param witness.customStartupProbe Override default startup probe + ## + customStartupProbe: {} + ## Pod disruption budget configuration + ## @param witness.pdb.create Specifies whether to create a Pod disruption budget for PostgreSQL witness with Repmgr + ## @param witness.pdb.minAvailable Minimum number / percentage of pods that should remain scheduled + ## @param witness.pdb.maxUnavailable Maximum number/percentage of pods that may be made unavailable. Defaults to `1` if both `witness.pdb.minAvailable` and `witness.pdb.maxUnavailable` are empty. + ## + pdb: + create: true + minAvailable: "" + maxUnavailable: "" + ## @param witness.upgradeRepmgrExtension Upgrade repmgr extension in the database + ## + upgradeRepmgrExtension: false + ## @param witness.pgHbaTrustAll Configures PostgreSQL HBA to trust every user + ## + pgHbaTrustAll: false + ## Repmgr configuration parameters + ## @param witness.repmgrLogLevel Repmgr log level (DEBUG, INFO, NOTICE, WARNING, ERROR, ALERT, CRIT or EMERG) + ## @param witness.repmgrConnectTimeout Repmgr backend connection timeout (in seconds) + ## @param witness.repmgrReconnectAttempts Repmgr backend reconnection attempts + ## @param witness.repmgrReconnectInterval Repmgr backend reconnection interval (in seconds) + ## + repmgrLogLevel: NOTICE + repmgrConnectTimeout: 5 + repmgrReconnectAttempts: 2 + repmgrReconnectInterval: 3 + ## Audit settings + ## https://github.com/bitnami/containers/tree/main/bitnami/postgresql#auditing + ## + audit: + ## @param witness.audit.logHostname Add client hostnames to the log file + ## + logHostname: true + ## @param witness.audit.logConnections Add client log-in operations to the log file + ## + logConnections: false + ## @param witness.audit.logDisconnections Add client log-outs operations to the log file + ## + logDisconnections: false + ## @param witness.audit.pgAuditLog Add operations to log using the pgAudit extension + ## + pgAuditLog: "" + ## @param witness.audit.pgAuditLogCatalog Log catalog using pgAudit + ## + pgAuditLogCatalog: "off" + ## @param witness.audit.clientMinMessages Message log level to share with the user + ## + clientMinMessages: error + ## @param witness.audit.logLinePrefix Template string for the log line prefix + ## + logLinePrefix: "" + ## @param witness.audit.logTimezone Timezone for the log timestamps + ## + logTimezone: "" + ## @param witness.maxConnections Maximum total connections + ## + maxConnections: "" + ## @param witness.postgresConnectionLimit Maximum connections for the postgres user + ## + postgresConnectionLimit: "" + ## @param witness.dbUserConnectionLimit Maximum connections for the created user + ## + dbUserConnectionLimit: "" + ## @param witness.tcpKeepalivesInterval TCP keepalives interval + ## + tcpKeepalivesInterval: "" + ## @param witness.tcpKeepalivesIdle TCP keepalives idle + ## + tcpKeepalivesIdle: "" + ## @param witness.tcpKeepalivesCount TCP keepalives count + ## + tcpKeepalivesCount: "" + ## @param witness.statementTimeout Statement timeout + ## + statementTimeout: "" + ## @param witness.pghbaRemoveFilters Comma-separated list of patterns to remove from the pg_hba.conf file + ## (cannot be used with custom pg_hba.conf) + ## + pghbaRemoveFilters: "" + ## @param witness.extraInitContainers Extra init containers + ## Example: + ## extraInitContainers: + ## - name: do-something + ## image: busybox + ## command: ['do', 'something'] + ## + extraInitContainers: [] + ## @param witness.repmgrConfiguration Repmgr configuration + ## You can use this parameter to specify the content for repmgr.conf + ## Otherwise, a repmgr.conf will be generated based on the environment variables + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql-repmgr#configuration + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql-repmgr#configuration-file + ## Example: + ## repmgrConfiguration: |- + ## ssh_options='-o "StrictHostKeyChecking no" -v' + ## use_replication_slots='1' + ## ... + ## + repmgrConfiguration: "" + ## @param witness.configuration PostgreSQL configuration + ## You can use this parameter to specify the content for witness.conf + ## Otherwise, a repmgr.conf will be generated based on the environment variables + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql-repmgr#configuration + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql-repmgr#configuration-file + ## Example: + ## configuration: |- + ## listen_addresses = '*' + ## port = '5432' + ## ... + ## + configuration: "" + ## @param witness.pgHbaConfiguration PostgreSQL client authentication configuration + ## You can use this parameter to specify the content for pg_hba.conf + ## Otherwise, a repmgr.conf will be generated based on the environment variables + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql-repmgr#configuration + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql-repmgr#configuration-file + ## Example: + ## pgHbaConfiguration: |- + ## host all repmgr 0.0.0.0/0 md5 + ## host repmgr repmgr 0.0.0.0/0 md + ## ... + ## + pgHbaConfiguration: "" + ## @param witness.configurationCM Name of existing ConfigMap with configuration files + ## NOTE: This will override witness.repmgrConfiguration, witness.configuration and witness.pgHbaConfiguration + ## + configurationCM: "" + ## @param witness.extendedConf Extended PostgreSQL configuration (requires `volumePermissions.enabled` to be `true`) + ## Similar to witness.configuration, but _appended_ to the main configuration + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql-repmgr#allow-settings-to-be-loaded-from-files-other-than-the-default-postgresqlconf + ## Example: + ## extendedConf: |- + ## deadlock_timeout = 1s + ## max_locks_per_transaction = 64 + ## ... + ## + extendedConf: "" + ## @param witness.extendedConfCM ConfigMap with PostgreSQL extended configuration (requires `volumePermissions.enabled` to be `true`) + ## NOTE: This will override witness.extendedConf + ## + extendedConfCM: "" + ## @param witness.initdbScripts Dictionary of initdb scripts + ## Specify dictionary of scripts to be run at first boot + ## The allowed extensions are `.sh`, `.sql` and `.sql.gz` + ## ref: https://github.com/bitnami/charts/tree/main/bitnami/postgresql-ha#initialize-a-fresh-instance + ## e.g: + ## initdbScripts: + ## my_init_script.sh: | + ## #!/bin/sh + ## echo "Do something." + ## + initdbScripts: {} + ## @param witness.initdbScriptsCM ConfigMap with scripts to be run at first boot + ## NOTE: This will override initdbScripts + ## + initdbScriptsCM: "" + ## @param witness.initdbScriptsSecret Secret with scripts to be run at first boot + ## Note: can be used with initdbScriptsCM or initdbScripts + ## + initdbScriptsSecret: "" + +## @section Pgpool-II parameters + +## Pgpool-II parameters +## +pgpool: + ## Bitnami Pgpool-II image + ## ref: https://hub.docker.com/r/bitnami/pgpool/tags/ + ## @param pgpool.image.registry [default: REGISTRY_NAME] Pgpool-II image registry + ## @param pgpool.image.repository [default: REPOSITORY_NAME/pgpool] Pgpool-II image repository + ## @skip pgpool.image.tag Pgpool-II image tag + ## @param pgpool.image.digest Pgpool-II image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param pgpool.image.pullPolicy Pgpool-II image pull policy + ## @param pgpool.image.pullSecrets Specify docker-registry secret names as an array + ## @param pgpool.image.debug Specify if debug logs should be enabled + ## + image: + registry: docker.io + repository: bitnami/pgpool + tag: 4.6.3-debian-12-r0 + digest: "" + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-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/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Set to true if you would like to see extra information on logs + ## + debug: false + ## @param pgpool.customUsers.usernames Comma or semicolon separated list of additional users that will be performing connections to the database using pgpool. + ## @param pgpool.customUsers.passwords Comma or semicolon separated list of the associated passwords for the users above. Must have the same number of elements as the usernames list. + ## Use this property in order to create new user/password entries that will be appended to the "pgpool_passwd" file. + ## e.g: + ## customUsers: + ## usernames: "user01;user02" + ## passwords: "pass01;pass02" + customUsers: + usernames: "" + passwords: "" + ## @param pgpool.automountServiceAccountToken Mount Service Account token in pod + ## + automountServiceAccountToken: false + ## @param pgpool.hostAliases Deployment pod host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param pgpool.customUsersSecret Name of a secret containing the usernames and passwords of accounts that will be added to pgpool_passwd + ## The secret must contain the keys "usernames" and "passwords" respectively. + ## + customUsersSecret: "" + ## @param pgpool.existingSecret Pgpool-II admin password using existing secret + ## + existingSecret: "" + ## @param pgpool.labels Labels to add to the Deployment. Evaluated as template + ## + labels: {} + ## @param pgpool.podLabels Labels to add to the pods. Evaluated as template + ## + podLabels: {} + ## @param pgpool.serviceLabels Labels to add to the service. Evaluated as template + ## + serviceLabels: {} + ## @param pgpool.serviceAnnotations Provide any additional annotations for Pgpool-II service + ## + serviceAnnotations: {} + ## @param pgpool.customLivenessProbe Override default liveness probe + ## + customLivenessProbe: {} + ## @param pgpool.customReadinessProbe Override default readiness probe + ## + customReadinessProbe: {} + ## @param pgpool.customStartupProbe Override default startup probe + ## + customStartupProbe: {} + ## @param pgpool.command Override default container command (useful when using custom images) + ## + command: [] + ## @param pgpool.args Override default container args (useful when using custom images) + ## + args: [] + ## @param pgpool.lifecycleHooks LifecycleHook to set additional configuration at startup, e.g. LDAP settings via REST API. Evaluated as a template + ## + lifecycleHooks: {} + ## @param pgpool.extraEnvVars Array containing extra environment variables + ## For example: + ## - name: BEARER_AUTH + ## value: true + ## + extraEnvVars: [] + ## @param pgpool.extraEnvVarsCM ConfigMap with extra environment variables + ## + extraEnvVarsCM: "" + ## @param pgpool.extraEnvVarsSecret Secret with extra environment variables + ## + extraEnvVarsSecret: "" + ## @param pgpool.extraVolumes Extra volumes to add to the deployment + ## + extraVolumes: [] + ## @param pgpool.extraVolumeMounts Extra volume mounts to add to the container. Normally used with `extraVolumes` + ## + extraVolumeMounts: [] + ## @param pgpool.initContainers Extra init containers to add to the deployment + ## + initContainers: [] + ## @param pgpool.sidecars Extra sidecar containers to add to the deployment + ## + sidecars: [] + ## @param pgpool.replicaCount The number of replicas to deploy + ## + replicaCount: 1 + ## @param pgpool.podAnnotations Additional pod annotations + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param pgpool.priorityClassName Pod priority class + ## Ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ + ## + priorityClassName: "" + ## @param pgpool.schedulerName Use an alternate scheduler, e.g. "stork". + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param pgpool.terminationGracePeriodSeconds Seconds pgpool pod needs to terminate gracefully + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods + ## + terminationGracePeriodSeconds: "" + ## @param pgpool.topologySpreadConstraints Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#spread-constraints-for-pods + ## + topologySpreadConstraints: [] + ## @param pgpool.podAffinityPreset Pgpool-II pod affinity preset. Ignored if `pgpool.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param pgpool.podAntiAffinityPreset Pgpool-II pod anti-affinity preset. Ignored if `pgpool.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Pgpool-II node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param pgpool.nodeAffinityPreset.type Pgpool-II node affinity preset type. Ignored if `pgpool.affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param pgpool.nodeAffinityPreset.key Pgpool-II node label key to match Ignored if `pgpool.affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param pgpool.nodeAffinityPreset.values Pgpool-II node label values to match. Ignored if `pgpool.affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param pgpool.affinity Affinity for Pgpool-II pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## Note: pgpool.podAffinityPreset, pgpool.podAntiAffinityPreset, and pgpool.nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## @param pgpool.nodeSelector Node labels for Pgpool-II pods assignment + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: {} + ## @param pgpool.tolerations Tolerations for Pgpool-II pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## K8s Security Context + ## https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + ## @param pgpool.podSecurityContext.enabled Enable security context for Pgpool-II + ## @param pgpool.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy + ## @param pgpool.podSecurityContext.sysctls Set kernel settings using the sysctl interface + ## @param pgpool.podSecurityContext.supplementalGroups Set filesystem extra groups + ## @param pgpool.podSecurityContext.fsGroup Group ID for the Pgpool-II filesystem + ## + podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + sysctls: [] + supplementalGroups: [] + fsGroup: 1001 + ## Container Security Context + ## https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + ## @param pgpool.containerSecurityContext.enabled Enabled containers' Security Context + ## @param pgpool.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param pgpool.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param pgpool.containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup + ## @param pgpool.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param pgpool.containerSecurityContext.privileged Set container's Security Context privileged + ## @param pgpool.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param pgpool.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param pgpool.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param pgpool.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## e.g: + ## containerSecurityContext: + ## enabled: true + ## capabilities: + ## drop: ["NET_RAW"] + ## readOnlyRootFilesystem: false + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## Pgpool-II containers' resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## 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:'. + ## @param pgpool.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if pgpool.resources is set (pgpool.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "micro" + ## @param pgpool.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Pgpool-II container's liveness probe + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param pgpool.livenessProbe.enabled Enable livenessProbe + ## @param pgpool.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param pgpool.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param pgpool.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param pgpool.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param pgpool.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + ## Pgpool-II container's readiness probe + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param pgpool.readinessProbe.enabled Enable readinessProbe + ## @param pgpool.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param pgpool.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param pgpool.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param pgpool.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param pgpool.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## Pgpool-II container's startup probe + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param pgpool.startupProbe.enabled Enable startupProbe + ## @param pgpool.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param pgpool.startupProbe.periodSeconds Period seconds for startupProbe + ## @param pgpool.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param pgpool.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param pgpool.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 10 + ## Network Policies + ## Ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ + ## + networkPolicy: + ## @param pgpool.networkPolicy.enabled Specifies whether a NetworkPolicy should be created + ## + enabled: true + ## @param pgpool.networkPolicy.allowExternal Don't require server label for connections + ## The Policy model to apply. When set to false, only pods with the correct + ## server label will have network access to the ports server is listening + ## on. When true, server will accept connections from any source + ## (with the correct destination port). + ## + allowExternal: true + ## @param pgpool.networkPolicy.allowExternalEgress Allow the pod to access any range of port and all destinations. + ## + allowExternalEgress: true + ## @param pgpool.networkPolicy.extraIngress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraIngress: + ## - ports: + ## - port: 1234 + ## from: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + extraIngress: [] + ## @param pgpool.networkPolicy.extraEgress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraEgress: + ## - ports: + ## - port: 1234 + ## to: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraEgress: [] + ## @param pgpool.networkPolicy.ingressNSMatchLabels [object] Labels to match to allow traffic from other namespaces + ## @param pgpool.networkPolicy.ingressNSPodMatchLabels [object] Pod labels to match to allow traffic from other namespaces + ## + ingressNSMatchLabels: {} + ingressNSPodMatchLabels: {} + ## Pod disruption budget configuration + ## @param pgpool.pdb.create Specifies whether a Pod disruption budget should be created for Pgpool-II pods + ## @param pgpool.pdb.minAvailable Minimum number / percentage of pods that should remain scheduled + ## @param pgpool.pdb.maxUnavailable Maximum number/percentage of pods that may be made unavailable. Defaults to `1` if both `pgpool.pdb.minAvailable` and `pgpool.pdb.maxUnavailable` are empty. + ## + pdb: + create: true + minAvailable: "" + maxUnavailable: "" + ## @param pgpool.updateStrategy Strategy used to replace old Pods by new ones + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy + ## + updateStrategy: {} + ## @param pgpool.containerPorts.postgresql Pgpool-II port + ## + containerPorts: + postgresql: 5432 + ## @param pgpool.minReadySeconds How many seconds a pod needs to be ready before killing the next, during update + ## + minReadySeconds: "" + ## Credentials for the Pgpool-II + ## @param pgpool.adminUsername Pgpool-II Admin username + ## @param pgpool.adminPassword Pgpool-II Admin password + ## @param pgpool.srCheckUsername Pgpool-II Streaming Replication Check username + ## @param pgpool.srCheckPassword Pgpool-II Streaming Replication Check password + ## @param pgpool.srCheckDatabase Name of the database to perform Streaming Replication Check + ## + adminUsername: admin + adminPassword: "" + srCheckUsername: "sr_check_user" + srCheckPassword: "" + srCheckDatabase: postgres + ## @param pgpool.usePasswordFiles Set to `true` to mount pgpool secret as a file instead of passing environment variable + ## + usePasswordFiles: true + ## Authentication method for pgpool container (PGPOOL_AUTHENTICATION_METHOD) + ## @param pgpool.authenticationMethod Pgpool authentication method. Use 'md5' for PSQL < 14. + ## + authenticationMethod: scram-sha-256 + ## @param pgpool.logConnections Log all client connections (PGPOOL_ENABLE_LOG_CONNECTIONS) + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/pgpool#configuration + ## + logConnections: false + ## @param pgpool.logHostname Log the client hostname instead of IP address (PGPOOL_ENABLE_LOG_HOSTNAME) + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/pgpool#configuration + ## + logHostname: true + ## @param pgpool.logPcpProcesses Log PCP processes (PGPOOL_ENABLE_LOG_PCP_PROCESSES) + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/pgpool#configuration + ## + logPcpProcesses: true + ## @param pgpool.logPerNodeStatement Log every SQL statement for each DB node separately (PGPOOL_ENABLE_LOG_PER_NODE_STATEMENT) + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/pgpool#configuration + ## + logPerNodeStatement: false + ## @param pgpool.logLinePrefix Format of the log entry lines (PGPOOL_LOG_LINE_PREFIX) + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/pgpool#configuration + ## ref: https://www.pgpool.net/docs/latest/en/html/runtime-config-logging.html + ## + logLinePrefix: "" + ## @param pgpool.clientMinMessages Log level for clients + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/pgpool#configuration + ## + clientMinMessages: error + ## @param pgpool.numInitChildren The number of preforked Pgpool-II server processes. It is also the concurrent + ## connections limit to Pgpool-II from clients. Must be a positive integer. (PGPOOL_NUM_INIT_CHILDREN) + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/pgpool#configuration + ## + numInitChildren: "" + ## @param pgpool.reservedConnections Number of reserved connections. When zero, excess connection block. When non-zero, excess connections are refused with an error message. + ## When this parameter is set to 1 or greater, incoming connections from clients are not accepted with error message + ## "Sorry, too many clients already", rather than blocked if the number of current connections from clients is more than + ## (num_init_children - reserved_connections). + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/pgpool#configuration + ## + reservedConnections: 1 + ## @param pgpool.maxPool The maximum number of cached connections in each child process (PGPOOL_MAX_POOL) + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/pgpool#configuration + ## + maxPool: "" + ## @param pgpool.childMaxConnections The maximum number of client connections in each child process (PGPOOL_CHILD_MAX_CONNECTIONS) + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/pgpool#configuration + ## + childMaxConnections: "" + ## @param pgpool.childLifeTime The time in seconds to terminate a Pgpool-II child process if it remains idle (PGPOOL_CHILD_LIFE_TIME) + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/pgpool#configuration + ## + childLifeTime: "" + ## @param pgpool.clientIdleLimit The time in seconds to disconnect a client if it remains idle since the last query (PGPOOL_CLIENT_IDLE_LIMIT) + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/pgpool#configuration + ## + clientIdleLimit: "" + ## @param pgpool.connectionLifeTime The time in seconds to terminate the cached connections to the PostgreSQL backend (PGPOOL_CONNECTION_LIFE_TIME) + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/pgpool#configuration + ## + connectionLifeTime: "" + ## @param pgpool.useConnectionCache Use connection cache (PGPOOL_ENABLE_CONNECTION_CACHE) + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/pgpool#configuration + ## + useConnectionCache: true + ## @param pgpool.useLoadBalancing Use Pgpool-II Load-Balancing + ## + useLoadBalancing: true + ## @param pgpool.disableLoadBalancingOnWrite LoadBalancer on write actions behavior + ## one of: [off, transaction, trans_transaction, always] + ## + disableLoadBalancingOnWrite: transaction + ## @param pgpool.configuration Pgpool-II configuration + ## You can use this parameter to specify the content for pgpool.conf + ## Otherwise, a repmgr.conf will be generated based on the environment variables + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/pgpool#configuration + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/pgpool#configuration-file + ## Example: + ## configuration: |- + ## listen_addresses = '*' + ## port = '5432' + ## ... + ## + configuration: "" + ## @param pgpool.poolHbaConfiguration Pgpool-II client authentication configuration + ## You can use this parameter to specify the content for pool_hba.conf + ## Otherwise, a pool_hba.conf will be generated based on the environment variables + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql-repmgr#configuration + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql-repmgr#configuration-file + ## Example: + ## poolHbaConfiguration: |- + ## host all repmgr 0.0.0.0/0 md5 + ## host repmgr repmgr 0.0.0.0/0 md + ## ... + ## + poolHbaConfiguration: "" + ## @param pgpool.configurationCM ConfigMap with Pgpool-II configuration + ## NOTE: This will override pgpool.configuration and pgpool.poolHbaConfiguration parameters + ## + configurationCM: "" + ## @param pgpool.initdbScripts Dictionary of initdb scripts + ## Specify dictionary of scripts to be run every time Pgpool-II container is initialized + ## The allowed extension is `.sh` + ## ref: https://github.com/bitnami/charts/tree/main/bitnami/postgresql-ha#initialize-a-fresh-instance + ## e.g: + ## initdbScripts: + ## my_init_script.sh: | + ## #!/bin/sh + ## echo "Do something." + ## + initdbScripts: {} + ## @param pgpool.initdbScriptsCM ConfigMap with scripts to be run every time Pgpool-II container is initialized + ## NOTE: This will override pgpool.initdbScripts + ## + initdbScriptsCM: "" + ## @param pgpool.initdbScriptsSecret Secret with scripts to be run every time Pgpool-II container is initialized + ## Note: can be used with initdbScriptsCM or initdbScripts + ## + initdbScriptsSecret: "" + ## + ## TLS configuration + ## + tls: + ## @param pgpool.tls.enabled Enable TLS traffic support for end-client connections + ## + enabled: false + ## @param pgpool.tls.autoGenerated Create self-signed TLS certificates. Currently only supports PEM certificates + ## + autoGenerated: false + ## @param pgpool.tls.preferServerCiphers Whether to use the server's TLS cipher preferences rather than the client's + ## + preferServerCiphers: true + ## @param pgpool.tls.certificatesSecret Name of an existing secret that contains the certificates + ## + certificatesSecret: "" + ## @param pgpool.tls.certFilename Certificate filename + ## + certFilename: "" + ## @param pgpool.tls.certKeyFilename Certificate key filename + ## + certKeyFilename: "" + ## @param pgpool.tls.certCAFilename CA Certificate filename + ## If provided, Pgpool-II will authenticate TLS/SSL clients by requesting them a certificate + ## ref: https://www.pgpool.net/docs/latest/en/html/runtime-ssl.html + ## + certCAFilename: "" + +## @section LDAP parameters + +## LDAP parameters +## @param ldap.enabled Enable LDAP support +## @param ldap.existingSecret Name of existing secret to use for LDAP passwords +## @param ldap.uri LDAP URL beginning in the form `ldap[s]://:` +## @param ldap.basedn LDAP base DN +## @param ldap.binddn LDAP bind DN +## @param ldap.bindpw LDAP bind password +## @param ldap.bslookup LDAP base lookup +## @param ldap.scope LDAP search scope +## @param ldap.searchfilter LDAP search filter +## @param ldap.searchmap LDAP search map +## @param ldap.tlsReqcert LDAP TLS check on server certificates +## @param ldap.nssInitgroupsIgnoreusers LDAP ignored users +## +ldap: + enabled: false + existingSecret: "" + uri: "" + basedn: "" + binddn: "" + bindpw: "" + bslookup: "" + scope: "" + searchfilter: "" + searchmap: "" + tlsReqcert: "" + nssInitgroupsIgnoreusers: root,nslcd +## @section Other Parameters + +## RBAC configuration +## Required for PSP +## +rbac: + ## @param rbac.create Create Role and RoleBinding (required for PSP to work) + ## + create: false + ## @param rbac.rules Custom RBAC rules to set + ## e.g: + ## rules: + ## - apiGroups: + ## - "" + ## resources: + ## - pods + ## verbs: + ## - get + ## - list + ## + rules: [] +## ServiceAccount configuration +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ +## +serviceAccount: + ## @param serviceAccount.create Specifies whether a ServiceAccount should be created + ## + create: true + ## @param serviceAccount.name The name of the ServiceAccount to use. + ## If not set and create is true, a name is generated using the common.names.fullname template + ## + name: "" + ## @param serviceAccount.annotations Additional custom annotations for the ServiceAccount + ## + annotations: {} + ## @param serviceAccount.automountServiceAccountToken Allows auto mount of ServiceAccountToken on the serviceAccount created + ## Can be set to false if pods using this serviceAccount do not need to use K8s API + ## + automountServiceAccountToken: false +## Pod Security Policy configuration +## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ +## @param psp.create Whether to create a PodSecurityPolicy. WARNING: PodSecurityPolicy is deprecated in Kubernetes v1.21 or later, unavailable in v1.25 or later +## +psp: + create: false +## @section Metrics parameters + +## PostgreSQL Prometheus exporter parameters +## +metrics: + ## Bitnami PostgreSQL Prometheus exporter image + ## @param metrics.enabled Enable PostgreSQL Prometheus exporter + ## + enabled: false + ## ref: https://hub.docker.com/r/bitnami/pgpool/tags/ + ## @param metrics.image.registry [default: REGISTRY_NAME] PostgreSQL Prometheus exporter image registry + ## @param metrics.image.repository [default: REPOSITORY_NAME/postgres-exporter] PostgreSQL Prometheus exporter image repository + ## @skip metrics.image.tag PostgreSQL Prometheus exporter image tag + ## @param metrics.image.digest PostgreSQL Prometheus exporter image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param metrics.image.pullPolicy PostgreSQL Prometheus exporter image pull policy + ## @param metrics.image.pullSecrets Specify docker-registry secret names as an array + ## @param metrics.image.debug Specify if debug logs should be enabled + ## + image: + registry: docker.io + repository: bitnami/postgres-exporter + tag: 0.17.1-debian-12-r16 + digest: "" + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-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/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Set to true if you would like to see extra information on logs + ## + debug: false + ## K8s Security Context + ## https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + ## @param metrics.podSecurityContext.enabled Enable security context for PostgreSQL Prometheus exporter + ## @param metrics.podSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param metrics.podSecurityContext.runAsUser User ID for the PostgreSQL Prometheus exporter container + ## @param metrics.podSecurityContext.runAsGroup Group ID for the PostgreSQL Prometheus exporter container + ## @param metrics.podSecurityContext.runAsNonRoot Set PostgreSQL Prometheus exporter container's Security Context runAsNonRoot + ## @param metrics.podSecurityContext.seccompProfile.type Set PostgreSQL Prometheus exporter container's Security Context seccompProfile + ## + podSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + ## Prometheus exporter containers' resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## 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:'. + ## @param metrics.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if metrics.resources is set (metrics.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param metrics.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## @param metrics.containerPorts.http Prometheus metrics exporter port + ## + containerPorts: + http: 9187 + ## Prometheus exporter container's liveness probe + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param metrics.livenessProbe.enabled Enable livenessProbe + ## @param metrics.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param metrics.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param metrics.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param metrics.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param metrics.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 6 + ## Prometheus exporter container's readiness probe + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param metrics.readinessProbe.enabled Enable readinessProbe + ## @param metrics.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param metrics.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param metrics.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param metrics.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param metrics.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 6 + ## Prometheus exporter container's startup probes + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param metrics.startupProbe.enabled Enable startupProbe + ## @param metrics.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param metrics.startupProbe.periodSeconds Period seconds for startupProbe + ## @param metrics.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param metrics.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param metrics.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 10 + ## @param metrics.customLivenessProbe Override default liveness probe + ## + customLivenessProbe: {} + ## @param metrics.customReadinessProbe Override default readiness probe + ## + customReadinessProbe: {} + ## @param metrics.customStartupProbe Override default startup probe + ## + customStartupProbe: {} + ## Metrics service parameters + ## + service: + ## @param metrics.service.enabled PostgreSQL Prometheus exporter metrics service enabled + ## + enabled: true + ## @param metrics.service.type PostgreSQL Prometheus exporter metrics service type + ## + type: ClusterIP + ## @param metrics.service.ports.metrics PostgreSQL Prometheus exporter metrics service port + ## + ports: + metrics: 9187 + ## @param metrics.service.nodePorts.metrics PostgreSQL Prometheus exporter Node Port + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + nodePorts: + metrics: "" + ## @param metrics.service.clusterIP PostgreSQL Prometheus exporter metrics service Cluster IP + ## e.g.: + ## clusterIP: None + ## + clusterIP: "" + ## @param metrics.service.loadBalancerIP PostgreSQL Prometheus exporter service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerIP: "" + ## @param metrics.service.loadBalancerSourceRanges PostgreSQL Prometheus exporter service Load Balancer sources + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param metrics.service.externalTrafficPolicy PostgreSQL Prometheus exporter service external traffic policy + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param metrics.annotations [object] Annotations for PostgreSQL Prometheus exporter service + ## + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "9187" + ## @param metrics.customMetrics 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_bytes 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" + ## + customMetrics: {} + ## @param metrics.extraEnvVars Array containing extra environment variables + ## For example: + ## - name: BEARER_AUTH + ## value: true + ## + extraEnvVars: [] + ## @param metrics.extraEnvVarsCM ConfigMap with extra environment variables + ## + extraEnvVarsCM: "" + ## @param metrics.extraEnvVarsSecret Secret with extra environment variables + ## + extraEnvVarsSecret: "" + ## Metrics serviceMonitor parameters + ## Enable this if you're using Prometheus Operator + ## + serviceMonitor: + ## @param metrics.serviceMonitor.enabled if `true`, creates a Prometheus Operator ServiceMonitor (also requires `metrics.enabled` to be `true`) + ## + enabled: false + ## @param metrics.serviceMonitor.namespace Optional namespace which Prometheus is running in + ## Fallback to the prometheus default unless specified + ## + namespace: "" + ## @param metrics.serviceMonitor.interval How frequently to scrape metrics (use by default, falling back to Prometheus' default) + ## e.g: + ## interval: 10s + ## + interval: "" + ## @param metrics.serviceMonitor.scrapeTimeout Service monitor scrape timeout + ## e.g: + ## scrapeTimeout: 10s + ## + scrapeTimeout: "" + ## @param metrics.serviceMonitor.annotations Additional annotations for the ServiceMonitor + ## + annotations: {} + ## @param metrics.serviceMonitor.labels Additional labels that can be used so ServiceMonitor will be discovered by Prometheus + ## + labels: {} + ## @param metrics.serviceMonitor.selector [object] Defaults to what's used if you follow CoreOS Prometheus Install Instructions () + ## Prometheus Selector Label (https://github.com/bitnami/charts/tree/main/bitnami/kube-prometheus#prometheus-operator-parameters) + ## Kube Prometheus Selector Label (https://github.com/bitnami/charts/tree/main/bitnami/kube-prometheus#exporters) + ## + selector: + prometheus: kube-prometheus + ## @param metrics.serviceMonitor.relabelings ServiceMonitor relabelings. Value is evaluated as a template + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#relabelconfig + ## + relabelings: [] + ## @param metrics.serviceMonitor.metricRelabelings ServiceMonitor metricRelabelings. Value is evaluated as a template + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#relabelconfig + ## + metricRelabelings: [] + ## @param metrics.serviceMonitor.honorLabels Specify honorLabels parameter to add the scrape endpoint + ## + honorLabels: false + ## @param metrics.serviceMonitor.jobLabel The name of the label on the target service to use as the job name in prometheus. + ## + jobLabel: "" +## @section Volume permissions parameters + +## Init Container parameters +## volumePermissions: Change the owner and group of the persistent volume mountpoint +## +volumePermissions: + ## @param volumePermissions.enabled Enable init container to adapt volume permissions + ## + enabled: false + ## @param volumePermissions.image.registry [default: REGISTRY_NAME] Init container volume-permissions image registry + ## @param volumePermissions.image.repository [default: REPOSITORY_NAME/os-shell] Init container volume-permissions image repository + ## @skip volumePermissions.image.tag Init container volume-permissions image tag + ## @param volumePermissions.image.digest Init container volume-permissions image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param volumePermissions.image.pullPolicy Init container volume-permissions image pull policy + ## @param volumePermissions.image.pullSecrets Specify docker-registry secret names as an array + ## + image: + registry: docker.io + repository: bitnami/os-shell + tag: 12-debian-12-r51 + digest: "" + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-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/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## K8s Security Context + ## https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + ## @param volumePermissions.podSecurityContext.enabled Whether to enable security context for the volume-permissions init container + ## @param volumePermissions.podSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param volumePermissions.podSecurityContext.runAsUser Init container volume-permissions User ID + ## @param volumePermissions.podSecurityContext.runAsGroup Group ID for the init container volume-permissions container + ## @param volumePermissions.podSecurityContext.runAsNonRoot Set Security Context runAsNonRoot for the init container volume-permissions container + ## @param volumePermissions.podSecurityContext.seccompProfile.type Set Security Context seccompProfile for the init container volume-permissions container + ## + podSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 0 + runAsGroup: 0 + runAsNonRoot: false + seccompProfile: + type: RuntimeDefault + ## Init container' resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## 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:'. + ## @param volumePermissions.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if volumePermissions.resources is set (volumePermissions.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param volumePermissions.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} +## @section Persistence parameters + +## Enable persistence using Persistent Volume Claims +## ref: https://kubernetes.io/docs/concepts/storage/persistent-volumes/ +## +persistence: + ## @param persistence.enabled Enable data persistence + ## + enabled: true + ## @param persistence.existingClaim A manually managed Persistent Volume and Claim + ## If defined, PVC must be created manually before volume will be bound. + ## All replicas will share this PVC, using existingClaim with replicas > 1 is only useful in very special use cases. + ## The value is evaluated as a template. + ## + existingClaim: "" + ## @param persistence.storageClass 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. + ## + storageClass: "" + ## @param persistence.mountPath The path the volume will be mounted at, useful when using different PostgreSQL images. + ## + mountPath: /bitnami/postgresql + ## @param persistence.accessModes List of access modes of data volume + ## + accessModes: + - ReadWriteOnce + ## @param persistence.size Persistent Volume Claim size + ## + size: 8Gi + ## @param persistence.annotations Persistent Volume Claim annotations + ## + annotations: {} + ## @param persistence.labels Persistent Volume Claim labels + ## + labels: {} + ## @param persistence.selector Selector to match an existing Persistent Volume (this value is evaluated as a template) + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} +## Persistent Volume Claim Retention Policy +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention +## +persistentVolumeClaimRetentionPolicy: + ## @param persistentVolumeClaimRetentionPolicy.enabled Enable Persistent volume retention policy for postgresql Statefulset + ## + enabled: false + ## @param persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced + ## + whenScaled: Retain + ## @param persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted + ## + whenDeleted: Retain +## @section Traffic Exposure parameters + +## PostgreSQL service parameters +## +service: + ## @param service.type Kubernetes service type (`ClusterIP`, `NodePort` or `LoadBalancer`) + ## + type: ClusterIP + ## @param service.ports.postgresql PostgreSQL port + ## + ports: + postgresql: 5432 + ## @param service.portName PostgreSQL service port name + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#multi-port-services + ## + portName: postgresql + ## @param service.nodePorts.postgresql Kubernetes service nodePort + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + nodePorts: + postgresql: "" + ## @param service.loadBalancerIP Load balancer IP if service type is `LoadBalancer` + ## Set the LoadBalancer service type to internal only + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param service.loadBalancerSourceRanges Addresses that are allowed when service is LoadBalancer + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param service.clusterIP Set the Cluster IP to use + ## Static clusterIP or None for headless services + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#choosing-your-own-ip-address + ## e.g: + ## clusterIP: None + ## + clusterIP: "" + ## @param service.externalTrafficPolicy Enable client source IP preservation + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param service.sessionAffinity Control where client requests go, to the same pod or round-robin + ## Values: ClientIP or None + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/ + ## + sessionAffinity: "None" + ## @param service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + sessionAffinityConfig: {} + ## @param service.annotations Provide any additional annotations both for PostgreSQL and Pgpool-II services + ## + annotations: {} + ## @param service.serviceLabels Labels for PostgreSQL service + ## + serviceLabels: {} + ## Headless service properties + ## + headless: + ## @param service.headless.annotations Annotations for the headless service. + ## + annotations: {} +## @section Backup parameters +## This section implements a trivial logical dump cronjob of the database. +## This only comes with the consistency guarantees of the dump program. +## This is not a snapshot based roll forward/backward recovery backup. +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/ +backup: + ## @param backup.enabled Enable the logical dump of the database "regularly" + enabled: false + cronjob: + ## @param backup.cronjob.schedule Set the cronjob parameter schedule + schedule: "@daily" + ## @param backup.cronjob.timeZone Set the cronjob parameter timeZone + timeZone: "" + ## @param backup.cronjob.concurrencyPolicy Set the cronjob parameter concurrencyPolicy + concurrencyPolicy: Allow + ## @param backup.cronjob.failedJobsHistoryLimit Set the cronjob parameter failedJobsHistoryLimit + failedJobsHistoryLimit: 1 + ## @param backup.cronjob.successfulJobsHistoryLimit Set the cronjob parameter successfulJobsHistoryLimit + successfulJobsHistoryLimit: 3 + ## @param backup.cronjob.startingDeadlineSeconds Set the cronjob parameter startingDeadlineSeconds + startingDeadlineSeconds: "" + ## @param backup.cronjob.ttlSecondsAfterFinished Set the cronjob parameter ttlSecondsAfterFinished + ttlSecondsAfterFinished: "" + ## @param backup.cronjob.restartPolicy Set the cronjob parameter restartPolicy + restartPolicy: OnFailure + ## @param backup.cronjob.podSecurityContext.enabled Enable PodSecurityContext for CronJob/Backup + ## @param backup.cronjob.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy + ## @param backup.cronjob.podSecurityContext.sysctls Set kernel settings using the sysctl interface + ## @param backup.cronjob.podSecurityContext.supplementalGroups Set filesystem extra groups + ## @param backup.cronjob.podSecurityContext.fsGroup Group ID for the CronJob + podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + sysctls: [] + supplementalGroups: [] + fsGroup: 1001 + ## backup container's Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param backup.cronjob.containerSecurityContext.enabled Enable container security context + ## @param backup.cronjob.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param backup.cronjob.containerSecurityContext.runAsUser User ID for the backup container + ## @param backup.cronjob.containerSecurityContext.runAsGroup Group ID for the backup container + ## @param backup.cronjob.containerSecurityContext.runAsNonRoot Set backup container's Security Context runAsNonRoot + ## @param backup.cronjob.containerSecurityContext.readOnlyRootFilesystem Is the container itself readonly + ## @param backup.cronjob.containerSecurityContext.allowPrivilegeEscalation Is it possible to escalate backup pod(s) privileges + ## @param backup.cronjob.containerSecurityContext.seccompProfile.type Set backup container's Security Context seccompProfile type + ## @param backup.cronjob.containerSecurityContext.capabilities.drop Set backup container's Security Context capabilities to drop + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + ## @param backup.cronjob.command Set backup container's command to run + command: + - /bin/bash + - -c + - PGPASSWORD="${PGPASSWORD:-$(< "$PGPASSWORD_FILE")}" pg_dumpall --clean --if-exists --load-via-partition-root --quote-all-identifiers --no-password --file="${PGDUMP_DIR}/pg_dumpall-$(date '+%Y-%m-%d-%H-%M').pgdump" + ## @param backup.cronjob.labels Set the cronjob labels + labels: {} + ## @param backup.cronjob.annotations Set the cronjob annotations + annotations: {} + ## @param backup.cronjob.nodeSelector Node labels for PostgreSQL backup CronJob pod assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + ## @param backup.cronjob.tolerations Tolerations for PostgreSQL backup CronJob pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param backup.cronjob.podAffinityPreset PostgreSQL backup pod affinity preset. Ignored if `backup.cronjob.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## PostgreSQL backup node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param backup.cronjob.nodeAffinityPreset.type PostgreSQL backup node affinity preset type. Ignored if `backup.cronjob.affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param backup.cronjob.nodeAffinityPreset.key PostgreSQL backup node label key to match Ignored if `backup.cronjob.affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param backup.cronjob.nodeAffinityPreset.values PostgreSQL backup node label values to match. Ignored if `backup.cronjob.affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param backup.cronjob.affinity Affinity for PostgreSQL backup pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## Note: backup.cronjob.podAffinityPreset and backup.cronjob.nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## backup cronjob container resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param backup.cronjob.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if backup.cronjob.resources is set (backup.cronjob.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param backup.cronjob.resources Set container requests and limits for different resources like CPU or memory + ## Example: + resources: {} + ## resources: + ## requests: + ## cpu: 1 + ## memory: 512Mi + ## limits: + ## cpu: 2 + ## memory: 1024Mi + ## @param backup.cronjob.extraEnvVars Array containing extra environment variables + ## For example: + ## - name: BEARER_AUTH + ## value: true + ## + extraEnvVars: [] + ## @param backup.cronjob.extraEnvVarsCM ConfigMap with extra environment variables + ## + extraEnvVarsCM: "" + ## @param backup.cronjob.extraEnvVarsSecret Secret with extra environment variables + ## + extraEnvVarsSecret: "" + ## @param backup.cronjob.extraVolumes Extra volumes to add to the backup container + ## + extraVolumes: [] + ## @param backup.cronjob.extraVolumeMounts Extra volume mounts to add to the backup container. Normally used with `extraVolumes` + ## + extraVolumeMounts: [] + storage: + ## @param backup.cronjob.storage.existingClaim Provide an existing `PersistentVolumeClaim` (only when `architecture=standalone`) + ## If defined, PVC must be created manually before volume will be bound + ## + existingClaim: "" + ## @param backup.cronjob.storage.resourcePolicy Setting it to "keep" to avoid removing PVCs during a helm delete operation. Leaving it empty will delete PVCs after the chart deleted + ## + resourcePolicy: "" + ## @param backup.cronjob.storage.storageClass PVC Storage Class for the backup data volume + ## 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. + ## + storageClass: "" + ## @param backup.cronjob.storage.accessModes PV Access Mode + ## + accessModes: + - ReadWriteOnce + ## @param backup.cronjob.storage.size PVC Storage Request for the backup data volume + ## + size: 8Gi + ## @param backup.cronjob.storage.annotations PVC annotations + ## + annotations: {} + ## @param backup.cronjob.storage.mountPath Path to mount the volume at + ## + mountPath: /backup/pgdump + ## @param backup.cronjob.storage.subPath Subdirectory of the volume to mount at + ## and one PV for multiple services. + ## + subPath: "" + ## Fine tuning for volumeClaimTemplates + ## + volumeClaimTemplates: + ## @param backup.cronjob.storage.volumeClaimTemplates.selector A label query over volumes to consider for binding (e.g. when using local volumes) + ## A label query over volumes to consider for binding (e.g. when using local volumes) + ## See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#labelselector-v1-meta for more details + ## + selector: {} diff --git a/backing-services/gitea/charts/postgresql/.helmignore b/backing-services/gitea/charts/postgresql/.helmignore new file mode 100644 index 0000000..207983f --- /dev/null +++ b/backing-services/gitea/charts/postgresql/.helmignore @@ -0,0 +1,25 @@ +# 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 +# img folder +img/ +# Changelog +CHANGELOG.md diff --git a/backing-services/gitea/charts/postgresql/Chart.lock b/backing-services/gitea/charts/postgresql/Chart.lock new file mode 100644 index 0000000..2f96f22 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + version: 2.31.4 +digest: sha256:fc442e77200e1914dd46fe26490dcf62f44caa51db673c2f8e67d5319cd4c163 +generated: "2025-08-14T15:30:01.842897577Z" diff --git a/backing-services/gitea/charts/postgresql/Chart.yaml b/backing-services/gitea/charts/postgresql/Chart.yaml new file mode 100644 index 0000000..27351d0 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/Chart.yaml @@ -0,0 +1,38 @@ +annotations: + category: Database + images: | + - name: os-shell + image: docker.io/bitnami/os-shell:12-debian-12-r51 + - name: postgres-exporter + image: docker.io/bitnami/postgres-exporter:0.17.1-debian-12-r16 + - name: postgresql + image: docker.io/bitnami/postgresql:17.6.0-debian-12-r4 + licenses: Apache-2.0 + tanzuCategory: service +apiVersion: v2 +appVersion: 17.6.0 +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + tags: + - bitnami-common + version: 2.x.x +description: PostgreSQL (Postgres) is an open source object-relational database known + for reliability and data integrity. ACID-compliant, it supports foreign keys, joins, + views, triggers and stored procedures. +home: https://bitnami.com +icon: https://dyltqmyl993wv.cloudfront.net/assets/stacks/postgresql/img/postgresql-stack-220x234.png +keywords: +- postgresql +- postgres +- database +- sql +- replication +- cluster +maintainers: +- name: Broadcom, Inc. All Rights Reserved. + url: https://github.com/bitnami/charts +name: postgresql +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/postgresql +version: 16.7.27 diff --git a/backing-services/gitea/charts/postgresql/README.md b/backing-services/gitea/charts/postgresql/README.md new file mode 100644 index 0000000..045e410 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/README.md @@ -0,0 +1,1154 @@ + + +# Bitnami package for PostgreSQL + +PostgreSQL (Postgres) is an open source object-relational database known for reliability and data integrity. ACID-compliant, it supports foreign keys, joins, views, triggers and stored procedures. + +[Overview of PostgreSQL](http://www.postgresql.org) + +Trademarks: This software listing is packaged by Bitnami. The respective trademarks mentioned in the offering are owned by the respective companies, and use of them does not imply any affiliation or endorsement. + +## TL;DR + +```console +helm install my-release oci://registry-1.docker.io/bitnamicharts/postgresql +``` + +> Tip: Did you know that this app is also available as a Kubernetes App on the Azure Marketplace? Kubernetes Apps are the easiest way to deploy Bitnami on AKS. Click [here](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/bitnami.postgresql-cnab) to see the listing on Azure Marketplace. + +Looking to use PostgreSQL in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the commercial edition of the Bitnami catalog. + +## ⚠️ Important Notice: Upcoming changes to the Bitnami Catalog + +Beginning August 28th, 2025, Bitnami will evolve its public catalog to offer a curated set of hardened, security-focused images under the new [Bitnami Secure Images initiative](https://news.broadcom.com/app-dev/broadcom-introduces-bitnami-secure-images-for-production-ready-containerized-applications). As part of this transition: + +- Granting community users access for the first time to security-optimized versions of popular container images. +- Bitnami will begin deprecating support for non-hardened, Debian-based software images in its free tier and will gradually remove non-latest tags from the public catalog. As a result, community users will have access to a reduced number of hardened images. These images are published only under the “latest” tag and are intended for development purposes +- Starting August 28th, over two weeks, all existing container images, including older or versioned tags (e.g., 2.50.0, 10.6), will be migrated from the public catalog (docker.io/bitnami) to the “Bitnami Legacy” repository (docker.io/bitnamilegacy), where they will no longer receive updates. +- For production workloads and long-term support, users are encouraged to adopt Bitnami Secure Images, which include hardened containers, smaller attack surfaces, CVE transparency (via VEX/KEV), SBOMs, and enterprise support. + +These changes aim to improve the security posture of all Bitnami users by promoting best practices for software supply chain integrity and up-to-date deployments. For more details, visit the [Bitnami Secure Images announcement](https://github.com/bitnami/containers/issues/83267). + +## Introduction + +This chart bootstraps a [PostgreSQL](https://github.com/bitnami/containers/tree/main/bitnami/postgresql) deployment on a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +For HA, please see [this repo](https://github.com/bitnami/charts/tree/main/bitnami/postgresql-ha) + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ +- 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 oci://REGISTRY_NAME/REPOSITORY_NAME/postgresql +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +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` + +## Configuration and installation details + +### Resource requests and limits + +Bitnami charts allow setting resource requests and limits for all containers inside the chart deployment. These are inside the `resources` value (check parameter table). Setting requests is essential for production workloads and these should be adapted to your specific use case. + +To make this process easier, the chart contains the `resourcesPreset` values, which automatically sets the `resources` section according to different presets. Check these presets in [the bitnami/common chart](https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15). However, in production workloads using `resourcesPreset` is discouraged as it may not fully adapt to your specific needs. Find more information on container resource management in the [official Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). + +### Prometheus metrics + +This chart can be integrated with Prometheus by setting `metrics.enabled` to `true`. This will deploy a sidecar container with [postgres_exporter](https://github.com/prometheus-community/postgres_exporter) in all pods. It will also create `metrics` services that can be configured under the `metrics.service` section. These services will be have the necessary annotations to be automatically scraped by Prometheus. + +#### Prometheus requirements + +It is necessary to have a working installation of Prometheus or Prometheus Operator for the integration to work. Install the [Bitnami Prometheus helm chart](https://github.com/bitnami/charts/tree/main/bitnami/prometheus) or the [Bitnami Kube Prometheus helm chart](https://github.com/bitnami/charts/tree/main/bitnami/kube-prometheus) to easily have a working Prometheus in your cluster. + +#### Integration with Prometheus Operator + +The chart can deploy `ServiceMonitor` objects for integration with Prometheus Operator installations. To do so, set the value `metrics.serviceMonitor.enabled=true`. Ensure that the Prometheus Operator `CustomResourceDefinitions` are installed in the cluster or it will fail with the following error: + +```text +no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1" +``` + +Install the [Bitnami Kube Prometheus helm chart](https://github.com/bitnami/charts/tree/main/bitnami/kube-prometheus) for having the necessary CRDs and the Prometheus Operator. + +### [Rolling VS Immutable tags](https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-understand-rolling-tags-containers-index.html) + +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. + +### Customizing primary and read replica services in a replicated configuration + +At the top level, there is a service object which defines the services for both primary and readReplicas. For deeper customization, there are service objects for both the primary and read types individually. This allows you to override the values in the top level service object so that the primary and read can be of different service types and with different clusterIPs / nodePorts. Also in the case you want the primary and read to be of type nodePort, you will need to set the nodePorts to different values to prevent a collision. The values that are deeper in the primary.service or readReplicas.service objects will take precedence over the top level service object. + +### Use a different PostgreSQL version + +To modify the application version used in this chart, specify a different version of the image using the `image.tag` parameter and/or a different repository using the `image.repository` parameter. + +### LDAP + +LDAP support can be enabled in the chart by specifying the `ldap.` parameters while creating a release. The following parameters should be configured to properly enable the LDAP support in the chart. + +- **ldap.enabled**: Enable LDAP support. Defaults to `false`. +- **ldap.uri**: LDAP URL beginning in the form `ldap[s]://:`. No defaults. +- **ldap.base**: LDAP base DN. No defaults. +- **ldap.binddn**: LDAP bind DN. No defaults. +- **ldap.bindpw**: LDAP bind password. No defaults. +- **ldap.bslookup**: LDAP base lookup. No defaults. +- **ldap.nss_initgroups_ignoreusers**: LDAP ignored users. `root,nslcd`. +- **ldap.scope**: LDAP search scope. No defaults. +- **ldap.tls_reqcert**: LDAP TLS check on server certificates. No defaults. + +For example: + +```text +ldap.enabled="true" +ldap.uri="ldap://my_ldap_server" +ldap.base="dc=example\,dc=org" +ldap.binddn="cn=admin\,dc=example\,dc=org" +ldap.bindpw="admin" +ldap.bslookup="ou=group-ok\,dc=example\,dc=org" +ldap.nss_initgroups_ignoreusers="root\,nslcd" +ldap.scope="sub" +ldap.tls_reqcert="demand" +``` + +Next, login to the PostgreSQL server using the `psql` client and add the PAM authenticated LDAP users. + +> Note: Parameters including commas must be escaped as shown in the above example. + +### Update credentials + +Bitnami charts, with its default settings, configure credentials at first boot. Any further change in the secrets or credentials can be done using one of the following methods: + +### Manual update of the passwords and secrets + +- Update the user password following [the upstream documentation](https://www.postgresql.org/docs/current/sql-alteruser.html) +- Update the password secret with the new values (replace the SECRET_NAME, PASSWORD and POSTGRES_PASSWORD placeholders) + +```shell +kubectl create secret generic SECRET_NAME --from-literal=password=PASSWORD --from-literal=postgres-password=POSTGRES_PASSWORD --dry-run -o yaml | kubectl apply -f - +``` + +### Automated update using a password update job + +The Bitnami PostgreSQL provides a password update job that will automatically change the PostgreSQL passwords when running helm upgrade. To enable the job set `passwordUpdateJob.enabled=true`. This job requires: + +- The new passwords: this is configured using either `auth.postgresPassword`, `auth.password` and `auth.replicationPassword` (if applicable) or setting `auth.existingSecret`. +- The previous passwords: This value is taken automatically from already deployed secret object. If you are using `auth.existingSecret` or `helm template` instead of `helm upgrade`, then set either `passwordUpdateJob.previousPasswords.postgresPassword`, `passwordUpdateJob.previousPasswords.password`, `passwordUpdateJob.previousPasswords.replicationPassword` (when applicable), or setting `passwordUpdateJob.previousPasswords.existingSecret`. + +In the following example we update the password via values.yaml in a PostgreSQL installation with replication + +```yaml +architecture: "replication" + +auth: + user: "user" + postgresPassword: "newPostgresPassword123" + password: "newUserPassword123" + replicationPassword: "newReplicationPassword123" + +passwordUpdateJob: + enabled: true +``` + +In this example we use two existing secrets (`new-password-secret` and `previous-password-secret`) to update the passwords: + +```yaml +auth: + existingSecret: new-password-secret + +passwordUpdateJob: + enabled: true + previousPasswords: + existingSecret: previous-password-secret +``` + +You can add extra update commands using the `passwordUpdateJob.extraCommands` value. + +### postgresql.conf / pg_hba.conf files as configMap + +This helm chart also supports to customize the PostgreSQL configuration file. You can add additional PostgreSQL configuration parameters using the `primary.extendedConfiguration`/`readReplicas.extendedConfiguration` parameters as a string. Alternatively, to replace the entire default configuration use `primary.configuration`. + +You can also add a custom pg_hba.conf using the `primary.pgHbaConfiguration` parameter. + +In addition to these options, you can also set an external ConfigMap with all the configuration files. This is done by setting the `primary.existingConfigmap` parameter. Note that this will override the two previous options. + +### Initialize a fresh instance + +The [Bitnami PostgreSQL](https://github.com/bitnami/containers/tree/main/bitnami/postgresql) image allows you to use your custom scripts to initialize a fresh instance. In order to execute the scripts, you can specify custom scripts using the `primary.initdb.scripts` parameter as a string. + +In addition, you can also set an external ConfigMap with all the initialization scripts. This is done by setting the `primary.initdb.scriptsConfigMap` 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 `primary.initdb.scriptsSecret` parameter. + +The allowed extensions are `.sh`, `.sql` and `.sql.gz`. + +### Securing traffic using TLS + +TLS support can be enabled in the chart by specifying the `tls.` parameters while creating a release. The following parameters should be configured to properly enable the TLS support in the chart: + +- `tls.enabled`: Enable TLS support. Defaults to `false` +- `tls.certificatesSecret`: Name of an existing secret that contains the certificates. No defaults. +- `tls.certFilename`: Certificate filename. No defaults. +- `tls.certKeyFilename`: Certificate key filename. No defaults. + +For example: + +- First, create the secret with the cetificates files: + + ```console + kubectl create secret generic certificates-tls-secret --from-file=./cert.crt --from-file=./cert.key --from-file=./ca.crt + ``` + +- Then, use the following parameters: + + ```console + volumePermissions.enabled=true + tls.enabled=true + tls.certificatesSecret="certificates-tls-secret" + tls.certFilename="cert.crt" + tls.certKeyFilename="cert.key" + ``` + + > Note TLS and VolumePermissions: PostgreSQL requires certain permissions on sensitive files (such as certificate keys) to start up. Due to an on-going [issue](https://github.com/kubernetes/kubernetes/issues/57923) regarding kubernetes permissions and the use of `containerSecurityContext.runAsUser`, you must enable `volumePermissions` to ensure everything works as expected. + +### 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 primary +primary: + sidecars: + - name: your-image-name + image: your-image + imagePullPolicy: Always + ports: + - name: portname + containerPort: 1234 +# For the PostgreSQL replicas +readReplicas: + 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 + +```text + +--------------+ + | | + +------------+ 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: + +```text +postgresql.auth.username=testuser +subchart1.postgresql.auth.username=testuser +subchart2.postgresql.auth.username=testuser +postgresql.auth.password=testpass +subchart1.postgresql.auth.password=testpass +subchart2.postgresql.auth.password=testpass +postgresql.auth.database=testdb +subchart1.postgresql.auth.database=testdb +subchart2.postgresql.auth.database=testdb +``` + +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: + +```text +global.postgresql.auth.username=testuser +global.postgresql.auth.password=testpass +global.postgresql.auth.database=testdb +``` + +This way, the credentials will be available in all of the subcharts. + +### Backup and restore + +To back up and restore Bitnami PostgreSQL Helm chart deployments on Kubernetes, you need to back up the persistent volumes from the source deployment and attach them to a new deployment using [Velero](https://velero.io/), a Kubernetes backup/restore tool. + +These are the steps you will usually follow to back up and restore your PostgreSQL cluster data: + +- Install Velero on the source and destination clusters. +- Use Velero to back up the PersistentVolumes (PVs) used by the deployment on the source cluster. +- Use Velero to restore the backed-up PVs on the destination cluster. +- Create a new deployment on the destination cluster with the same chart, deployment name, credentials and other parameters as the original. This new deployment will use the restored PVs and hence the original data. + +Refer to our detailed [tutorial on backing up and restoring PostgreSQL deployments on Kubernetes](https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-migrate-data-tac-velero-index.html) for more information. + +### 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 up to 4.10, let set the volume permissions, security context, runAsUser and fsGroup automatically by OpenShift and disable the predefined settings of the helm chart: primary.securityContext.enabled=false,primary.containerSecurityContext.enabled=false,volumePermissions.enabled=false,shmVolume.enabled=false +- For OpenShift 4.11 and higher, let set OpenShift the runAsUser and fsGroup automatically. Configure the pod and container security context to restrictive defaults and disable the volume permissions setup: primary. + podSecurityContext.fsGroup=null,primary.podSecurityContext.seccompProfile.type=RuntimeDefault,primary.containerSecurityContext.runAsUser=null,primary.containerSecurityContext.allowPrivilegeEscalation=false,primary.containerSecurityContext.runAsNonRoot=true,primary.containerSecurityContext.seccompProfile.type=RuntimeDefault,primary.containerSecurityContext.capabilities.drop=['ALL'],volumePermissions.enabled=false,shmVolume.enabled=false + +### Setting Pod's affinity + +This chart allows you to set your custom affinity using the `XXX.affinity` parameter(s). Find more information about Pod's affinity in the [kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). + +As an alternative, you can use of the preset configurations for pod affinity, pod anti-affinity, and node affinity available at the [bitnami/common](https://github.com/bitnami/charts/tree/main/bitnami/common#affinities) chart. To do so, set the `XXX.podAffinityPreset`, `XXX.podAntiAffinityPreset`, or `XXX.nodeAffinityPreset` parameters. + +## Persistence + +The [Bitnami PostgreSQL](https://github.com/bitnami/containers/tree/main/bitnami/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 the [code present in the container repository](https://github.com/bitnami/containers/tree/main/bitnami/postgresql). If you need to use those data, please covert them to sql and import after `helm install` finished. + +## Parameters + +### Global parameters + +| Name | Description | Value | +| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `global.imageRegistry` | Global Docker image registry | `""` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | +| `global.defaultStorageClass` | Global default StorageClass for Persistent Volume(s) | `""` | +| `global.storageClass` | DEPRECATED: use global.defaultStorageClass instead | `""` | +| `global.security.allowInsecureImages` | Allows skipping image verification | `false` | +| `global.postgresql.fullnameOverride` | Full chart name (overrides `fullnameOverride`) | `""` | +| `global.postgresql.auth.postgresPassword` | Password for the "postgres" admin user (overrides `auth.postgresPassword`) | `""` | +| `global.postgresql.auth.username` | Name for a custom user to create (overrides `auth.username`) | `""` | +| `global.postgresql.auth.password` | Password for the custom user to create (overrides `auth.password`) | `""` | +| `global.postgresql.auth.database` | Name for a custom database to create (overrides `auth.database`) | `""` | +| `global.postgresql.auth.existingSecret` | Name of existing secret to use for PostgreSQL credentials (overrides `auth.existingSecret`). | `""` | +| `global.postgresql.auth.secretKeys.adminPasswordKey` | Name of key in existing secret to use for PostgreSQL credentials (overrides `auth.secretKeys.adminPasswordKey`). Only used when `global.postgresql.auth.existingSecret` is set. | `""` | +| `global.postgresql.auth.secretKeys.userPasswordKey` | Name of key in existing secret to use for PostgreSQL credentials (overrides `auth.secretKeys.userPasswordKey`). Only used when `global.postgresql.auth.existingSecret` is set. | `""` | +| `global.postgresql.auth.secretKeys.replicationPasswordKey` | Name of key in existing secret to use for PostgreSQL credentials (overrides `auth.secretKeys.replicationPasswordKey`). Only used when `global.postgresql.auth.existingSecret` is set. | `""` | +| `global.postgresql.service.ports.postgresql` | PostgreSQL service port (overrides `service.ports.postgresql`) | `""` | +| `global.compatibility.openshift.adaptSecurityContext` | Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) | `auto` | + +### Common parameters + +| Name | Description | Value | +| ------------------------ | -------------------------------------------------------------------------------------------- | --------------- | +| `kubeVersion` | Override Kubernetes version | `""` | +| `nameOverride` | String to partially override common.names.fullname template (will maintain the release name) | `""` | +| `fullnameOverride` | String to fully override common.names.fullname template | `""` | +| `namespaceOverride` | String to fully override common.names.namespace | `""` | +| `clusterDomain` | Kubernetes Cluster Domain | `cluster.local` | +| `extraDeploy` | Array of extra objects to deploy with the release (evaluated as a template) | `[]` | +| `commonLabels` | Add labels to all the deployed resources | `{}` | +| `commonAnnotations` | Add annotations to all the deployed resources | `{}` | +| `secretAnnotations` | Add annotations to the secrets | `{}` | +| `diagnosticMode.enabled` | Enable diagnostic mode (all probes will be disabled and the command will be overridden) | `false` | +| `diagnosticMode.command` | Command to override all containers in the statefulset | `["sleep"]` | +| `diagnosticMode.args` | Args to override all containers in the statefulset | `["infinity"]` | + +### PostgreSQL common parameters + +| Name | Description | Value | +| ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- | +| `image.registry` | PostgreSQL image registry | `REGISTRY_NAME` | +| `image.repository` | PostgreSQL image repository | `REPOSITORY_NAME/postgresql` | +| `image.digest` | PostgreSQL image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `image.pullPolicy` | PostgreSQL image pull policy | `IfNotPresent` | +| `image.pullSecrets` | Specify image pull secrets | `[]` | +| `image.debug` | Specify if debug values should be set | `false` | +| `auth.enablePostgresUser` | Assign a password to the "postgres" admin user. Otherwise, remote access will be blocked for this user | `true` | +| `auth.postgresPassword` | Password for the "postgres" admin user. Ignored if `auth.existingSecret` is provided | `""` | +| `auth.username` | Name for a custom user to create | `""` | +| `auth.password` | Password for the custom user to create. Ignored if `auth.existingSecret` is provided | `""` | +| `auth.database` | Name for a custom database to create | `""` | +| `auth.replicationUsername` | Name of the replication user | `repl_user` | +| `auth.replicationPassword` | Password for the replication user. Ignored if `auth.existingSecret` is provided | `""` | +| `auth.existingSecret` | Name of existing secret to use for PostgreSQL credentials. `auth.postgresPassword`, `auth.password`, and `auth.replicationPassword` will be ignored and picked up from this secret. The secret might also contains the key `ldap-password` if LDAP is enabled. `ldap.bind_password` will be ignored and picked from this secret in this case. | `""` | +| `auth.secretKeys.adminPasswordKey` | Name of key in existing secret to use for PostgreSQL credentials. Only used when `auth.existingSecret` is set. | `postgres-password` | +| `auth.secretKeys.userPasswordKey` | Name of key in existing secret to use for PostgreSQL credentials. Only used when `auth.existingSecret` is set. | `password` | +| `auth.secretKeys.replicationPasswordKey` | Name of key in existing secret to use for PostgreSQL credentials. Only used when `auth.existingSecret` is set. | `replication-password` | +| `auth.usePasswordFiles` | Mount credentials as a files instead of using an environment variable | `true` | +| `architecture` | PostgreSQL architecture (`standalone` or `replication`) | `standalone` | +| `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 `readReplicas.replicaCount`. | `0` | +| `replication.applicationName` | Cluster application name. Useful for advanced replication settings | `my_application` | +| `containerPorts.postgresql` | PostgreSQL container port | `5432` | +| `audit.logHostname` | Log client hostnames | `false` | +| `audit.logConnections` | Add client log-in operations to the log file | `false` | +| `audit.logDisconnections` | Add client log-outs operations to the log file | `false` | +| `audit.pgAuditLog` | Add operations to log using the pgAudit extension | `""` | +| `audit.pgAuditLogCatalog` | Log catalog using pgAudit | `off` | +| `audit.clientMinMessages` | Message log level to share with the user | `error` | +| `audit.logLinePrefix` | Template for log line prefix (default if not set) | `""` | +| `audit.logTimezone` | Timezone for the log timestamps | `""` | +| `ldap.enabled` | Enable LDAP support | `false` | +| `ldap.server` | IP address or name of the LDAP server. | `""` | +| `ldap.port` | Port number on the LDAP server to connect to | `""` | +| `ldap.prefix` | String to prepend to the user name when forming the DN to bind | `""` | +| `ldap.suffix` | String to append to the user name when forming the DN to bind | `""` | +| `ldap.basedn` | Root DN to begin the search for the user in | `""` | +| `ldap.binddn` | DN of user to bind to LDAP | `""` | +| `ldap.bindpw` | Password for the user to bind to LDAP | `""` | +| `ldap.searchAttribute` | Attribute to match against the user name in the search | `""` | +| `ldap.searchFilter` | The search filter to use when doing search+bind authentication | `""` | +| `ldap.scheme` | Set to `ldaps` to use LDAPS | `""` | +| `ldap.tls.enabled` | Se to true to enable TLS encryption | `false` | +| `ldap.uri` | LDAP URL beginning in the form `ldap[s]://host[:port]/basedn`. If provided, all the other LDAP parameters will be ignored. | `""` | +| `postgresqlDataDir` | PostgreSQL data dir folder | `/bitnami/postgresql/data` | +| `postgresqlSharedPreloadLibraries` | Shared preload libraries (comma-separated list) | `pgaudit` | +| `shmVolume.enabled` | Enable emptyDir volume for /dev/shm for PostgreSQL pod(s) | `true` | +| `shmVolume.sizeLimit` | Set this to enable a size limit on the shm tmpfs | `""` | +| `tls.enabled` | Enable TLS traffic support | `false` | +| `tls.autoGenerated` | Generate automatically self-signed TLS certificates | `false` | +| `tls.preferServerCiphers` | Whether to use the server's TLS cipher preferences rather than the client's | `true` | +| `tls.certificatesSecret` | Name of an existing secret that contains the certificates | `""` | +| `tls.certFilename` | Certificate filename | `""` | +| `tls.certKeyFilename` | Certificate key filename | `""` | +| `tls.certCAFilename` | CA Certificate filename | `""` | +| `tls.crlFilename` | File containing a Certificate Revocation List | `""` | + +### PostgreSQL Primary parameters + +| Name | Description | Value | +| ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- | +| `primary.name` | Name of the primary database (eg primary, master, leader, ...) | `primary` | +| `primary.configuration` | PostgreSQL Primary main configuration to be injected as ConfigMap | `""` | +| `primary.pgHbaConfiguration` | PostgreSQL Primary client authentication configuration | `""` | +| `primary.existingConfigmap` | Name of an existing ConfigMap with PostgreSQL Primary configuration | `""` | +| `primary.extendedConfiguration` | Extended PostgreSQL Primary configuration (appended to main or default configuration) | `""` | +| `primary.existingExtendedConfigmap` | Name of an existing ConfigMap with PostgreSQL Primary extended configuration | `""` | +| `primary.initdb.args` | PostgreSQL initdb extra arguments | `""` | +| `primary.initdb.postgresqlWalDir` | Specify a custom location for the PostgreSQL transaction log | `""` | +| `primary.initdb.scripts` | Dictionary of initdb scripts | `{}` | +| `primary.initdb.scriptsConfigMap` | ConfigMap with scripts to be run at first boot | `""` | +| `primary.initdb.scriptsSecret` | Secret with scripts to be run at first boot (in case it contains sensitive information) | `""` | +| `primary.initdb.user` | Specify the PostgreSQL username to execute the initdb scripts | `""` | +| `primary.initdb.password` | Specify the PostgreSQL password to execute the initdb scripts | `""` | +| `primary.preInitDb.scripts` | Dictionary of pre-init scripts | `{}` | +| `primary.preInitDb.scriptsConfigMap` | ConfigMap with pre-init scripts to be run | `""` | +| `primary.preInitDb.scriptsSecret` | Secret with pre-init scripts to be run | `""` | +| `primary.standby.enabled` | Whether to enable current cluster's primary as standby server of another cluster or not | `false` | +| `primary.standby.primaryHost` | The Host of replication primary in the other cluster | `""` | +| `primary.standby.primaryPort` | The Port of replication primary in the other cluster | `""` | +| `primary.extraEnvVars` | Array with extra environment variables to add to PostgreSQL Primary nodes | `[]` | +| `primary.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for PostgreSQL Primary nodes | `""` | +| `primary.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for PostgreSQL Primary nodes | `""` | +| `primary.command` | Override default container command (useful when using custom images) | `[]` | +| `primary.args` | Override default container args (useful when using custom images) | `[]` | +| `primary.livenessProbe.enabled` | Enable livenessProbe on PostgreSQL Primary containers | `true` | +| `primary.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `30` | +| `primary.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `primary.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `primary.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `primary.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `primary.readinessProbe.enabled` | Enable readinessProbe on PostgreSQL Primary containers | `true` | +| `primary.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `primary.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `primary.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` | +| `primary.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `primary.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `primary.startupProbe.enabled` | Enable startupProbe on PostgreSQL Primary containers | `false` | +| `primary.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `30` | +| `primary.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `primary.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `1` | +| `primary.startupProbe.failureThreshold` | Failure threshold for startupProbe | `15` | +| `primary.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `primary.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `primary.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `primary.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `primary.lifecycleHooks` | for the PostgreSQL Primary container to automate configuration before or after startup | `{}` | +| `primary.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if primary.resources is set (primary.resources is recommended for production). | `nano` | +| `primary.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `primary.podSecurityContext.enabled` | Enable security context | `true` | +| `primary.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `primary.podSecurityContext.sysctls` | Set kernel settings using the sysctl interface | `[]` | +| `primary.podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `primary.podSecurityContext.fsGroup` | Group ID for the pod | `1001` | +| `primary.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `primary.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `primary.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `primary.containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `primary.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `primary.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `primary.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `primary.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `primary.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `primary.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `primary.automountServiceAccountToken` | Mount Service Account token in pod | `false` | +| `primary.hostAliases` | PostgreSQL primary pods host aliases | `[]` | +| `primary.hostNetwork` | Specify if host network should be enabled for PostgreSQL pod (postgresql primary) | `false` | +| `primary.hostIPC` | Specify if host IPC should be enabled for PostgreSQL pod (postgresql primary) | `false` | +| `primary.labels` | Map of labels to add to the statefulset (postgresql primary) | `{}` | +| `primary.annotations` | Annotations for PostgreSQL primary pods | `{}` | +| `primary.podLabels` | Map of labels to add to the pods (postgresql primary) | `{}` | +| `primary.podAnnotations` | Map of annotations to add to the pods (postgresql primary) | `{}` | +| `primary.podAffinityPreset` | PostgreSQL primary pod affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `primary.podAntiAffinityPreset` | PostgreSQL primary pod anti-affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `primary.nodeAffinityPreset.type` | PostgreSQL primary node affinity preset type. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `primary.nodeAffinityPreset.key` | PostgreSQL primary node label key to match Ignored if `primary.affinity` is set. | `""` | +| `primary.nodeAffinityPreset.values` | PostgreSQL primary node label values to match. Ignored if `primary.affinity` is set. | `[]` | +| `primary.affinity` | Affinity for PostgreSQL primary pods assignment | `{}` | +| `primary.nodeSelector` | Node labels for PostgreSQL primary pods assignment | `{}` | +| `primary.tolerations` | Tolerations for PostgreSQL primary pods assignment | `[]` | +| `primary.topologySpreadConstraints` | Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template | `[]` | +| `primary.priorityClassName` | Priority Class to use for each pod (postgresql primary) | `""` | +| `primary.schedulerName` | Use an alternate scheduler, e.g. "stork". | `""` | +| `primary.terminationGracePeriodSeconds` | Seconds PostgreSQL primary pod needs to terminate gracefully | `""` | +| `primary.updateStrategy.type` | PostgreSQL Primary statefulset strategy type | `RollingUpdate` | +| `primary.updateStrategy.rollingUpdate` | PostgreSQL Primary statefulset rolling update configuration parameters | `{}` | +| `primary.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the PostgreSQL Primary container(s) | `[]` | +| `primary.extraVolumes` | Optionally specify extra list of additional volumes for the PostgreSQL Primary pod(s) | `[]` | +| `primary.sidecars` | Add additional sidecar containers to the PostgreSQL Primary pod(s) | `[]` | +| `primary.initContainers` | Add additional init containers to the PostgreSQL Primary pod(s) | `[]` | +| `primary.pdb.create` | Enable/disable a Pod Disruption Budget creation | `true` | +| `primary.pdb.minAvailable` | Minimum number/percentage of pods that should remain scheduled | `""` | +| `primary.pdb.maxUnavailable` | Maximum number/percentage of pods that may be made unavailable. Defaults to `1` if both `primary.pdb.minAvailable` and `primary.pdb.maxUnavailable` are empty. | `""` | +| `primary.extraPodSpec` | Optionally specify extra PodSpec for the PostgreSQL Primary pod(s) | `{}` | +| `primary.networkPolicy.enabled` | Specifies whether a NetworkPolicy should be created | `true` | +| `primary.networkPolicy.allowExternal` | Don't require server label for connections | `true` | +| `primary.networkPolicy.allowExternalEgress` | Allow the pod to access any range of port and all destinations. | `true` | +| `primary.networkPolicy.extraIngress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `primary.networkPolicy.extraEgress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `primary.networkPolicy.ingressNSMatchLabels` | Labels to match to allow traffic from other namespaces | `{}` | +| `primary.networkPolicy.ingressNSPodMatchLabels` | Pod labels to match to allow traffic from other namespaces | `{}` | +| `primary.service.type` | Kubernetes Service type | `ClusterIP` | +| `primary.service.ports.postgresql` | PostgreSQL service port | `5432` | +| `primary.service.nodePorts.postgresql` | Node port for PostgreSQL | `""` | +| `primary.service.clusterIP` | Static clusterIP or None for headless services | `""` | +| `primary.service.labels` | Map of labels to add to the primary service | `{}` | +| `primary.service.annotations` | Annotations for PostgreSQL primary service | `{}` | +| `primary.service.loadBalancerClass` | Load balancer class if service type is `LoadBalancer` | `""` | +| `primary.service.loadBalancerIP` | Load balancer IP if service type is `LoadBalancer` | `""` | +| `primary.service.externalTrafficPolicy` | Enable client source IP preservation | `Cluster` | +| `primary.service.loadBalancerSourceRanges` | Addresses that are allowed when service is LoadBalancer | `[]` | +| `primary.service.extraPorts` | Extra ports to expose in the PostgreSQL primary service | `[]` | +| `primary.service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` | +| `primary.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `primary.service.headless.annotations` | Additional custom annotations for headless PostgreSQL primary service | `{}` | +| `primary.persistence.enabled` | Enable PostgreSQL Primary data persistence using PVC | `true` | +| `primary.persistence.volumeName` | Name to assign the volume | `data` | +| `primary.persistence.existingClaim` | Name of an existing PVC to use | `""` | +| `primary.persistence.mountPath` | The path the volume will be mounted at | `/bitnami/postgresql` | +| `primary.persistence.subPath` | The subdirectory of the volume to mount to | `""` | +| `primary.persistence.storageClass` | PVC Storage Class for PostgreSQL Primary data volume | `""` | +| `primary.persistence.accessModes` | PVC Access Mode for PostgreSQL volume | `["ReadWriteOnce"]` | +| `primary.persistence.size` | PVC Storage Request for PostgreSQL volume | `8Gi` | +| `primary.persistence.annotations` | Annotations for the PVC | `{}` | +| `primary.persistence.labels` | Labels for the PVC | `{}` | +| `primary.persistence.selector` | Selector to match an existing Persistent Volume (this value is evaluated as a template) | `{}` | +| `primary.persistence.dataSource` | Custom PVC data source | `{}` | +| `primary.persistentVolumeClaimRetentionPolicy.enabled` | Enable Persistent volume retention policy for Primary Statefulset | `false` | +| `primary.persistentVolumeClaimRetentionPolicy.whenScaled` | Volume retention behavior when the replica count of the StatefulSet is reduced | `Retain` | +| `primary.persistentVolumeClaimRetentionPolicy.whenDeleted` | Volume retention behavior that applies when the StatefulSet is deleted | `Retain` | + +### PostgreSQL read only replica parameters (only used when `architecture` is set to `replication`) + +| Name | Description | Value | +| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- | +| `readReplicas.name` | Name of the read replicas database (eg secondary, slave, ...) | `read` | +| `readReplicas.replicaCount` | Number of PostgreSQL read only replicas | `1` | +| `readReplicas.extendedConfiguration` | Extended PostgreSQL read only replicas configuration (appended to main or default configuration) | `""` | +| `readReplicas.extraEnvVars` | Array with extra environment variables to add to PostgreSQL read only nodes | `[]` | +| `readReplicas.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for PostgreSQL read only nodes | `""` | +| `readReplicas.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for PostgreSQL read only nodes | `""` | +| `readReplicas.command` | Override default container command (useful when using custom images) | `[]` | +| `readReplicas.args` | Override default container args (useful when using custom images) | `[]` | +| `readReplicas.livenessProbe.enabled` | Enable livenessProbe on PostgreSQL read only containers | `true` | +| `readReplicas.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `30` | +| `readReplicas.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `readReplicas.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `readReplicas.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `readReplicas.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `readReplicas.readinessProbe.enabled` | Enable readinessProbe on PostgreSQL read only containers | `true` | +| `readReplicas.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `readReplicas.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `readReplicas.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` | +| `readReplicas.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `readReplicas.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `readReplicas.startupProbe.enabled` | Enable startupProbe on PostgreSQL read only containers | `false` | +| `readReplicas.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `30` | +| `readReplicas.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `readReplicas.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `1` | +| `readReplicas.startupProbe.failureThreshold` | Failure threshold for startupProbe | `15` | +| `readReplicas.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `readReplicas.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `readReplicas.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `readReplicas.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `readReplicas.lifecycleHooks` | for the PostgreSQL read only container to automate configuration before or after startup | `{}` | +| `readReplicas.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if readReplicas.resources is set (readReplicas.resources is recommended for production). | `nano` | +| `readReplicas.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `readReplicas.podSecurityContext.enabled` | Enable security context | `true` | +| `readReplicas.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `readReplicas.podSecurityContext.sysctls` | Set kernel settings using the sysctl interface | `[]` | +| `readReplicas.podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `readReplicas.podSecurityContext.fsGroup` | Group ID for the pod | `1001` | +| `readReplicas.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `readReplicas.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `readReplicas.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `readReplicas.containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `readReplicas.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `readReplicas.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `readReplicas.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `readReplicas.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `readReplicas.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `readReplicas.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `readReplicas.automountServiceAccountToken` | Mount Service Account token in pod | `false` | +| `readReplicas.hostAliases` | PostgreSQL read only pods host aliases | `[]` | +| `readReplicas.hostNetwork` | Specify if host network should be enabled for PostgreSQL pod (PostgreSQL read only) | `false` | +| `readReplicas.hostIPC` | Specify if host IPC should be enabled for PostgreSQL pod (postgresql primary) | `false` | +| `readReplicas.labels` | Map of labels to add to the statefulset (PostgreSQL read only) | `{}` | +| `readReplicas.annotations` | Annotations for PostgreSQL read only pods | `{}` | +| `readReplicas.podLabels` | Map of labels to add to the pods (PostgreSQL read only) | `{}` | +| `readReplicas.podAnnotations` | Map of annotations to add to the pods (PostgreSQL read only) | `{}` | +| `readReplicas.podAffinityPreset` | PostgreSQL read only pod affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `readReplicas.podAntiAffinityPreset` | PostgreSQL read only pod anti-affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `readReplicas.nodeAffinityPreset.type` | PostgreSQL read only node affinity preset type. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `readReplicas.nodeAffinityPreset.key` | PostgreSQL read only node label key to match Ignored if `primary.affinity` is set. | `""` | +| `readReplicas.nodeAffinityPreset.values` | PostgreSQL read only node label values to match. Ignored if `primary.affinity` is set. | `[]` | +| `readReplicas.affinity` | Affinity for PostgreSQL read only pods assignment | `{}` | +| `readReplicas.nodeSelector` | Node labels for PostgreSQL read only pods assignment | `{}` | +| `readReplicas.tolerations` | Tolerations for PostgreSQL read only pods assignment | `[]` | +| `readReplicas.topologySpreadConstraints` | Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template | `[]` | +| `readReplicas.priorityClassName` | Priority Class to use for each pod (PostgreSQL read only) | `""` | +| `readReplicas.schedulerName` | Use an alternate scheduler, e.g. "stork". | `""` | +| `readReplicas.terminationGracePeriodSeconds` | Seconds PostgreSQL read only pod needs to terminate gracefully | `""` | +| `readReplicas.updateStrategy.type` | PostgreSQL read only statefulset strategy type | `RollingUpdate` | +| `readReplicas.updateStrategy.rollingUpdate` | PostgreSQL read only statefulset rolling update configuration parameters | `{}` | +| `readReplicas.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the PostgreSQL read only container(s) | `[]` | +| `readReplicas.extraVolumes` | Optionally specify extra list of additional volumes for the PostgreSQL read only pod(s) | `[]` | +| `readReplicas.sidecars` | Add additional sidecar containers to the PostgreSQL read only pod(s) | `[]` | +| `readReplicas.initContainers` | Add additional init containers to the PostgreSQL read only pod(s) | `[]` | +| `readReplicas.pdb.create` | Enable/disable a Pod Disruption Budget creation | `true` | +| `readReplicas.pdb.minAvailable` | Minimum number/percentage of pods that should remain scheduled | `""` | +| `readReplicas.pdb.maxUnavailable` | Maximum number/percentage of pods that may be made unavailable. Defaults to `1` if both `readReplicas.pdb.minAvailable` and `readReplicas.pdb.maxUnavailable` are empty. | `""` | +| `readReplicas.extraPodSpec` | Optionally specify extra PodSpec for the PostgreSQL read only pod(s) | `{}` | +| `readReplicas.networkPolicy.enabled` | Specifies whether a NetworkPolicy should be created | `true` | +| `readReplicas.networkPolicy.allowExternal` | Don't require server label for connections | `true` | +| `readReplicas.networkPolicy.allowExternalEgress` | Allow the pod to access any range of port and all destinations. | `true` | +| `readReplicas.networkPolicy.extraIngress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `readReplicas.networkPolicy.extraEgress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `readReplicas.networkPolicy.ingressNSMatchLabels` | Labels to match to allow traffic from other namespaces | `{}` | +| `readReplicas.networkPolicy.ingressNSPodMatchLabels` | Pod labels to match to allow traffic from other namespaces | `{}` | +| `readReplicas.service.type` | Kubernetes Service type | `ClusterIP` | +| `readReplicas.service.ports.postgresql` | PostgreSQL service port | `5432` | +| `readReplicas.service.nodePorts.postgresql` | Node port for PostgreSQL | `""` | +| `readReplicas.service.clusterIP` | Static clusterIP or None for headless services | `""` | +| `readReplicas.service.labels` | Map of labels to add to the read service | `{}` | +| `readReplicas.service.annotations` | Annotations for PostgreSQL read only service | `{}` | +| `readReplicas.service.loadBalancerClass` | Load balancer class if service type is `LoadBalancer` | `""` | +| `readReplicas.service.loadBalancerIP` | Load balancer IP if service type is `LoadBalancer` | `""` | +| `readReplicas.service.externalTrafficPolicy` | Enable client source IP preservation | `Cluster` | +| `readReplicas.service.loadBalancerSourceRanges` | Addresses that are allowed when service is LoadBalancer | `[]` | +| `readReplicas.service.extraPorts` | Extra ports to expose in the PostgreSQL read only service | `[]` | +| `readReplicas.service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` | +| `readReplicas.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `readReplicas.service.headless.annotations` | Additional custom annotations for headless PostgreSQL read only service | `{}` | +| `readReplicas.persistence.enabled` | Enable PostgreSQL read only data persistence using PVC | `true` | +| `readReplicas.persistence.existingClaim` | Name of an existing PVC to use | `""` | +| `readReplicas.persistence.mountPath` | The path the volume will be mounted at | `/bitnami/postgresql` | +| `readReplicas.persistence.subPath` | The subdirectory of the volume to mount to | `""` | +| `readReplicas.persistence.storageClass` | PVC Storage Class for PostgreSQL read only data volume | `""` | +| `readReplicas.persistence.accessModes` | PVC Access Mode for PostgreSQL volume | `["ReadWriteOnce"]` | +| `readReplicas.persistence.size` | PVC Storage Request for PostgreSQL volume | `8Gi` | +| `readReplicas.persistence.annotations` | Annotations for the PVC | `{}` | +| `readReplicas.persistence.labels` | Labels for the PVC | `{}` | +| `readReplicas.persistence.selector` | Selector to match an existing Persistent Volume (this value is evaluated as a template) | `{}` | +| `readReplicas.persistence.dataSource` | Custom PVC data source | `{}` | +| `readReplicas.persistentVolumeClaimRetentionPolicy.enabled` | Enable Persistent volume retention policy for read only Statefulset | `false` | +| `readReplicas.persistentVolumeClaimRetentionPolicy.whenScaled` | Volume retention behavior when the replica count of the StatefulSet is reduced | `Retain` | +| `readReplicas.persistentVolumeClaimRetentionPolicy.whenDeleted` | Volume retention behavior that applies when the StatefulSet is deleted | `Retain` | + +### Backup parameters + +| Name | Description | Value | +| ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `backup.enabled` | Enable the logical dump of the database "regularly" | `false` | +| `backup.cronjob.schedule` | Set the cronjob parameter schedule | `@daily` | +| `backup.cronjob.timeZone` | Set the cronjob parameter timeZone | `""` | +| `backup.cronjob.concurrencyPolicy` | Set the cronjob parameter concurrencyPolicy | `Allow` | +| `backup.cronjob.failedJobsHistoryLimit` | Set the cronjob parameter failedJobsHistoryLimit | `1` | +| `backup.cronjob.successfulJobsHistoryLimit` | Set the cronjob parameter successfulJobsHistoryLimit | `3` | +| `backup.cronjob.startingDeadlineSeconds` | Set the cronjob parameter startingDeadlineSeconds | `""` | +| `backup.cronjob.ttlSecondsAfterFinished` | Set the cronjob parameter ttlSecondsAfterFinished | `""` | +| `backup.cronjob.restartPolicy` | Set the cronjob parameter restartPolicy | `OnFailure` | +| `backup.cronjob.podSecurityContext.enabled` | Enable PodSecurityContext for CronJob/Backup | `true` | +| `backup.cronjob.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `backup.cronjob.podSecurityContext.sysctls` | Set kernel settings using the sysctl interface | `[]` | +| `backup.cronjob.podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `backup.cronjob.podSecurityContext.fsGroup` | Group ID for the CronJob | `1001` | +| `backup.cronjob.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `backup.cronjob.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `backup.cronjob.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `backup.cronjob.containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `backup.cronjob.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `backup.cronjob.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `backup.cronjob.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `backup.cronjob.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `backup.cronjob.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `backup.cronjob.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `backup.cronjob.command` | Set backup container's command to run | `["/bin/bash","-c","PGPASSWORD=\"${PGPASSWORD:-$(< \"$PGPASSWORD_FILE\")}\" pg_dumpall --clean --if-exists --load-via-partition-root --quote-all-identifiers --no-password --file=\"${PGDUMP_DIR}/pg_dumpall-$(date '+%Y-%m-%d-%H-%M').pgdump\""]` | +| `backup.cronjob.labels` | Set the cronjob labels | `{}` | +| `backup.cronjob.annotations` | Set the cronjob annotations | `{}` | +| `backup.cronjob.nodeSelector` | Node labels for PostgreSQL backup CronJob pod assignment | `{}` | +| `backup.cronjob.tolerations` | Tolerations for PostgreSQL backup CronJob pods assignment | `[]` | +| `backup.cronjob.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if backup.cronjob.resources is set (backup.cronjob.resources is recommended for production). | `nano` | +| `backup.cronjob.resources` | Set container requests and limits for different resources like CPU or memory | `{}` | +| `backup.cronjob.networkPolicy.enabled` | Specifies whether a NetworkPolicy should be created | `true` | +| `backup.cronjob.storage.enabled` | Enable using a `PersistentVolumeClaim` as backup data volume | `true` | +| `backup.cronjob.storage.existingClaim` | Provide an existing `PersistentVolumeClaim` (only when `architecture=standalone`) | `""` | +| `backup.cronjob.storage.resourcePolicy` | Setting it to "keep" to avoid removing PVCs during a helm delete operation. Leaving it empty will delete PVCs after the chart deleted | `""` | +| `backup.cronjob.storage.storageClass` | PVC Storage Class for the backup data volume | `""` | +| `backup.cronjob.storage.accessModes` | PV Access Mode | `["ReadWriteOnce"]` | +| `backup.cronjob.storage.size` | PVC Storage Request for the backup data volume | `8Gi` | +| `backup.cronjob.storage.annotations` | PVC annotations | `{}` | +| `backup.cronjob.storage.mountPath` | Path to mount the volume at | `/backup/pgdump` | +| `backup.cronjob.storage.subPath` | Subdirectory of the volume to mount at | `""` | +| `backup.cronjob.storage.volumeClaimTemplates.selector` | A label query over volumes to consider for binding (e.g. when using local volumes) | `{}` | +| `backup.cronjob.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the backup container | `[]` | +| `backup.cronjob.extraVolumes` | Optionally specify extra list of additional volumes for the backup container | `[]` | + +### Password update job + +| Name | Description | Value | +| --------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | +| `passwordUpdateJob.enabled` | Enable password update job | `false` | +| `passwordUpdateJob.backoffLimit` | set backoff limit of the job | `10` | +| `passwordUpdateJob.command` | Override default container command on mysql Primary container(s) (useful when using custom images) | `[]` | +| `passwordUpdateJob.args` | Override default container args on mysql Primary container(s) (useful when using custom images) | `[]` | +| `passwordUpdateJob.extraCommands` | Extra commands to pass to the generation job | `""` | +| `passwordUpdateJob.previousPasswords.postgresPassword` | Previous postgres password (set if the password secret was already changed) | `""` | +| `passwordUpdateJob.previousPasswords.password` | Previous password (set if the password secret was already changed) | `""` | +| `passwordUpdateJob.previousPasswords.replicationPassword` | Previous replication password (set if the password secret was already changed) | `""` | +| `passwordUpdateJob.previousPasswords.existingSecret` | Name of a secret containing the previous passwords (set if the password secret was already changed) | `""` | +| `passwordUpdateJob.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `passwordUpdateJob.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `passwordUpdateJob.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `passwordUpdateJob.containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `passwordUpdateJob.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `passwordUpdateJob.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `passwordUpdateJob.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `passwordUpdateJob.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `passwordUpdateJob.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `passwordUpdateJob.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `passwordUpdateJob.podSecurityContext.enabled` | Enabled credential init job pods' Security Context | `true` | +| `passwordUpdateJob.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `passwordUpdateJob.podSecurityContext.sysctls` | Set kernel settings using the sysctl interface | `[]` | +| `passwordUpdateJob.podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `passwordUpdateJob.podSecurityContext.fsGroup` | Set credential init job pod's Security Context fsGroup | `1001` | +| `passwordUpdateJob.extraEnvVars` | Array containing extra env vars to configure the credential init job | `[]` | +| `passwordUpdateJob.extraEnvVarsCM` | ConfigMap containing extra env vars to configure the credential init job | `""` | +| `passwordUpdateJob.extraEnvVarsSecret` | Secret containing extra env vars to configure the credential init job (in case of sensitive data) | `""` | +| `passwordUpdateJob.extraVolumes` | Optionally specify extra list of additional volumes for the credential init job | `[]` | +| `passwordUpdateJob.extraVolumeMounts` | Array of extra volume mounts to be added to the jwt Container (evaluated as template). Normally used with `extraVolumes`. | `[]` | +| `passwordUpdateJob.initContainers` | Add additional init containers for the mysql Primary pod(s) | `[]` | +| `passwordUpdateJob.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if passwordUpdateJob.resources is set (passwordUpdateJob.resources is recommended for production). | `micro` | +| `passwordUpdateJob.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `passwordUpdateJob.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `passwordUpdateJob.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `passwordUpdateJob.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `passwordUpdateJob.automountServiceAccountToken` | Mount Service Account token in pod | `false` | +| `passwordUpdateJob.hostAliases` | Add deployment host aliases | `[]` | +| `passwordUpdateJob.annotations` | Add annotations to the job | `{}` | +| `passwordUpdateJob.podLabels` | Additional pod labels | `{}` | +| `passwordUpdateJob.podAnnotations` | Additional pod annotations | `{}` | + +### Volume Permissions parameters + +| Name | Description | Value | +| ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | +| `volumePermissions.enabled` | Enable init container that changes the owner and group of the persistent volume | `false` | +| `volumePermissions.image.registry` | Init container volume-permissions image registry | `REGISTRY_NAME` | +| `volumePermissions.image.repository` | Init container volume-permissions image repository | `REPOSITORY_NAME/os-shell` | +| `volumePermissions.image.digest` | Init container volume-permissions image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `volumePermissions.image.pullPolicy` | Init container volume-permissions image pull policy | `IfNotPresent` | +| `volumePermissions.image.pullSecrets` | Init container volume-permissions image pull secrets | `[]` | +| `volumePermissions.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if volumePermissions.resources is set (volumePermissions.resources is recommended for production). | `nano` | +| `volumePermissions.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `volumePermissions.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `volumePermissions.containerSecurityContext.runAsUser` | User ID for the init container | `0` | +| `volumePermissions.containerSecurityContext.runAsGroup` | Group ID for the init container | `0` | +| `volumePermissions.containerSecurityContext.runAsNonRoot` | runAsNonRoot for the init container | `false` | +| `volumePermissions.containerSecurityContext.seccompProfile.type` | seccompProfile.type for the init container | `RuntimeDefault` | + +### Other Parameters + +| Name | Description | Value | +| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `serviceBindings.enabled` | Create secret for service binding (Experimental) | `false` | +| `serviceAccount.create` | Enable creation of ServiceAccount for PostgreSQL pod | `true` | +| `serviceAccount.name` | The name of the ServiceAccount to use. | `""` | +| `serviceAccount.automountServiceAccountToken` | Allows auto mount of ServiceAccountToken on the serviceAccount created | `false` | +| `serviceAccount.annotations` | Additional custom annotations for the ServiceAccount | `{}` | +| `rbac.create` | Create Role and RoleBinding (required for PSP to work) | `false` | +| `rbac.rules` | Custom RBAC rules to set | `[]` | +| `psp.create` | Whether to create a PodSecurityPolicy. WARNING: PodSecurityPolicy is deprecated in Kubernetes v1.21 or later, unavailable in v1.25 or later | `false` | + +### Metrics Parameters + +| Name | Description | Value | +| ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | +| `metrics.enabled` | Start a prometheus exporter | `false` | +| `metrics.image.registry` | PostgreSQL Prometheus Exporter image registry | `REGISTRY_NAME` | +| `metrics.image.repository` | PostgreSQL Prometheus Exporter image repository | `REPOSITORY_NAME/postgres-exporter` | +| `metrics.image.digest` | PostgreSQL image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `metrics.image.pullPolicy` | PostgreSQL Prometheus Exporter image pull policy | `IfNotPresent` | +| `metrics.image.pullSecrets` | Specify image pull secrets | `[]` | +| `metrics.collectors` | Control enabled collectors | `{}` | +| `metrics.customMetrics` | Define additional custom metrics | `{}` | +| `metrics.extraEnvVars` | Extra environment variables to add to PostgreSQL Prometheus exporter | `[]` | +| `metrics.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `metrics.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `metrics.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `metrics.containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `metrics.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `metrics.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `metrics.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `metrics.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `metrics.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `metrics.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `metrics.livenessProbe.enabled` | Enable livenessProbe on PostgreSQL Prometheus exporter containers | `true` | +| `metrics.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `5` | +| `metrics.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `metrics.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `metrics.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `metrics.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `metrics.readinessProbe.enabled` | Enable readinessProbe on PostgreSQL Prometheus exporter containers | `true` | +| `metrics.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `metrics.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `metrics.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` | +| `metrics.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `metrics.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `metrics.startupProbe.enabled` | Enable startupProbe on PostgreSQL Prometheus exporter containers | `false` | +| `metrics.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `10` | +| `metrics.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `metrics.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `1` | +| `metrics.startupProbe.failureThreshold` | Failure threshold for startupProbe | `15` | +| `metrics.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `metrics.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `metrics.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `metrics.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `metrics.containerPorts.metrics` | PostgreSQL Prometheus exporter metrics container port | `9187` | +| `metrics.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if metrics.resources is set (metrics.resources is recommended for production). | `nano` | +| `metrics.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `metrics.service.ports.metrics` | PostgreSQL Prometheus Exporter service port | `9187` | +| `metrics.service.clusterIP` | Static clusterIP or None for headless services | `""` | +| `metrics.service.sessionAffinity` | Control where client requests go, to the same pod or round-robin | `None` | +| `metrics.service.annotations` | Annotations for Prometheus to auto-discover the metrics endpoint | `{}` | +| `metrics.serviceMonitor.enabled` | Create ServiceMonitor Resource for scraping metrics using Prometheus Operator | `false` | +| `metrics.serviceMonitor.namespace` | Namespace for the ServiceMonitor Resource (defaults to the Release Namespace) | `""` | +| `metrics.serviceMonitor.interval` | Interval at which metrics should be scraped. | `""` | +| `metrics.serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended | `""` | +| `metrics.serviceMonitor.labels` | Additional labels that can be used so ServiceMonitor will be discovered by Prometheus | `{}` | +| `metrics.serviceMonitor.selector` | Prometheus instance selector labels | `{}` | +| `metrics.serviceMonitor.relabelings` | RelabelConfigs to apply to samples before scraping | `[]` | +| `metrics.serviceMonitor.metricRelabelings` | MetricRelabelConfigs to apply to samples before ingestion | `[]` | +| `metrics.serviceMonitor.honorLabels` | Specify honorLabels parameter to add the scrape endpoint | `false` | +| `metrics.serviceMonitor.jobLabel` | The name of the label on the target service to use as the job name in prometheus. | `""` | +| `metrics.prometheusRule.enabled` | Create a PrometheusRule for Prometheus Operator | `false` | +| `metrics.prometheusRule.namespace` | Namespace for the PrometheusRule Resource (defaults to the Release Namespace) | `""` | +| `metrics.prometheusRule.labels` | Additional labels that can be used so PrometheusRule will be discovered by Prometheus | `{}` | +| `metrics.prometheusRule.rules` | PrometheusRule definitions | `[]` | + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +helm install my-release \ + --set auth.postgresPassword=secretpassword + oci://REGISTRY_NAME/REPOSITORY_NAME/postgresql +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The above command sets the PostgreSQL `postgres` account password to `secretpassword`. + +> NOTE: Once this chart is deployed, it is not possible to change the application's access credentials, such as usernames or passwords, using Helm. To change these application credentials after deployment, delete any persistent volumes (PVs) used by the chart and re-deploy it, or use the application's built-in administrative tools if available. +> **Warning** Setting a password will be ignored on new installation in case when previous PostgreSQL release was deleted through the helm command. In that case, old PVC will have an old password, and setting it through helm won't take effect. Deleting persistent volumes (PVs) will solve the issue. Refer to [issue 2061](https://github.com/bitnami/charts/issues/2061) for more details + +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 oci://REGISTRY_NAME/REPOSITORY_NAME/postgresql +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> **Tip**: You can use the default [values.yaml](https://github.com/bitnami/charts/tree/main/bitnami/postgresql/values.yaml) + +## Troubleshooting + +Find more information about how to deal with common errors related to Bitnami's Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues). + +## Upgrading + +### To 16.3.0 + +This version introduces image verification for security purposes. To disable it, set `global.security.allowInsecureImages` to `true`. More details at [GitHub issue](https://github.com/bitnami/charts/issues/30850). + +### To 15.0.0 + +This major bump changes the following security defaults: + +- `runAsGroup` is changed from `0` to `1001` +- `readOnlyRootFilesystem` is set to `true` +- `resourcesPreset` is changed from `none` to the minimum size working in our test suites (NOTE: `resourcesPreset` is not meant for production usage, but `resources` adapted to your use case). +- `global.compatibility.openshift.adaptSecurityContext` is changed from `disabled` to `auto`. + +This could potentially break any customization or init scripts used in your deployment. If this is the case, change the default values to the previous ones. + +### To 14.0.0 + +This major version adapts the NetworkPolicy objects to the most recent Bitnami standards. Now there is a separate object for `primary` and for `readReplicas`, being located in their corresponding sections. It is also enabled by default in other to comply with the best security standards. + +Check the parameter section for the new value structure. + +### To 13.0.0 + +This major version changes the default PostgreSQL image from 15.x to 16.x. Follow the [official instructions](https://www.postgresql.org/docs/16/upgrading.html) to upgrade to 16.x. + +### To 12.0.0 + +This major version changes the default PostgreSQL image from 14.x to 15.x. Follow the [official instructions](https://www.postgresql.org/docs/15/upgrading.html) to upgrade to 15.x. + +### To 11.0.0 + +In this version the application version was bumped to _14.x_ series. Also, this major release renames several values in this chart and adds missing features, in order to be inline with the rest of assets in the Bitnami charts repository. + +- _replication.enabled_ parameter is deprecated in favor of _architecture_ parameter that accepts two values: _standalone_ and _replication_. +- _replication.singleService_ and _replication.uniqueServices_ parameters are deprecated. When using replication, each statefulset (primary and read-only) has its own headless service & service allowing to connect to read-only replicas through the service (round-robin) or individually. +- _postgresqlPostgresPassword_, _postgresqlUsername_, _postgresqlPassword_, _postgresqlDatabase_, _replication.user_, _replication.password_, and _existingSecret_ parameters have been regrouped under the _auth_ map. The _auth_ map uses a new perspective to configure authentication, so please read carefully each sub-parameter description. +- _extraEnv_ has been deprecated in favor of _primary.extraEnvVars_ and _readReplicas.extraEnvVars_. +- _postgresqlConfiguration_, _pgHbaConfiguration_, _configurationConfigMap_, _postgresqlExtendedConf_, and _extendedConfConfigMap_ have been deprecated in favor of _primary.configuration_, _primary.pgHbaConfiguration_, _primary.existingConfigmap_, _primary.extendedConfiguration_, and _primary.existingExtendedConfigmap_. +- _postgresqlInitdbArgs_, _postgresqlInitdbWalDir_, _initdbScripts_, _initdbScriptsConfigMap_, _initdbScriptsSecret_, _initdbUser_ and _initdbPassword_ have been regrouped under the _primary.initdb_ map. +- _postgresqlMaxConnections_, _postgresqlPostgresConnectionLimit_, _postgresqlDbUserConnectionLimit_, _postgresqlTcpKeepalivesInterval_, _postgresqlTcpKeepalivesIdle_, _postgresqlTcpKeepalivesCount_, _postgresqlStatementTimeout_ and _postgresqlPghbaRemoveFilters_ parameters are deprecated. Use _XXX.extraEnvVars_ instead. +- _primaryAsStandBy_ has been deprecated in favor of _primary.standby_. +- _securityContext_ and _containerSecurityContext_ have been deprecated in favor of _primary.podSecurityContext_, _primary.containerSecurityContext_, _readReplicas.podSecurityContext_, and _readReplicas.containerSecurityContext_. +- _livenessProbe_ and _readinessProbe_ maps have been deprecated in favor of _primary.livenessProbe_, _primary.readinessProbe_, _readReplicas.livenessProbe_ and _readReplicas.readinessProbe_ maps. +- _persistence_ map has been deprecated in favor of _primary.persistence_ and _readReplicas.persistence_ maps. +- _networkPolicy_ map has been completely refactored. +- _service_ map has been deprecated in favor of _primary.service_ and _readReplicas.service_ maps. +- _metrics.service.port_ has been regrouped under the _metrics.service.ports_ map. +- _serviceAccount.enabled_ and _serviceAccount.autoMount_ have been deprecated in favor of _serviceAccount.create_ and _serviceAccount.automountServiceAccountToken_. + +#### How to upgrade to version 11.0.0 + +To upgrade to _11.0.0_ from _10.x_, it should be done reusing the PVC(s) used to hold the PostgreSQL data on your previous release. To do so, follow the instructions below (the following example assumes that the release name is _postgresql_): + +> NOTE: Please, create a backup of your database before running any of these actions. + +1. Obtain the credentials and the names of the PVCs used to hold the PostgreSQL data on your current release: + +```console +export POSTGRESQL_PASSWORD=$(kubectl get secret --namespace default postgresql -o jsonpath="{.data.postgresql-password}" | base64 --decode) +export POSTGRESQL_PVC=$(kubectl get pvc -l app.kubernetes.io/instance=postgresql,role=primary -o jsonpath="{.items[0].metadata.name}") +``` + +1. Delete the PostgreSQL statefulset (notice the option _--cascade=false_) and secret: + +```console +kubectl delete statefulsets.apps postgresql-postgresql --namespace default --cascade=false +kubectl delete secret postgresql --namespace default +``` + +1. Upgrade your release using the same PostgreSQL version: + +```console +CURRENT_VERSION=$(kubectl exec postgresql-postgresql-0 -- bash -c 'echo $BITNAMI_IMAGE_VERSION') +helm upgrade postgresql bitnami/postgresql \ + --set auth.postgresPassword=$POSTGRESQL_PASSWORD \ + --set primary.persistence.existingClaim=$POSTGRESQL_PVC \ + --set image.tag=$CURRENT_VERSION +``` + +1. You will have to delete the existing PostgreSQL pod and the new statefulset is going to create a new one + +```console +kubectl delete pod postgresql-postgresql-0 +``` + +1. Finally, you should see the lines below in PostgreSQL container logs: + +```text +$ kubectl logs $(kubectl get pods -l app.kubernetes.io/instance=postgresql,app.kubernetes.io/name=postgresql,app.kubernetes.io/component=primary -o jsonpath="{.items[0].metadata.name}") +... +postgresql 08:05:12.59 INFO ==> Deploying PostgreSQL with persisted data... +... +``` + +> NOTE: the instructions above reuse the same PostgreSQL version you were using in your chart release. Otherwise, you will find an error such as the one below when upgrading since the new chart major version also bumps the application version. To workaround this issue you need to upgrade database, please refer to the [official PostgreSQL documentation](https://www.postgresql.org/docs/current/upgrading.html) for more information about this. + +```console +$ kubectl logs $(kubectl get pods -l app.kubernetes.io/instance=postgresql,app.kubernetes.io/name=postgresql,app.kubernetes.io/component=primary -o jsonpath="{.items[0].metadata.name}") + ... +postgresql 08:10:14.72 INFO ==> ** Starting PostgreSQL ** +2022-02-01 08:10:14.734 GMT [1] FATAL: database files are incompatible with server +2022-02-01 08:10:14.734 GMT [1] DETAIL: The data directory was initialized by PostgreSQL version 11, which is not compatible with this version 14.1. +``` + +### To 10.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- Move dependency information from the _requirements.yaml_ to the _Chart.yaml_ +- After running _helm dependency update_, a _Chart.lock_ file is generated containing the same structure used in the previous _requirements.lock_ +- The different fields present in the _Chart.yaml_ file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Chart. +- The term _master_ has been replaced with _primary_ and _slave_ with _readReplicas_ throughout the chart. Role names have changed from _master_ and _slave_ to _primary_ and _read_. + +#### Considerations when upgrading to this version + +- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version does not support Helm v2 anymore. +- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3. + +#### Useful links + +- [Bitnami Tutorial](https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-resolve-helm2-helm3-post-migration-issues-index.html) +- [Helm docs](https://helm.sh/docs/topics/v2_v3_migration) +- [Helm Blog](https://helm.sh/blog/migrate-from-helm-v2-to-helm-v3) + +#### How to upgrade to version 10.0.0 + +To upgrade to _10.0.0_ from _9.x_, it should be done reusing the PVC(s) used to hold the PostgreSQL data on your previous release. To do so, follow the instructions below (the following example assumes that the release name is _postgresql_): + +> NOTE: Please, create a backup of your database before running any of those actions. + +1. Obtain the credentials and the names of the PVCs used to hold the PostgreSQL data on your current release: + +```console +export POSTGRESQL_PASSWORD=$(kubectl get secret --namespace default postgresql -o jsonpath="{.data.postgresql-password}" | base64 --decode) +export POSTGRESQL_PVC=$(kubectl get pvc -l app.kubernetes.io/instance=postgresql,role=primary -o jsonpath="{.items[0].metadata.name}") +``` + +1. Delete the PostgreSQL statefulset (notice the option _--cascade=false_): + +```console +kubectl delete statefulsets.apps postgresql-postgresql --namespace default --cascade=false +``` + +1. Upgrade your release using the same PostgreSQL version: + +```console +helm upgrade postgresql bitnami/postgresql \ + --set postgresqlPassword=$POSTGRESQL_PASSWORD \ + --set persistence.existingClaim=$POSTGRESQL_PVC +``` + +1. Delete the existing PostgreSQL pod and the new statefulset will create a new one: + +```console +kubectl delete pod postgresql-postgresql-0 +``` + +1. Finally, you should see the lines below in PostgreSQL container logs: + +```text +$ kubectl logs $(kubectl get pods -l app.kubernetes.io/instance=postgresql,app.kubernetes.io/name=postgresql,role=primary -o jsonpath="{.items[0].metadata.name}") +... +postgresql 08:05:12.59 INFO ==> Deploying PostgreSQL with persisted data... +... +``` + +### To 9.0.0 + +In this version the chart was adapted to follow the [Helm standard labels](https://helm.sh/docs/chart_best_practices/labels/#standard-labels). + +- Some inmutable objects were modified to adopt Helm standard labels introducing backward incompatibilities. + +#### How to upgrade to version 9.0.0 + +To upgrade to _9.0.0_ from _8.x_, it should be done reusing the PVC(s) used to hold the PostgreSQL data on your previous release. To do so, follow the instructions below (the following example assumes that the release name is _postgresql_): + +> NOTE: Please, create a backup of your database before running any of those actions. + +1. Obtain the credentials and the names of the PVCs used to hold the PostgreSQL data on your current release: + +```console +export POSTGRESQL_PASSWORD=$(kubectl get secret --namespace default postgresql -o jsonpath="{.data.postgresql-password}" | base64 --decode) +export POSTGRESQL_PVC=$(kubectl get pvc -l app=postgresql,role=master -o jsonpath="{.items[0].metadata.name}") +``` + +1. Delete the PostgreSQL statefulset (notice the option _--cascade=false_): + +```console +kubectl delete statefulsets.apps postgresql-postgresql --namespace default --cascade=false +``` + +1. Upgrade your release using the same PostgreSQL version: + +```console +helm upgrade postgresql bitnami/postgresql \ + --set postgresqlPassword=$POSTGRESQL_PASSWORD \ + --set persistence.existingClaim=$POSTGRESQL_PVC +``` + +1. Delete the existing PostgreSQL pod and the new statefulset will create a new one: + +```console +kubectl delete pod postgresql-postgresql-0 +``` + +1. Finally, you should see the lines below in PostgreSQL container logs: + +```text +$ kubectl logs $(kubectl get pods -l app.kubernetes.io/instance=postgresql,app.kubernetes.io/name=postgresql,role=master -o jsonpath="{.items[0].metadata.name}") +... +postgresql 08:05:12.59 INFO ==> Deploying PostgreSQL with persisted data... +... +``` + +## License + +Copyright © 2025 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/backing-services/gitea/charts/postgresql/charts/common/.helmignore b/backing-services/gitea/charts/postgresql/charts/common/.helmignore new file mode 100644 index 0000000..d0e1084 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/.helmignore @@ -0,0 +1,26 @@ +# 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 +.vscode/ +# img folder +img/ +# Changelog +CHANGELOG.md diff --git a/backing-services/gitea/charts/postgresql/charts/common/Chart.yaml b/backing-services/gitea/charts/postgresql/charts/common/Chart.yaml new file mode 100644 index 0000000..fb04f76 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/Chart.yaml @@ -0,0 +1,23 @@ +annotations: + category: Infrastructure + licenses: Apache-2.0 +apiVersion: v2 +appVersion: 2.31.4 +description: A Library Helm Chart for grouping common logic between bitnami charts. + This chart is not deployable by itself. +home: https://bitnami.com +icon: https://dyltqmyl993wv.cloudfront.net/downloads/logos/bitnami-mark.png +keywords: +- common +- helper +- template +- function +- bitnami +maintainers: +- name: Broadcom, Inc. All Rights Reserved. + url: https://github.com/bitnami/charts +name: common +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/common +type: library +version: 2.31.4 diff --git a/backing-services/gitea/charts/postgresql/charts/common/README.md b/backing-services/gitea/charts/postgresql/charts/common/README.md new file mode 100644 index 0000000..71368aa --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/README.md @@ -0,0 +1,387 @@ +# Bitnami Common Library Chart + +A [Helm Library Chart](https://helm.sh/docs/topics/library_charts/#helm) for grouping common logic between Bitnami charts. + +## TL;DR + +```yaml +dependencies: + - name: common + version: 2.x.x + repository: oci://registry-1.docker.io/bitnamicharts +``` + +```console +helm dependency update +``` + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "common.names.fullname" . }} +data: + myvalue: "Hello World" +``` + +Looking to use our applications in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the commercial edition of the Bitnami catalog. + +## ⚠️ Important Notice: Upcoming changes to the Bitnami Catalog + +Beginning August 28th, 2025, Bitnami will evolve its public catalog to offer a curated set of hardened, security-focused images under the new [Bitnami Secure Images initiative](https://news.broadcom.com/app-dev/broadcom-introduces-bitnami-secure-images-for-production-ready-containerized-applications). As part of this transition: + +- Granting community users access for the first time to security-optimized versions of popular container images. +- Bitnami will begin deprecating support for non-hardened, Debian-based software images in its free tier and will gradually remove non-latest tags from the public catalog. As a result, community users will have access to a reduced number of hardened images. These images are published only under the “latest” tag and are intended for development purposes +- Starting August 28th, over two weeks, all existing container images, including older or versioned tags (e.g., 2.50.0, 10.6), will be migrated from the public catalog (docker.io/bitnami) to the “Bitnami Legacy” repository (docker.io/bitnamilegacy), where they will no longer receive updates. +- For production workloads and long-term support, users are encouraged to adopt Bitnami Secure Images, which include hardened containers, smaller attack surfaces, CVE transparency (via VEX/KEV), SBOMs, and enterprise support. + +These changes aim to improve the security posture of all Bitnami users by promoting best practices for software supply chain integrity and up-to-date deployments. For more details, visit the [Bitnami Secure Images announcement](https://github.com/bitnami/containers/issues/83267). + +## Introduction + +This chart provides a common template helpers which can be used to develop new charts using [Helm](https://helm.sh) package manager. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ + +## Parameters + +The following table lists the helpers available in the library which are scoped in different sections. + +### Affinities + +| Helper identifier | Description | Expected Input | +| ------------------------------- | ---------------------------------------------------- | ------------------------------------------------------------ | +| `common.affinities.nodes.soft` | Return a soft nodeAffinity definition | `dict "key" "FOO" "values" (list "BAR" "BAZ")` | +| `common.affinities.nodes.hard` | Return a hard nodeAffinity definition | `dict "key" "FOO" "values" (list "BAR" "BAZ")` | +| `common.affinities.nodes` | Return a nodeAffinity definition | `dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")` | +| `common.affinities.topologyKey` | Return a topologyKey definition | `dict "topologyKey" "FOO"` | +| `common.affinities.pods.soft` | Return a soft podAffinity/podAntiAffinity definition | `dict "component" "FOO" "context" $` | +| `common.affinities.pods.hard` | Return a hard podAffinity/podAntiAffinity definition | `dict "component" "FOO" "context" $` | +| `common.affinities.pods` | Return a podAffinity/podAntiAffinity definition | `dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")` | + +### Capabilities + +| Helper identifier | Description | Expected Input | +| --------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------- | +| `common.capabilities.kubeVersion` | Return the target Kubernetes version (using client default if .Values.kubeVersion is not set). | `.` Chart context | +| `common.capabilities.apiVersions.has` | Return true if the apiVersion is supported | `dict "version" "batch/v1" "context" $` | +| `common.capabilities.job.apiVersion` | Return the appropriate apiVersion for job. | `.` Chart context | +| `common.capabilities.cronjob.apiVersion` | Return the appropriate apiVersion for cronjob. | `.` Chart context | +| `common.capabilities.daemonset.apiVersion` | Return the appropriate apiVersion for daemonset. | `.` Chart context | +| `common.capabilities.deployment.apiVersion` | Return the appropriate apiVersion for deployment. | `.` Chart context | +| `common.capabilities.statefulset.apiVersion` | Return the appropriate apiVersion for statefulset. | `.` Chart context | +| `common.capabilities.ingress.apiVersion` | Return the appropriate apiVersion for ingress. | `.` Chart context | +| `common.capabilities.rbac.apiVersion` | Return the appropriate apiVersion for RBAC resources. | `.` Chart context | +| `common.capabilities.crd.apiVersion` | Return the appropriate apiVersion for CRDs. | `.` Chart context | +| `common.capabilities.policy.apiVersion` | Return the appropriate apiVersion for podsecuritypolicy. | `.` Chart context | +| `common.capabilities.networkPolicy.apiVersion` | Return the appropriate apiVersion for networkpolicy. | `.` Chart context | +| `common.capabilities.apiService.apiVersion` | Return the appropriate apiVersion for APIService. | `.` Chart context | +| `common.capabilities.hpa.apiVersion` | Return the appropriate apiVersion for Horizontal Pod Autoscaler | `.` Chart context | +| `common.capabilities.vpa.apiVersion` | Return the appropriate apiVersion for Vertical Pod Autoscaler. | `.` Chart context | +| `common.capabilities.psp.supported` | Returns true if PodSecurityPolicy is supported | `.` Chart context | +| `common.capabilities.supportsHelmVersion` | Returns true if the used Helm version is 3.3+ | `.` Chart context | +| `common.capabilities.admissionConfiguration.supported` | Returns true if AdmissionConfiguration is supported | `.` Chart context | +| `common.capabilities.admissionConfiguration.apiVersion` | Return the appropriate apiVersion for AdmissionConfiguration. | `.` Chart context | +| `common.capabilities.podSecurityConfiguration.apiVersion` | Return the appropriate apiVersion for PodSecurityConfiguration. | `.` Chart context | + +### Compatibility + +| Helper identifier | Description | Expected Input | +| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | +| `common.compatibility.isOpenshift` | Return true if the detected platform is Openshift | `.` Chart context | +| `common.compatibility.renderSecurityContext` | Render a compatible securityContext depending on the platform. By default it is maintained as it is. In other platforms like Openshift we remove default user/group values that do not work out of the box with the restricted-v1 SCC | `dict "secContext" .Values.containerSecurityContext "context" $` | + +### Errors + +| Helper identifier | Description | Expected Input | +| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | +| `common.errors.upgrade.passwords.empty` | It will ensure required passwords are given when we are upgrading a chart. If `validationErrors` is not empty it will throw an error and will stop the upgrade action. | `dict "validationErrors" (list $validationError00 $validationError01) "context" $` | +| `common.errors.insecureImages` | Throw error when original container images are replaced. The error can be bypassed by setting the `global.security.allowInsecureImages` to true. | `dict "images" (list .Values.path.to.the.imageRoot) "context" $` | + +### Images + +| Helper identifier | Description | Expected Input | +| --------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | +| `common.images.image` | Return the proper and full image name | `dict "imageRoot" .Values.path.to.the.image "global" $`, see [ImageRoot](#imageroot) for the structure. | +| `common.images.pullSecrets` | Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead) | `dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global` | +| `common.images.renderPullSecrets` | Return the proper Docker Image Registry Secret Names (evaluates values as templates) | `dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $` | +| `common.images.version` | Return the proper image version | `dict "imageRoot" .Values.path.to.the.image "chart" .Chart` , see [ImageRoot](#imageroot) for the structure. | + +### Ingress + +| Helper identifier | Description | Expected Input | +| ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `common.ingress.backend` | Generate a proper Ingress backend entry depending on the API version | `dict "serviceName" "foo" "servicePort" "bar"`, see the [Ingress deprecation notice](https://kubernetes.io/blog/2019/07/18/api-deprecations-in-1-16/) for the syntax differences | +| `common.ingress.certManagerRequest` | Prints "true" if required cert-manager annotations for TLS signed certificates are set in the Ingress annotations | `dict "annotations" .Values.path.to.the.ingress.annotations` | + +### Labels + +| Helper identifier | Description | Expected Input | +| --------------------------- | --------------------------------------------------------------------------- | ----------------- | +| `common.labels.standard` | Return Kubernetes standard labels | `.` Chart context | +| `common.labels.matchLabels` | Labels to use on `deploy.spec.selector.matchLabels` and `svc.spec.selector` | `.` Chart context | + +### Names + +| Helper identifier | Description | Expected Input | +| ---------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | +| `common.names.name` | Expand the name of the chart or use `.Values.nameOverride` | `.` Chart context | +| `common.names.fullname` | Create a default fully qualified app name. | `.` Chart context | +| `common.names.namespace` | Allow the release namespace to be overridden | `.` Chart context | +| `common.names.fullname.namespace` | Create a fully qualified app name adding the installation's namespace | `.` Chart context | +| `common.names.chart` | Chart name plus version | `.` Chart context | +| `common.names.dependency.fullname` | Create a default fully qualified dependency name. | `dict "chartName" "dependency-chart-name" "chartValues" .Values.dependency-chart "context" $` | + +### Resources + +| Helper identifier | Description | Expected Input | +| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | +| `common.resources.preset` | Return a resource request/limit object based on a given preset. These presets are for basic testing and not meant to be used in production. | `dict "type" "nano"` | + +### Secrets + +| Helper identifier | Description | Expected Input | +| --------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `common.secrets.name` | Generate the name of the secret. | `dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $` see [ExistingSecret](#existingsecret) for the structure. | +| `common.secrets.key` | Generate secret key. | `dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName"` see [ExistingSecret](#existingsecret) for the structure. | +| `common.secrets.passwords.manage` | Generate secret password or retrieve one if already created. | `dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "honorProvidedValues" false "context" $`, length, strong, honorProvidedValues and chartName fields are optional. | +| `common.secrets.exists` | Returns whether a previous generated secret already exists. | `dict "secret" "secret-name" "context" $` | +| `common.secrets.lookup` | Reuses the value from an existing secret, otherwise sets its value to a default value. | `dict "secret" "secret-name" "key" "keyName" "defaultValue" .Values.myValue "context" $` | + +### Storage + +| Helper identifier | Description | Expected Input | +| ---------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------- | +| `common.storage.class` | Return the proper Storage Class | `dict "persistence" .Values.path.to.the.persistence "global" $`, see [Persistence](#persistence) for the structure. | + +### TplValues + +| Helper identifier | Description | Expected Input | +| ---------------------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `common.tplvalues.render` | Renders a value that contains template | `dict "value" .Values.path.to.the.Value "context" $`, value is the value should rendered as template, context frequently is the chart context `$` or `.` | +| `common.tplvalues.merge` | Merge a list of values that contains template after rendering them. | `dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $` | +| `common.tplvalues.merge-overwrite` | Merge a list of values that contains template after rendering them. | `dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $` | + +### Utils + +| Helper identifier | Description | Expected Input | +| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | +| `common.utils.fieldToEnvVar` | Build environment variable name given a field. | `dict "field" "my-password"` | +| `common.utils.secret.getvalue` | Print instructions to get a secret value. | `dict "secret" "secret-name" "field" "secret-value-field" "context" $` | +| `common.utils.getValueFromKey` | Gets a value from `.Values` object given its key path | `dict "key" "path.to.key" "context" $` | +| `common.utils.getKeyFromList` | Returns first `.Values` key with a defined value or first of the list if all non-defined | `dict "keys" (list "path.to.key1" "path.to.key2") "context" $` | +| `common.utils.checksumTemplate` | Checksum a template at "path" containing a *single* resource (ConfigMap,Secret) for use in pod annotations, excluding the metadata (see #18376) | `dict "path" "/configmap.yaml" "context" $` | + +### Validations + +| Helper identifier | Description | Expected Input | +| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `common.validations.values.single.empty` | Validate a value must not be empty. | `dict "valueKey" "path.to.value" "secret" "secret.name" "field" "my-password" "subchart" "subchart" "context" $` secret, field and subchart are optional. In case they are given, the helper will generate a how to get instruction. See [ValidateValue](#validatevalue) | +| `common.validations.values.multiple.empty` | Validate a multiple values must not be empty. It returns a shared error for all the values. | `dict "required" (list $validateValueConf00 $validateValueConf01) "context" $`. See [ValidateValue](#validatevalue) | +| `common.validations.values.mariadb.passwords` | This helper will ensure required password for MariaDB are not empty. It returns a shared error for all the values. | `dict "secret" "mariadb-secret" "subchart" "true" "context" $` subchart field is optional and could be true or false it depends on where you will use mariadb chart and the helper. | + +### Warnings + +| Helper identifier | Description | Expected Input | +| -------------------------------- | ----------------------------------------------------------------- | ---------------------------------------------------------- | +| `common.warnings.rollingTag` | Warning about using rolling tag. | `ImageRoot` see [ImageRoot](#imageroot) for the structure. | +| `common.warnings.modifiedImages` | Warning about replaced images from the original. | `ImageRoot` see [ImageRoot](#imageroot) for the structure. | +| `common.warnings.resources` | Warning about not setting the resource object in all deployments. | `dict "sections" (list "path1" "path2") context $` | + +## Special input schemas + +### ImageRoot + +```yaml +registry: + type: string + description: Docker registry where the image is located + example: docker.io + +repository: + type: string + description: Repository and image name + example: bitnami/nginx + +tag: + type: string + description: image tag + example: 1.16.1-debian-10-r63 + +pullPolicy: + type: string + description: Specify a imagePullPolicy.' + +pullSecrets: + type: array + items: + type: string + description: Optionally specify an array of imagePullSecrets (evaluated as templates). + +debug: + type: boolean + description: Set to true if you would like to see extra information on logs + example: false + +## An instance would be: +# registry: docker.io +# repository: bitnami/nginx +# tag: 1.16.1-debian-10-r63 +# pullPolicy: IfNotPresent +# debug: false +``` + +### Persistence + +```yaml +enabled: + type: boolean + description: Whether enable persistence. + example: true + +storageClass: + type: string + description: Ghost data Persistent Volume Storage Class, If set to "-", storageClassName: "" which disables dynamic provisioning. + example: "-" + +accessMode: + type: string + description: Access mode for the Persistent Volume Storage. + example: ReadWriteOnce + +size: + type: string + description: Size the Persistent Volume Storage. + example: 8Gi + +path: + type: string + description: Path to be persisted. + example: /bitnami + +## An instance would be: +# enabled: true +# storageClass: "-" +# accessMode: ReadWriteOnce +# size: 8Gi +# path: /bitnami +``` + +### ExistingSecret + +```yaml +name: + type: string + description: Name of the existing secret. + example: mySecret +keyMapping: + description: Mapping between the expected key name and the name of the key in the existing secret. + type: object + +## An instance would be: +# name: mySecret +# keyMapping: +# password: myPasswordKey +``` + +#### Example of use + +When we store sensitive data for a deployment in a secret, some times we want to give to users the possibility of using theirs existing secrets. + +```yaml +# templates/secret.yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }} + labels: + app: {{ include "common.names.fullname" . }} +type: Opaque +data: + password: {{ .Values.password | b64enc | quote }} + +# templates/dpl.yaml +--- +... + env: + - name: PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "common.secrets.name" (dict "existingSecret" .Values.existingSecret "context" $) }} + key: {{ include "common.secrets.key" (dict "existingSecret" .Values.existingSecret "key" "password") }} +... + +# values.yaml +--- +name: mySecret +keyMapping: + password: myPasswordKey +``` + +### ValidateValue + +#### NOTES.txt + +```console +{{- $validateValueConf00 := (dict "valueKey" "path.to.value00" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value01" "secret" "secretName" "field" "password-01") -}} + +{{ include "common.validations.values.multiple.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} +``` + +If we force those values to be empty we will see some alerts + +```console +helm install test mychart --set path.to.value00="",path.to.value01="" + 'path.to.value00' must not be empty, please add '--set path.to.value00=$PASSWORD_00' to the command. To get the current value: + + export PASSWORD_00=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-00}" | base64 -d) + + 'path.to.value01' must not be empty, please add '--set path.to.value01=$PASSWORD_01' to the command. To get the current value: + + export PASSWORD_01=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-01}" | base64 -d) +``` + +## Upgrading + +### To 1.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +#### What changes were introduced in this major version? + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- Use `type: library`. [Here](https://v3.helm.sh/docs/faq/#library-chart-support) you can find more information. +- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts + +#### Considerations when upgrading to this version + +- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues +- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore +- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 + +#### Useful links + +- +- +- + +## License + +Copyright © 2025 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/backing-services/gitea/charts/postgresql/charts/common/templates/_affinities.tpl b/backing-services/gitea/charts/postgresql/charts/common/templates/_affinities.tpl new file mode 100644 index 0000000..c6ccc62 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/templates/_affinities.tpl @@ -0,0 +1,169 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a soft nodeAffinity definition +{{ include "common.affinities.nodes.soft" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.soft" -}} +preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} + weight: 1 +{{- end -}} + +{{/* +Return a hard nodeAffinity definition +{{ include "common.affinities.nodes.hard" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.hard" -}} +requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} +{{- end -}} + +{{/* +Return a nodeAffinity definition +{{ include "common.affinities.nodes" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.nodes.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.nodes.hard" . -}} + {{- end -}} +{{- end -}} + +{{/* +Return a topologyKey definition +{{ include "common.affinities.topologyKey" (dict "topologyKey" "BAR") -}} +*/}} +{{- define "common.affinities.topologyKey" -}} +{{ .topologyKey | default "kubernetes.io/hostname" -}} +{{- end -}} + +{{/* +Return a soft podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.soft" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "extraNamespaces" (list "namespace1" "namespace2") "context" $) -}} +*/}} +{{- define "common.affinities.pods.soft" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +{{- $extraNamespaces := default (list) .extraNamespaces -}} +preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if $extraNamespaces }} + namespaces: + - {{ .context.Release.Namespace }} + {{- with $extraNamespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: 1 + {{- range $extraPodAffinityTerms }} + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if .namespaces }} + namespaces: + - {{ $.context.Release.Namespace }} + {{- with .namespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: {{ .weight | default 1 -}} + {{- end -}} +{{- end -}} + +{{/* +Return a hard podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.hard" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "extraNamespaces" (list "namespace1" "namespace2") "context" $) -}} +*/}} +{{- define "common.affinities.pods.hard" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +{{- $extraNamespaces := default (list) .extraNamespaces -}} +requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if $extraNamespaces }} + namespaces: + - {{ .context.Release.Namespace }} + {{- with $extraNamespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 6 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- range $extraPodAffinityTerms }} + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if .namespaces }} + namespaces: + - {{ $.context.Release.Namespace }} + {{- with .namespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 6 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- end -}} +{{- end -}} + +{{/* +Return a podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.pods" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.pods.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.pods.hard" . -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql/charts/common/templates/_capabilities.tpl b/backing-services/gitea/charts/postgresql/charts/common/templates/_capabilities.tpl new file mode 100644 index 0000000..58f58c1 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/templates/_capabilities.tpl @@ -0,0 +1,178 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the target Kubernetes version +*/}} +{{- define "common.capabilities.kubeVersion" -}} +{{- default (default .Capabilities.KubeVersion.Version .Values.kubeVersion) ((.Values.global).kubeVersion) -}} +{{- end -}} + +{{/* +Return true if the apiVersion is supported +Usage: +{{ include "common.capabilities.apiVersions.has" (dict "version" "batch/v1" "context" $) }} +*/}} +{{- define "common.capabilities.apiVersions.has" -}} +{{- $providedAPIVersions := default .context.Values.apiVersions ((.context.Values.global).apiVersions) -}} +{{- if and (empty $providedAPIVersions) (.context.Capabilities.APIVersions.Has .version) -}} + {{- true -}} +{{- else if has .version $providedAPIVersions -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for poddisruptionbudget. +*/}} +{{- define "common.capabilities.policy.apiVersion" -}} +{{- print "policy/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "common.capabilities.networkPolicy.apiVersion" -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for job. +*/}} +{{- define "common.capabilities.job.apiVersion" -}} +{{- print "batch/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for cronjob. +*/}} +{{- define "common.capabilities.cronjob.apiVersion" -}} +{{- print "batch/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for daemonset. +*/}} +{{- define "common.capabilities.daemonset.apiVersion" -}} +{{- print "apps/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for deployment. +*/}} +{{- define "common.capabilities.deployment.apiVersion" -}} +{{- print "apps/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for statefulset. +*/}} +{{- define "common.capabilities.statefulset.apiVersion" -}} +{{- print "apps/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "common.capabilities.ingress.apiVersion" -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for RBAC resources. +*/}} +{{- define "common.capabilities.rbac.apiVersion" -}} +{{- print "rbac.authorization.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for CRDs. +*/}} +{{- define "common.capabilities.crd.apiVersion" -}} +{{- print "apiextensions.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for APIService. +*/}} +{{- define "common.capabilities.apiService.apiVersion" -}} +{{- print "apiregistration.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Horizontal Pod Autoscaler. +*/}} +{{- define "common.capabilities.hpa.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" .context -}} +{{- print "autoscaling/v2" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Vertical Pod Autoscaler. +*/}} +{{- define "common.capabilities.vpa.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "autoscaling/v1beta2" -}} +{{- else -}} +{{- print "autoscaling/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if PodSecurityPolicy is supported +*/}} +{{- define "common.capabilities.psp.supported" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if or (empty $kubeVersion) (semverCompare "<1.25-0" $kubeVersion) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if AdmissionConfiguration is supported +*/}} +{{- define "common.capabilities.admissionConfiguration.supported" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} + {{- true -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for AdmissionConfiguration. +*/}} +{{- define "common.capabilities.admissionConfiguration.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "apiserver.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiserver.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for PodSecurityConfiguration. +*/}} +{{- define "common.capabilities.podSecurityConfiguration.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "pod-security.admission.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "pod-security.admission.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the used Helm version is 3.3+. +A way to check the used Helm version was not introduced until version 3.3.0 with .Capabilities.HelmVersion, which contains an additional "{}}" structure. +This check is introduced as a regexMatch instead of {{ if .Capabilities.HelmVersion }} because checking for the key HelmVersion in <3.3 results in a "interface not found" error. +**To be removed when the catalog's minimun Helm version is 3.3** +*/}} +{{- define "common.capabilities.supportsHelmVersion" -}} +{{- if regexMatch "{(v[0-9])*[^}]*}}$" (.Capabilities | toString ) }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql/charts/common/templates/_compatibility.tpl b/backing-services/gitea/charts/postgresql/charts/common/templates/_compatibility.tpl new file mode 100644 index 0000000..19c26db --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/templates/_compatibility.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return true if the detected platform is Openshift +Usage: +{{- include "common.compatibility.isOpenshift" . -}} +*/}} +{{- define "common.compatibility.isOpenshift" -}} +{{- if .Capabilities.APIVersions.Has "security.openshift.io/v1" -}} +{{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Render a compatible securityContext depending on the platform. By default it is maintained as it is. In other platforms like Openshift we remove default user/group values that do not work out of the box with the restricted-v1 SCC +Usage: +{{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) -}} +*/}} +{{- define "common.compatibility.renderSecurityContext" -}} +{{- $adaptedContext := .secContext -}} + +{{- if (((.context.Values.global).compatibility).openshift) -}} + {{- if or (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "force") (and (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "auto") (include "common.compatibility.isOpenshift" .context)) -}} + {{/* Remove incompatible user/group values that do not work in Openshift out of the box */}} + {{- $adaptedContext = omit $adaptedContext "fsGroup" "runAsUser" "runAsGroup" -}} + {{- if not .secContext.seLinuxOptions -}} + {{/* If it is an empty object, we remove it from the resulting context because it causes validation issues */}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{/* Remove empty seLinuxOptions object if global.compatibility.omitEmptySeLinuxOptions is set to true */}} +{{- if and (((.context.Values.global).compatibility).omitEmptySeLinuxOptions) (not .secContext.seLinuxOptions) -}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} +{{- end -}} +{{/* Remove fields that are disregarded when running the container in privileged mode */}} +{{- if $adaptedContext.privileged -}} + {{- $adaptedContext = omit $adaptedContext "capabilities" -}} +{{- end -}} +{{- omit $adaptedContext "enabled" | toYaml -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql/charts/common/templates/_errors.tpl b/backing-services/gitea/charts/postgresql/charts/common/templates/_errors.tpl new file mode 100644 index 0000000..fb704c9 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/templates/_errors.tpl @@ -0,0 +1,92 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Throw error when upgrading using empty passwords values that must not be empty. + +Usage: +{{- $validationError00 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password00" "secret" "secretName" "field" "password-00") -}} +{{- $validationError01 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password01" "secret" "secretName" "field" "password-01") -}} +{{ include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $validationError00 $validationError01) "context" $) }} + +Required password params: + - validationErrors - String - Required. List of validation strings to be return, if it is empty it won't throw error. + - context - Context - Required. Parent context. +*/}} +{{- define "common.errors.upgrade.passwords.empty" -}} + {{- $validationErrors := join "" .validationErrors -}} + {{- if and $validationErrors .context.Release.IsUpgrade -}} + {{- $errorString := "\nPASSWORDS ERROR: You must provide your current passwords when upgrading the release." -}} + {{- $errorString = print $errorString "\n Note that even after reinstallation, old credentials may be needed as they may be kept in persistent volume claims." -}} + {{- $errorString = print $errorString "\n Further information can be obtained at https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues/#credential-errors-while-upgrading-chart-releases" -}} + {{- $errorString = print $errorString "\n%s" -}} + {{- printf $errorString $validationErrors | fail -}} + {{- end -}} +{{- end -}} + +{{/* +Throw error when original container images are replaced. +The error can be bypassed by setting the "global.security.allowInsecureImages" to true. In this case, +a warning message will be shown instead. + +Usage: +{{ include "common.errors.insecureImages" (dict "images" (list .Values.path.to.the.imageRoot) "context" $) }} +*/}} +{{- define "common.errors.insecureImages" -}} +{{- $relocatedImages := list -}} +{{- $replacedImages := list -}} +{{- $bitnamiLegacyImages := list -}} +{{- $retaggedImages := list -}} +{{- $globalRegistry := ((.context.Values.global).imageRegistry) -}} +{{- $originalImages := .context.Chart.Annotations.images -}} +{{- range .images -}} + {{- $registryName := default .registry $globalRegistry -}} + {{- $fullImageNameNoTag := printf "%s/%s" $registryName .repository -}} + {{- $fullImageName := printf "%s:%s" $fullImageNameNoTag .tag -}} + {{- if not (contains $fullImageNameNoTag $originalImages) -}} + {{- if not (contains $registryName $originalImages) -}} + {{- $relocatedImages = append $relocatedImages $fullImageName -}} + {{- else if not (contains .repository $originalImages) -}} + {{- $replacedImages = append $replacedImages $fullImageName -}} + {{- if contains "docker.io/bitnamilegacy/" $fullImageNameNoTag -}} + {{- $bitnamiLegacyImages = append $bitnamiLegacyImages $fullImageName -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- if not (contains (printf "%s:%s" .repository .tag) $originalImages) -}} + {{- $retaggedImages = append $retaggedImages $fullImageName -}} + {{- end -}} +{{- end -}} + +{{- if and (or (gt (len $relocatedImages) 0) (gt (len $replacedImages) 0)) (((.context.Values.global).security).allowInsecureImages) -}} + {{- print "\n\n⚠ SECURITY WARNING: Verifying original container images was skipped. Please note this Helm chart was designed, tested, and validated on multiple platforms using a specific set of Bitnami and Bitnami Secure Images containers. Substituting other containers is likely to cause degraded security and performance, broken chart features, and missing environment variables.\n" -}} +{{- else if (or (gt (len $relocatedImages) 0) (gt (len $replacedImages) 0)) -}} + {{- $errorString := "Original containers have been substituted for unrecognized ones. Deploying this chart with non-standard containers is likely to cause degraded security and performance, broken chart features, and missing environment variables." -}} + {{- $errorString = print $errorString "\n\nUnrecognized images:" -}} + {{- range (concat $relocatedImages $replacedImages) -}} + {{- $errorString = print $errorString "\n - " . -}} + {{- end -}} + {{- if and (eq (len $relocatedImages) 0) (eq (len $replacedImages) (len $bitnamiLegacyImages)) -}} + {{- $errorString = print "\n\n⚠ WARNING: " $errorString -}} + {{- print $errorString -}} + {{- else if or (contains "docker.io/bitnami/" $originalImages) (contains "docker.io/bitnamiprem/" $originalImages) (contains "docker.io/bitnamisecure/" $originalImages) -}} + {{- $errorString = print "\n\n⚠ ERROR: " $errorString -}} + {{- $errorString = print $errorString "\n\nIf you are sure you want to proceed with non-standard containers, you can skip container image verification by setting the global parameter 'global.security.allowInsecureImages' to true." -}} + {{- $errorString = print $errorString "\nFurther information can be obtained at https://github.com/bitnami/charts/issues/30850" -}} + {{- print $errorString | fail -}} + {{- else if gt (len $replacedImages) 0 -}} + {{- $errorString = print "\n\n⚠ WARNING: " $errorString -}} + {{- print $errorString -}} + {{- end -}} +{{- else if gt (len $retaggedImages) 0 -}} + {{- $warnString := "\n\n⚠ WARNING: Original containers have been retagged. Please note this Helm chart was tested, and validated on multiple platforms using a specific set of Bitnami and Bitnami Secure Images containers. Substituting original image tags could cause unexpected behavior." -}} + {{- $warnString = print $warnString "\n\nRetagged images:" -}} + {{- range $retaggedImages -}} + {{- $warnString = print $warnString "\n - " . -}} + {{- end -}} + {{- print $warnString -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql/charts/common/templates/_images.tpl b/backing-services/gitea/charts/postgresql/charts/common/templates/_images.tpl new file mode 100644 index 0000000..76bb7ce --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/templates/_images.tpl @@ -0,0 +1,115 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Return the proper image name. +If image tag and digest are not defined, termination fallbacks to chart appVersion. +{{ include "common.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" .Values.global "chart" .Chart ) }} +*/}} +{{- define "common.images.image" -}} +{{- $registryName := default .imageRoot.registry ((.global).imageRegistry) -}} +{{- $repositoryName := .imageRoot.repository -}} +{{- $separator := ":" -}} +{{- $termination := .imageRoot.tag | toString -}} + +{{- if not .imageRoot.tag }} + {{- if .chart }} + {{- $termination = .chart.AppVersion | toString -}} + {{- end -}} +{{- end -}} +{{- if .imageRoot.digest }} + {{- $separator = "@" -}} + {{- $termination = .imageRoot.digest | toString -}} +{{- end -}} +{{- if $registryName }} + {{- printf "%s/%s%s%s" $registryName $repositoryName $separator $termination -}} +{{- else -}} + {{- printf "%s%s%s" $repositoryName $separator $termination -}} +{{- end -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead) +{{ include "common.images.pullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global) }} +*/}} +{{- define "common.images.pullSecrets" -}} + {{- $pullSecrets := list }} + + {{- range ((.global).imagePullSecrets) -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end }} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) -}} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names evaluating values as templates +{{ include "common.images.renderPullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $) }} +*/}} +{{- define "common.images.renderPullSecrets" -}} + {{- $pullSecrets := list }} + {{- $context := .context }} + + {{- range (($context.Values.global).imagePullSecrets) -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) -}} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper image version (ingores image revision/prerelease info & fallbacks to chart appVersion) +{{ include "common.images.version" ( dict "imageRoot" .Values.path.to.the.image "chart" .Chart ) }} +*/}} +{{- define "common.images.version" -}} +{{- $imageTag := .imageRoot.tag | toString -}} +{{/* regexp from https://github.com/Masterminds/semver/blob/23f51de38a0866c5ef0bfc42b3f735c73107b700/version.go#L41-L44 */}} +{{- if regexMatch `^([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?$` $imageTag -}} + {{- $version := semver $imageTag -}} + {{- printf "%d.%d.%d" $version.Major $version.Minor $version.Patch -}} +{{- else -}} + {{- print .chart.AppVersion -}} +{{- end -}} +{{- end -}} + diff --git a/backing-services/gitea/charts/postgresql/charts/common/templates/_ingress.tpl b/backing-services/gitea/charts/postgresql/charts/common/templates/_ingress.tpl new file mode 100644 index 0000000..2d0dbf1 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/templates/_ingress.tpl @@ -0,0 +1,41 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Generate backend entry that is compatible with all Kubernetes API versions. + +Usage: +{{ include "common.ingress.backend" (dict "serviceName" "backendName" "servicePort" "backendPort" "context" $) }} + +Params: + - serviceName - String. Name of an existing service backend + - servicePort - String/Int. Port name (or number) of the service. It will be translated to different yaml depending if it is a string or an integer. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.ingress.backend" -}} +service: + name: {{ .serviceName }} + port: + {{- if typeIs "string" .servicePort }} + name: {{ .servicePort }} + {{- else if or (typeIs "int" .servicePort) (typeIs "float64" .servicePort) }} + number: {{ .servicePort | int }} + {{- end }} +{{- end -}} + +{{/* +Return true if cert-manager required annotations for TLS signed +certificates are set in the Ingress annotations +Ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations +Usage: +{{ include "common.ingress.certManagerRequest" ( dict "annotations" .Values.path.to.the.ingress.annotations ) }} +*/}} +{{- define "common.ingress.certManagerRequest" -}} +{{ if or (hasKey .annotations "cert-manager.io/cluster-issuer") (hasKey .annotations "cert-manager.io/issuer") (hasKey .annotations "kubernetes.io/tls-acme") }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql/charts/common/templates/_labels.tpl b/backing-services/gitea/charts/postgresql/charts/common/templates/_labels.tpl new file mode 100644 index 0000000..0a0cc54 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/templates/_labels.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Kubernetes standard labels +{{ include "common.labels.standard" (dict "customLabels" .Values.commonLabels "context" $) -}} +*/}} +{{- define "common.labels.standard" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{- $default := dict "app.kubernetes.io/name" (include "common.names.name" .context) "helm.sh/chart" (include "common.names.chart" .context) "app.kubernetes.io/instance" .context.Release.Name "app.kubernetes.io/managed-by" .context.Release.Service -}} +{{- with .context.Chart.AppVersion -}} +{{- $_ := set $default "app.kubernetes.io/version" . -}} +{{- end -}} +{{ template "common.tplvalues.merge" (dict "values" (list .customLabels $default) "context" .context) }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +helm.sh/chart: {{ include "common.names.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Chart.AppVersion }} +app.kubernetes.io/version: {{ . | quote }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Labels used on immutable fields such as deploy.spec.selector.matchLabels or svc.spec.selector +{{ include "common.labels.matchLabels" (dict "customLabels" .Values.podLabels "context" $) -}} + +We don't want to loop over custom labels appending them to the selector +since it's very likely that it will break deployments, services, etc. +However, it's important to overwrite the standard labels if the user +overwrote them on metadata.labels fields. +*/}} +{{- define "common.labels.matchLabels" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{ merge (pick (include "common.tplvalues.render" (dict "value" .customLabels "context" .context) | fromYaml) "app.kubernetes.io/name" "app.kubernetes.io/instance") (dict "app.kubernetes.io/name" (include "common.names.name" .context) "app.kubernetes.io/instance" .context.Release.Name ) | toYaml }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql/charts/common/templates/_names.tpl b/backing-services/gitea/charts/postgresql/charts/common/templates/_names.tpl new file mode 100644 index 0000000..d5d0ae4 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/templates/_names.tpl @@ -0,0 +1,72 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "common.names.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "common.names.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "common.names.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- $releaseName := regexReplaceAll "(-?[^a-z\\d\\-])+-?" (lower .Release.Name) "-" -}} +{{- if contains $name $releaseName -}} +{{- $releaseName | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" $releaseName $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified dependency name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +Usage: +{{ include "common.names.dependency.fullname" (dict "chartName" "dependency-chart-name" "chartValues" .Values.dependency-chart "context" $) }} +*/}} +{{- define "common.names.dependency.fullname" -}} +{{- if .chartValues.fullnameOverride -}} +{{- .chartValues.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .chartName .chartValues.nameOverride -}} +{{- if contains $name .context.Release.Name -}} +{{- .context.Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .context.Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts. +*/}} +{{- define "common.names.namespace" -}} +{{- default .Release.Namespace .Values.namespaceOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a fully qualified app name adding the installation's namespace. +*/}} +{{- define "common.names.fullname.namespace" -}} +{{- printf "%s-%s" (include "common.names.fullname" .) (include "common.names.namespace" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql/charts/common/templates/_resources.tpl b/backing-services/gitea/charts/postgresql/charts/common/templates/_resources.tpl new file mode 100644 index 0000000..d8a43e1 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/templates/_resources.tpl @@ -0,0 +1,50 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a resource request/limit object based on a given preset. +These presets are for basic testing and not meant to be used in production +{{ include "common.resources.preset" (dict "type" "nano") -}} +*/}} +{{- define "common.resources.preset" -}} +{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} +{{- $presets := dict + "nano" (dict + "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "2Gi") + ) + "micro" (dict + "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "2Gi") + ) + "small" (dict + "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "2Gi") + ) + "medium" (dict + "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "2Gi") + ) + "large" (dict + "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "2Gi") + ) + "xlarge" (dict + "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "2Gi") + ) + "2xlarge" (dict + "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "2Gi") + ) + }} +{{- if hasKey $presets .type -}} +{{- index $presets .type | toYaml -}} +{{- else -}} +{{- printf "ERROR: Preset key '%s' invalid. Allowed values are %s" .type (join "," (keys $presets)) | fail -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql/charts/common/templates/_secrets.tpl b/backing-services/gitea/charts/postgresql/charts/common/templates/_secrets.tpl new file mode 100644 index 0000000..7868c00 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/templates/_secrets.tpl @@ -0,0 +1,192 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Generate secret name. + +Usage: +{{ include "common.secrets.name" (dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $) }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - defaultNameSuffix - String - Optional. It is used only if we have several secrets in the same deployment. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.secrets.name" -}} +{{- $name := (include "common.names.fullname" .context) -}} + +{{- if .defaultNameSuffix -}} +{{- $name = printf "%s-%s" $name .defaultNameSuffix | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- with .existingSecret -}} +{{- if not (typeIs "string" .) -}} +{{- with .name -}} +{{- $name = . -}} +{{- end -}} +{{- else -}} +{{- $name = . -}} +{{- end -}} +{{- end -}} + +{{- printf "%s" $name -}} +{{- end -}} + +{{/* +Generate secret key. + +Usage: +{{ include "common.secrets.key" (dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName") }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - key - String - Required. Name of the key in the secret. +*/}} +{{- define "common.secrets.key" -}} +{{- $key := .key -}} + +{{- if .existingSecret -}} + {{- if not (typeIs "string" .existingSecret) -}} + {{- if .existingSecret.keyMapping -}} + {{- $key = index .existingSecret.keyMapping $.key -}} + {{- end -}} + {{- end }} +{{- end -}} + +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Generate secret password or retrieve one if already created. + +Usage: +{{ include "common.secrets.passwords.manage" (dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "honorProvidedValues" false "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - providedValues - List - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - length - int - Optional - Length of the generated random password. + - strong - Boolean - Optional - Whether to add symbols to the generated random password. + - chartName - String - Optional - Name of the chart used when said chart is deployed as a subchart. + - context - Context - Required - Parent context. + - failOnNew - Boolean - Optional - Default to true. If set to false, skip errors adding new keys to existing secrets. + - skipB64enc - Boolean - Optional - Default to false. If set to true, no the secret will not be base64 encrypted. + - skipQuote - Boolean - Optional - Default to false. If set to true, no quotes will be added around the secret. + - honorProvidedValues - Boolean - Optional - Default to false. If set to true, the values in providedValues have higher priority than an existing secret +The order in which this function returns a secret password: + 1. Password provided via the values.yaml if honorProvidedValues = true + (If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned) + 2. Already existing 'Secret' resource + (If a 'Secret' resource is found under the name provided to the 'secret' parameter to this function and that 'Secret' resource contains a key with the name passed as the 'key' parameter to this function then the value of this existing secret password will be returned) + 3. Password provided via the values.yaml if honorProvidedValues = false + (If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned) + 4. Randomly generated secret password + (A new random secret password with the length specified in the 'length' parameter will be generated and returned) + +*/}} +{{- define "common.secrets.passwords.manage" -}} + +{{- $password := "" }} +{{- $subchart := "" }} +{{- $chartName := default "" .chartName }} +{{- $passwordLength := default 10 .length }} +{{- $providedPasswordKey := include "common.utils.getKeyFromList" (dict "keys" .providedValues "context" $.context) }} +{{- $providedPasswordValue := include "common.utils.getValueFromKey" (dict "key" $providedPasswordKey "context" $.context) }} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data }} +{{- if $secretData }} + {{- if hasKey $secretData .key }} + {{- $password = index $secretData .key | b64dec }} + {{- else if not (eq .failOnNew false) }} + {{- printf "\nPASSWORDS ERROR: The secret \"%s\" does not contain the key \"%s\"\n" .secret .key | fail -}} + {{- end -}} +{{- end }} + +{{- if and $providedPasswordValue .honorProvidedValues }} + {{- $password = tpl ($providedPasswordValue | toString) .context }} +{{- end }} + +{{- if not $password }} + {{- if $providedPasswordValue }} + {{- $password = tpl ($providedPasswordValue | toString) .context }} + {{- else }} + {{- if .context.Values.enabled }} + {{- $subchart = $chartName }} + {{- end -}} + + {{- if not (eq .failOnNew false) }} + {{- $requiredPassword := dict "valueKey" $providedPasswordKey "secret" .secret "field" .key "subchart" $subchart "context" $.context -}} + {{- $requiredPasswordError := include "common.validations.values.single.empty" $requiredPassword -}} + {{- $passwordValidationErrors := list $requiredPasswordError -}} + {{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" $passwordValidationErrors "context" $.context) -}} + {{- end }} + + {{- if .strong }} + {{- $subStr := list (lower (randAlpha 1)) (randNumeric 1) (upper (randAlpha 1)) | join "_" }} + {{- $password = randAscii $passwordLength }} + {{- $password = regexReplaceAllLiteral "\\W" $password "@" | substr 5 $passwordLength }} + {{- $password = printf "%s%s" $subStr $password | toString | shuffle }} + {{- else }} + {{- $password = randAlphaNum $passwordLength }} + {{- end }} + {{- end -}} +{{- end -}} +{{- if not .skipB64enc }} +{{- $password = $password | b64enc }} +{{- end -}} +{{- if .skipQuote -}} +{{- printf "%s" $password -}} +{{- else -}} +{{- printf "%s" $password | quote -}} +{{- end -}} +{{- end -}} + +{{/* +Reuses the value from an existing secret, otherwise sets its value to a default value. + +Usage: +{{ include "common.secrets.lookup" (dict "secret" "secret-name" "key" "keyName" "defaultValue" .Values.myValue "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - defaultValue - String - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - context - Context - Required - Parent context. + +*/}} +{{- define "common.secrets.lookup" -}} +{{- $value := "" -}} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data -}} +{{- if and $secretData (hasKey $secretData .key) -}} + {{- $value = index $secretData .key -}} +{{- else if .defaultValue -}} + {{- $value = .defaultValue | toString | b64enc -}} +{{- end -}} +{{- if $value -}} +{{- printf "%s" $value -}} +{{- end -}} +{{- end -}} + +{{/* +Returns whether a previous generated secret already exists + +Usage: +{{ include "common.secrets.exists" (dict "secret" "secret-name" "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - context - Context - Required - Parent context. +*/}} +{{- define "common.secrets.exists" -}} +{{- $secret := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret) }} +{{- if $secret }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql/charts/common/templates/_storage.tpl b/backing-services/gitea/charts/postgresql/charts/common/templates/_storage.tpl new file mode 100644 index 0000000..aa75856 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/templates/_storage.tpl @@ -0,0 +1,21 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the proper Storage Class +{{ include "common.storage.class" ( dict "persistence" .Values.path.to.the.persistence "global" $) }} +*/}} +{{- define "common.storage.class" -}} +{{- $storageClass := (.global).storageClass | default .persistence.storageClass | default (.global).defaultStorageClass | default "" -}} +{{- if $storageClass -}} + {{- if (eq "-" $storageClass) -}} + {{- printf "storageClassName: \"\"" -}} + {{- else -}} + {{- printf "storageClassName: %s" $storageClass -}} + {{- end -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql/charts/common/templates/_tplvalues.tpl b/backing-services/gitea/charts/postgresql/charts/common/templates/_tplvalues.tpl new file mode 100644 index 0000000..a04f4c1 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/templates/_tplvalues.tpl @@ -0,0 +1,52 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Renders a value that contains template perhaps with scope if the scope is present. +Usage: +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ ) }} +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ "scope" $app ) }} +*/}} +{{- define "common.tplvalues.render" -}} +{{- $value := typeIs "string" .value | ternary .value (.value | toYaml) }} +{{- if contains "{{" (toJson .value) }} + {{- if .scope }} + {{- tpl (cat "{{- with $.RelativeScope -}}" $value "{{- end }}") (merge (dict "RelativeScope" .scope) .context) }} + {{- else }} + {{- tpl $value .context }} + {{- end }} +{{- else }} + {{- $value }} +{{- end }} +{{- end -}} + +{{/* +Merge a list of values that contains template after rendering them. +Merge precedence is consistent with http://masterminds.github.io/sprig/dicts.html#merge-mustmerge +Usage: +{{ include "common.tplvalues.merge" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }} +*/}} +{{- define "common.tplvalues.merge" -}} +{{- $dst := dict -}} +{{- range .values -}} +{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | merge $dst -}} +{{- end -}} +{{ $dst | toYaml }} +{{- end -}} + +{{/* +Merge a list of values that contains template after rendering them. +Merge precedence is consistent with https://masterminds.github.io/sprig/dicts.html#mergeoverwrite-mustmergeoverwrite +Usage: +{{ include "common.tplvalues.merge-overwrite" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }} +*/}} +{{- define "common.tplvalues.merge-overwrite" -}} +{{- $dst := dict -}} +{{- range .values -}} +{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | mergeOverwrite $dst -}} +{{- end -}} +{{ $dst | toYaml }} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql/charts/common/templates/_utils.tpl b/backing-services/gitea/charts/postgresql/charts/common/templates/_utils.tpl new file mode 100644 index 0000000..d53c74a --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/templates/_utils.tpl @@ -0,0 +1,77 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Print instructions to get a secret value. +Usage: +{{ include "common.utils.secret.getvalue" (dict "secret" "secret-name" "field" "secret-value-field" "context" $) }} +*/}} +{{- define "common.utils.secret.getvalue" -}} +{{- $varname := include "common.utils.fieldToEnvVar" . -}} +export {{ $varname }}=$(kubectl get secret --namespace {{ include "common.names.namespace" .context | quote }} {{ .secret }} -o jsonpath="{.data.{{ .field }}}" | base64 -d) +{{- end -}} + +{{/* +Build env var name given a field +Usage: +{{ include "common.utils.fieldToEnvVar" dict "field" "my-password" }} +*/}} +{{- define "common.utils.fieldToEnvVar" -}} + {{- $fieldNameSplit := splitList "-" .field -}} + {{- $upperCaseFieldNameSplit := list -}} + + {{- range $fieldNameSplit -}} + {{- $upperCaseFieldNameSplit = append $upperCaseFieldNameSplit ( upper . ) -}} + {{- end -}} + + {{ join "_" $upperCaseFieldNameSplit }} +{{- end -}} + +{{/* +Gets a value from .Values given +Usage: +{{ include "common.utils.getValueFromKey" (dict "key" "path.to.key" "context" $) }} +*/}} +{{- define "common.utils.getValueFromKey" -}} +{{- $splitKey := splitList "." .key -}} +{{- $value := "" -}} +{{- $latestObj := $.context.Values -}} +{{- range $splitKey -}} + {{- if not $latestObj -}} + {{- printf "please review the entire path of '%s' exists in values" $.key | fail -}} + {{- end -}} + {{- $value = ( index $latestObj . ) -}} + {{- $latestObj = $value -}} +{{- end -}} +{{- printf "%v" (default "" $value) -}} +{{- end -}} + +{{/* +Returns first .Values key with a defined value or first of the list if all non-defined +Usage: +{{ include "common.utils.getKeyFromList" (dict "keys" (list "path.to.key1" "path.to.key2") "context" $) }} +*/}} +{{- define "common.utils.getKeyFromList" -}} +{{- $key := first .keys -}} +{{- $reverseKeys := reverse .keys }} +{{- range $reverseKeys }} + {{- $value := include "common.utils.getValueFromKey" (dict "key" . "context" $.context ) }} + {{- if $value -}} + {{- $key = . }} + {{- end -}} +{{- end -}} +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Checksum a template at "path" containing a *single* resource (ConfigMap,Secret) for use in pod annotations, excluding the metadata (see #18376). +Usage: +{{ include "common.utils.checksumTemplate" (dict "path" "/configmap.yaml" "context" $) }} +*/}} +{{- define "common.utils.checksumTemplate" -}} +{{- $obj := include (print .context.Template.BasePath .path) .context | fromYaml -}} +{{ omit $obj "apiVersion" "kind" "metadata" | toYaml | sha256sum }} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql/charts/common/templates/_warnings.tpl b/backing-services/gitea/charts/postgresql/charts/common/templates/_warnings.tpl new file mode 100644 index 0000000..62c44df --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/templates/_warnings.tpl @@ -0,0 +1,109 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Warning about using rolling tag. +Usage: +{{ include "common.warnings.rollingTag" .Values.path.to.the.imageRoot }} +*/}} +{{- define "common.warnings.rollingTag" -}} + +{{- if and (contains "bitnami/" .repository) (not (.tag | toString | regexFind "-r\\d+$|sha256:")) }} +WARNING: Rolling tag detected ({{ .repository }}:{{ .tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. ++info https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-understand-rolling-tags-containers-index.html +{{- end }} +{{- end -}} + +{{/* +Warning about replaced images from the original. +Usage: +{{ include "common.warnings.modifiedImages" (dict "images" (list .Values.path.to.the.imageRoot) "context" $) }} +*/}} +{{- define "common.warnings.modifiedImages" -}} +{{- $affectedImages := list -}} +{{- $printMessage := false -}} +{{- $originalImages := .context.Chart.Annotations.images -}} +{{- range .images -}} + {{- $fullImageName := printf (printf "%s/%s:%s" .registry .repository .tag) -}} + {{- if not (contains $fullImageName $originalImages) }} + {{- $affectedImages = append $affectedImages (printf "%s/%s:%s" .registry .repository .tag) -}} + {{- $printMessage = true -}} + {{- end -}} +{{- end -}} +{{- if $printMessage }} + +⚠ SECURITY WARNING: Original containers have been substituted. This Helm chart was designed, tested, and validated on multiple platforms using a specific set of Bitnami and Tanzu Application Catalog containers. Substituting other containers is likely to cause degraded security and performance, broken chart features, and missing environment variables. + +Substituted images detected: +{{- range $affectedImages }} + - {{ . }} +{{- end }} +{{- end -}} +{{- end -}} + +{{/* +Warning about not setting the resource object in all deployments. +Usage: +{{ include "common.warnings.resources" (dict "sections" (list "path1" "path2") context $) }} +Example: +{{- include "common.warnings.resources" (dict "sections" (list "csiProvider.provider" "server" "volumePermissions" "") "context" $) }} +The list in the example assumes that the following values exist: + - csiProvider.provider.resources + - server.resources + - volumePermissions.resources + - resources +*/}} +{{- define "common.warnings.resources" -}} +{{- $values := .context.Values -}} +{{- $printMessage := false -}} +{{ $affectedSections := list -}} +{{- range .sections -}} + {{- if eq . "" -}} + {{/* Case where the resources section is at the root (one main deployment in the chart) */}} + {{- if not (index $values "resources") -}} + {{- $affectedSections = append $affectedSections "resources" -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Case where the are multiple resources sections (more than one main deployment in the chart) */}} + {{- $keys := split "." . -}} + {{/* We iterate through the different levels until arriving to the resource section. Example: a.b.c.resources */}} + {{- $section := $values -}} + {{- range $keys -}} + {{- $section = index $section . -}} + {{- end -}} + {{- if not (index $section "resources") -}} + {{/* If the section has enabled=false or replicaCount=0, do not include it */}} + {{- if and (hasKey $section "enabled") -}} + {{- if index $section "enabled" -}} + {{/* enabled=true */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else if and (hasKey $section "replicaCount") -}} + {{/* We need a casting to int because number 0 is not treated as an int by default */}} + {{- if (gt (index $section "replicaCount" | int) 0) -}} + {{/* replicaCount > 0 */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Default case, add it to the affected sections */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- if $printMessage }} + +WARNING: There are "resources" sections in the chart not set. Using "resourcesPreset" is not recommended for production. For production installations, please set the following values according to your workload needs: +{{- range $affectedSections }} + - {{ . }} +{{- end }} ++info https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql/charts/common/templates/validations/_cassandra.tpl b/backing-services/gitea/charts/postgresql/charts/common/templates/validations/_cassandra.tpl new file mode 100644 index 0000000..f8fd213 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/templates/validations/_cassandra.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.cassandra.values.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.cassandra.dbUser.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.dbUser.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled cassandra. + +Usage: +{{ include "common.cassandra.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.cassandra.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.cassandra.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key dbUser + +Usage: +{{ include "common.cassandra.values.key.dbUser" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.key.dbUser" -}} + {{- if .subchart -}} + cassandra.dbUser + {{- else -}} + dbUser + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql/charts/common/templates/validations/_mariadb.tpl b/backing-services/gitea/charts/postgresql/charts/common/templates/validations/_mariadb.tpl new file mode 100644 index 0000000..6ea8c0f --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/templates/validations/_mariadb.tpl @@ -0,0 +1,108 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MariaDB required passwords are not empty. + +Usage: +{{ include "common.validations.values.mariadb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MariaDB values are stored, e.g: "mysql-passwords-secret" + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mariadb.passwords" -}} + {{- $existingSecret := include "common.mariadb.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mariadb.values.enabled" . -}} + {{- $architecture := include "common.mariadb.values.architecture" . -}} + {{- $authPrefix := include "common.mariadb.values.key.auth" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mariadb-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- if not (empty $valueUsername) -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mariadb-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replication") -}} + {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mariadb-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mariadb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mariadb. + +Usage: +{{ include "common.mariadb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mariadb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mariadb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mariadb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mariadb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.key.auth" -}} + {{- if .subchart -}} + mariadb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql/charts/common/templates/validations/_mongodb.tpl b/backing-services/gitea/charts/postgresql/charts/common/templates/validations/_mongodb.tpl new file mode 100644 index 0000000..e678a6d --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/templates/validations/_mongodb.tpl @@ -0,0 +1,67 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mongodb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDb is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mongodb. + +Usage: +{{ include "common.mongodb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mongodb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mongodb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mongodb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.key.auth" -}} + {{- if .subchart -}} + mongodb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mongodb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql/charts/common/templates/validations/_mysql.tpl b/backing-services/gitea/charts/postgresql/charts/common/templates/validations/_mysql.tpl new file mode 100644 index 0000000..fbb65c3 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/templates/validations/_mysql.tpl @@ -0,0 +1,67 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mysql.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mysql. + +Usage: +{{ include "common.mysql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mysql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mysql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mysql.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mysql.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.key.auth" -}} + {{- if .subchart -}} + mysql.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql/charts/common/templates/validations/_postgresql.tpl b/backing-services/gitea/charts/postgresql/charts/common/templates/validations/_postgresql.tpl new file mode 100644 index 0000000..51d4716 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/templates/validations/_postgresql.tpl @@ -0,0 +1,105 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to decide whether evaluate global values. + +Usage: +{{ include "common.postgresql.values.use.global" (dict "key" "key-of-global" "context" $) }} +Params: + - key - String - Required. Field to be evaluated within global, e.g: "existingSecret" +*/}} +{{- define "common.postgresql.values.use.global" -}} + {{- if .context.Values.global -}} + {{- if .context.Values.global.postgresql -}} + {{- index .context.Values.global.postgresql .key | quote -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.postgresql.values.existingSecret" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.existingSecret" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "existingSecret" "context" .context) -}} + + {{- if .subchart -}} + {{- default (.context.Values.postgresql.existingSecret | quote) $globalValue -}} + {{- else -}} + {{- default (.context.Values.existingSecret | quote) $globalValue -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled postgresql. + +Usage: +{{ include "common.postgresql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key postgressPassword. + +Usage: +{{ include "common.postgresql.values.key.postgressPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.postgressPassword" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "postgresqlUsername" "context" .context) -}} + + {{- if not $globalValue -}} + {{- if .subchart -}} + postgresql.postgresqlPassword + {{- else -}} + postgresqlPassword + {{- end -}} + {{- else -}} + global.postgresql.postgresqlPassword + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled.replication. + +Usage: +{{ include "common.postgresql.values.enabled.replication" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.enabled.replication" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.replication.enabled -}} + {{- else -}} + {{- printf "%v" .context.Values.replication.enabled -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key replication.password. + +Usage: +{{ include "common.postgresql.values.key.replicationPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.replicationPassword" -}} + {{- if .subchart -}} + postgresql.replication.password + {{- else -}} + replication.password + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql/charts/common/templates/validations/_redis.tpl b/backing-services/gitea/charts/postgresql/charts/common/templates/validations/_redis.tpl new file mode 100644 index 0000000..9fedfef --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/templates/validations/_redis.tpl @@ -0,0 +1,48 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for enabled redis. + +Usage: +{{ include "common.redis.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.redis.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.redis.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right prefix path for the values + +Usage: +{{ include "common.redis.values.key.prefix" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false +*/}} +{{- define "common.redis.values.keys.prefix" -}} + {{- if .subchart -}}redis.{{- else -}}{{- end -}} +{{- end -}} + +{{/* +Checks whether the redis chart's includes the standarizations (version >= 14) + +Usage: +{{ include "common.redis.values.standarized.version" (dict "context" $) }} +*/}} +{{- define "common.redis.values.standarized.version" -}} + + {{- $standarizedAuth := printf "%s%s" (include "common.redis.values.keys.prefix" .) "auth" -}} + {{- $standarizedAuthValues := include "common.utils.getValueFromKey" (dict "key" $standarizedAuth "context" .context) }} + + {{- if $standarizedAuthValues -}} + {{- true -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql/charts/common/templates/validations/_validations.tpl b/backing-services/gitea/charts/postgresql/charts/common/templates/validations/_validations.tpl new file mode 100644 index 0000000..7cdee61 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/templates/validations/_validations.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate values must not be empty. + +Usage: +{{- $validateValueConf00 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-01") -}} +{{ include "common.validations.values.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" +*/}} +{{- define "common.validations.values.multiple.empty" -}} + {{- range .required -}} + {{- include "common.validations.values.single.empty" (dict "valueKey" .valueKey "secret" .secret "field" .field "context" $.context) -}} + {{- end -}} +{{- end -}} + +{{/* +Validate a value must not be empty. + +Usage: +{{ include "common.validations.value.empty" (dict "valueKey" "mariadb.password" "secret" "secretName" "field" "my-password" "subchart" "subchart" "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" + - subchart - String - Optional - Name of the subchart that the validated password is part of. +*/}} +{{- define "common.validations.values.single.empty" -}} + {{- $value := include "common.utils.getValueFromKey" (dict "key" .valueKey "context" .context) }} + {{- $subchart := ternary "" (printf "%s." .subchart) (empty .subchart) }} + + {{- if not $value -}} + {{- $varname := "my-value" -}} + {{- $getCurrentValue := "" -}} + {{- if and .secret .field -}} + {{- $varname = include "common.utils.fieldToEnvVar" . -}} + {{- $getCurrentValue = printf " To get the current value:\n\n %s\n" (include "common.utils.secret.getvalue" .) -}} + {{- end -}} + {{- printf "\n '%s' must not be empty, please add '--set %s%s=$%s' to the command.%s" .valueKey $subchart .valueKey $varname $getCurrentValue -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql/charts/common/values.yaml b/backing-services/gitea/charts/postgresql/charts/common/values.yaml new file mode 100644 index 0000000..de2cac5 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/charts/common/values.yaml @@ -0,0 +1,8 @@ +# Copyright Broadcom, Inc. All Rights Reserved. +# SPDX-License-Identifier: APACHE-2.0 + +## bitnami/common +## It is required by CI/CD tools and processes. +## @skip exampleValue +## +exampleValue: common-chart diff --git a/backing-services/gitea/charts/postgresql/templates/NOTES.txt b/backing-services/gitea/charts/postgresql/templates/NOTES.txt new file mode 100644 index 0000000..1a086d2 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/NOTES.txt @@ -0,0 +1,123 @@ +{{- $releaseNamespace := include "common.names.namespace" . }} +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +⚠ WARNING: Since August 28th, 2025, only a limited subset of images/charts are available for free. + Subscribe to Bitnami Secure Images to receive continued support and security updates. + More info at https://bitnami.com and https://github.com/bitnami/containers/issues/83267 + +** Please be patient while the chart is being deployed ** + +{{- if .Values.diagnosticMode.enabled }} +The chart has been deployed in diagnostic mode. All probes have been disabled and the command has been overwritten with: + + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 4 }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 4 }} + +Get the list of pods by executing: + + kubectl get pods --namespace {{ $releaseNamespace }} -l app.kubernetes.io/instance={{ .Release.Name }} + +Access the pod you want to debug by executing + + kubectl exec --namespace {{ $releaseNamespace }} -ti -- /opt/bitnami/scripts/postgresql/entrypoint.sh /bin/bash + +In order to replicate the container startup scripts execute this command: + + /opt/bitnami/scripts/postgresql/entrypoint.sh /opt/bitnami/scripts/postgresql/run.sh + +{{- else }} + +{{- $customUser := include "postgresql.v1.username" . }} +{{- $postgresPassword := include "common.secrets.lookup" (dict "secret" (include "postgresql.v1.chart.fullname" .) "key" .Values.auth.secretKeys.adminPasswordKey "defaultValue" (ternary .Values.auth.postgresPassword .Values.auth.password (eq $customUser "postgres")) "context" $) -}} +{{- $authEnabled := and (not (or .Values.global.postgresql.auth.existingSecret .Values.auth.existingSecret)) (or $postgresPassword .Values.auth.enablePostgresUser (and (not (empty $customUser)) (ne $customUser "postgres"))) }} +{{- if not $authEnabled }} + +WARNING: PostgreSQL has been configured without authentication, this is not recommended for production environments. +{{- end }} + +PostgreSQL can be accessed via port {{ include "postgresql.v1.service.port" . }} on the following DNS names from within your cluster: + + {{ include "postgresql.v1.primary.fullname" . }}.{{ $releaseNamespace }}.svc.cluster.local - Read/Write connection + +{{- if eq .Values.architecture "replication" }} + + {{ include "postgresql.v1.readReplica.fullname" . }}.{{ $releaseNamespace }}.svc.cluster.local - Read only connection + +{{- end }} + +{{- if and (not (empty $customUser)) (ne $customUser "postgres") }} +{{- if .Values.auth.enablePostgresUser }} + +To get the password for "postgres" run: + + export POSTGRES_ADMIN_PASSWORD=$(kubectl get secret --namespace {{ $releaseNamespace }} {{ include "postgresql.v1.secretName" . }} -o jsonpath="{.data.{{include "postgresql.v1.adminPasswordKey" .}}}" | base64 -d) +{{- end }} + +To get the password for "{{ $customUser }}" run: + + export POSTGRES_PASSWORD=$(kubectl get secret --namespace {{ $releaseNamespace }} {{ include "postgresql.v1.secretName" . }} -o jsonpath="{.data.{{include "postgresql.v1.userPasswordKey" .}}}" | base64 -d) +{{- else }} +{{- if .Values.auth.enablePostgresUser }} + +To get the password for "{{ default "postgres" $customUser }}" run: + + export POSTGRES_PASSWORD=$(kubectl get secret --namespace {{ $releaseNamespace }} {{ include "postgresql.v1.secretName" . }} -o jsonpath="{.data.{{ ternary "password" (include "postgresql.v1.adminPasswordKey" .) (and (not (empty $customUser)) (ne $customUser "postgres")) }}}" | base64 -d) +{{- end }} +{{- end }} + +To connect to your database run the following command: + {{- if $authEnabled }} + + kubectl run {{ include "postgresql.v1.chart.fullname" . }}-client --rm --tty -i --restart='Never' --namespace {{ $releaseNamespace }} --image {{ include "postgresql.v1.image" . }} --env="PGPASSWORD=$POSTGRES_PASSWORD" \ + --command -- psql --host {{ include "postgresql.v1.primary.fullname" . }} -U {{ default "postgres" $customUser }} -d {{- if include "postgresql.v1.database" . }} {{ include "postgresql.v1.database" . }}{{- else }} postgres{{- end }} -p {{ include "postgresql.v1.service.port" . }} + {{- else }} + + kubectl run {{ include "postgresql.v1.chart.fullname" . }}-client --rm --tty -i --restart='Never' --namespace {{ $releaseNamespace }} --image {{ include "postgresql.v1.image" . }} \ + --command -- psql --host {{ include "postgresql.v1.primary.fullname" . }} -d {{- if include "postgresql.v1.database" . }} {{ include "postgresql.v1.database" . }}{{- else }} postgres{{- end }} -p {{ include "postgresql.v1.service.port" . }} + {{- end }} + + > NOTE: If you access the container using bash, make sure that you execute "/opt/bitnami/scripts/postgresql/entrypoint.sh /bin/bash" in order to avoid the error "psql: local user with ID {{ .Values.primary.containerSecurityContext.runAsUser }}} does not exist" + +To connect to your database from outside the cluster execute the following commands: + +{{- if contains "NodePort" .Values.primary.service.type }} + + export NODE_IP=$(kubectl get nodes --namespace {{ $releaseNamespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get --namespace {{ $releaseNamespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "postgresql.v1.primary.fullname" . }}) + {{- if $authEnabled }} + PGPASSWORD="$POSTGRES_PASSWORD" psql --host $NODE_IP --port $NODE_PORT -U {{ default "postgres" $customUser }} -d {{- if include "postgresql.v1.database" . }} {{ include "postgresql.v1.database" . }}{{- else }} postgres{{- end }} + {{- else }} + psql --host $NODE_IP --port $NODE_PORT -d {{- if include "postgresql.v1.database" . }} {{ include "postgresql.v1.database" . }}{{- else }} postgres{{- end }} + {{- end }} +{{- else if contains "LoadBalancer" .Values.primary.service.type }} + + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + Watch the status with: 'kubectl get svc --namespace {{ $releaseNamespace }} -w {{ include "postgresql.v1.primary.fullname" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ $releaseNamespace }} {{ include "postgresql.v1.primary.fullname" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") + {{- if $authEnabled }} + PGPASSWORD="$POSTGRES_PASSWORD" psql --host $SERVICE_IP --port {{ include "postgresql.v1.service.port" . }} -U {{ default "postgres" $customUser }} -d {{- if include "postgresql.v1.database" . }} {{ include "postgresql.v1.database" . }}{{- else }} postgres{{- end }} + {{- else }} + psql --host $SERVICE_IP --port {{ include "postgresql.v1.service.port" . }} -d {{- if include "postgresql.v1.database" . }} {{ include "postgresql.v1.database" . }}{{- else }} postgres{{- end }} + {{- end }} +{{- else if contains "ClusterIP" .Values.primary.service.type }} + + kubectl port-forward --namespace {{ $releaseNamespace }} svc/{{ include "postgresql.v1.primary.fullname" . }} {{ include "postgresql.v1.service.port" . }}:{{ include "postgresql.v1.service.port" . }} & + {{- if $authEnabled }} + PGPASSWORD="$POSTGRES_PASSWORD" psql --host 127.0.0.1 -U {{ default "postgres" $customUser }} -d {{- if include "postgresql.v1.database" . }} {{ include "postgresql.v1.database" . }}{{- else }} postgres{{- end }} -p {{ include "postgresql.v1.service.port" . }} + {{- else }} + psql --host 127.0.0.1 -d {{- if include "postgresql.v1.database" . }} {{ include "postgresql.v1.database" . }}{{- else }} postgres{{- end }} -p {{ include "postgresql.v1.service.port" . }} + {{- end }} +{{- end }} +{{- end }} + +WARNING: The configured password will be ignored on new installation in case when previous PostgreSQL release was deleted through the helm command. In that case, old PVC will have an old password, and setting it through helm won't take effect. Deleting persistent volumes (PVs) will solve the issue. + +{{- include "postgresql.v1.validateValues" . -}} +{{- include "common.warnings.rollingTag" .Values.image -}} +{{- include "common.warnings.rollingTag" .Values.volumePermissions.image }} +{{- include "common.warnings.resources" (dict "sections" (list "metrics" "primary" "readReplicas" "volumePermissions") "context" $) }} +{{- include "common.warnings.modifiedImages" (dict "images" (list .Values.image .Values.volumePermissions.image .Values.metrics.image) "context" $) }} +{{- include "common.errors.insecureImages" (dict "images" (list .Values.image .Values.volumePermissions.image .Values.metrics.image) "context" $) }} diff --git a/backing-services/gitea/charts/postgresql/templates/_helpers.tpl b/backing-services/gitea/charts/postgresql/templates/_helpers.tpl new file mode 100644 index 0000000..c582fc1 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/_helpers.tpl @@ -0,0 +1,458 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Create a global name for the chart to use and parse with other naming functions +Please use instead of "common.names.fullname" to preserve support for .Values.global.postgresql.fullnameOverride +*/}} +{{- define "postgresql.v1.chart.fullname" -}} +{{- default (include "common.names.fullname" .) .Values.global.postgresql.fullnameOverride -}} +{{- end -}} + +{{/* +Create a default fully qualified app name for PostgreSQL Primary objects +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "postgresql.v1.primary.fullname" -}} +{{- $fullname := include "postgresql.v1.chart.fullname" . -}} +{{- ternary (printf "%s-%s" $fullname .Values.primary.name | trunc 63 | trimSuffix "-") $fullname (eq .Values.architecture "replication") -}} +{{- end -}} + +{{/* +Create a default fully qualified app name for PostgreSQL read-only replicas objects +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "postgresql.v1.readReplica.fullname" -}} +{{- printf "%s-%s" (include "postgresql.v1.chart.fullname" .) .Values.readReplicas.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create the default FQDN for PostgreSQL primary headless service +We truncate at 63 chars because of the DNS naming spec. +*/}} +{{- define "postgresql.v1.primary.svc.headless" -}} +{{- printf "%s-hl" (include "postgresql.v1.primary.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create the default FQDN for PostgreSQL read-only replicas headless service +We truncate at 63 chars because of the DNS naming spec. +*/}} +{{- define "postgresql.v1.readReplica.svc.headless" -}} +{{- printf "%s-hl" (include "postgresql.v1.readReplica.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Return the proper PostgreSQL image name +*/}} +{{- define "postgresql.v1.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper PostgreSQL metrics image name +*/}} +{{- define "postgresql.v1.metrics.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.metrics.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper image name (for the init container volume-permissions image) +*/}} +{{- define "postgresql.v1.volumePermissions.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.volumePermissions.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "postgresql.v1.imagePullSecrets" -}} +{{ include "common.images.renderPullSecrets" (dict "images" (list .Values.image .Values.metrics.image .Values.volumePermissions.image) "context" $) }} +{{- end -}} + +{{/* +Return the name for a custom user to create +*/}} +{{- define "postgresql.v1.username" -}} +{{- if .Values.global.postgresql.auth.username -}} + {{- .Values.global.postgresql.auth.username -}} +{{- else -}} + {{- .Values.auth.username -}} +{{- end -}} +{{- end -}} + +{{/* +Return the name for a custom database to create +*/}} +{{- define "postgresql.v1.database" -}} +{{- if .Values.global.postgresql.auth.database -}} + {{- printf "%s" (tpl .Values.global.postgresql.auth.database $) -}} +{{- else if .Values.auth.database -}} + {{- printf "%s" (tpl .Values.auth.database $) -}} +{{- end -}} +{{- end -}} + +{{/* +Get the password secret. +*/}} +{{- define "postgresql.v1.secretName" -}} +{{- if .Values.global.postgresql.auth.existingSecret -}} + {{- printf "%s" (tpl .Values.global.postgresql.auth.existingSecret $) -}} +{{- else if .Values.auth.existingSecret -}} + {{- printf "%s" (tpl .Values.auth.existingSecret $) -}} +{{- else -}} + {{- printf "%s" (include "postgresql.v1.chart.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Get the replication-password key. +*/}} +{{- define "postgresql.v1.replicationPasswordKey" -}} +{{- if or .Values.global.postgresql.auth.existingSecret .Values.auth.existingSecret -}} + {{- if .Values.global.postgresql.auth.secretKeys.replicationPasswordKey -}} + {{- printf "%s" (tpl .Values.global.postgresql.auth.secretKeys.replicationPasswordKey $) -}} + {{- else if .Values.auth.secretKeys.replicationPasswordKey -}} + {{- printf "%s" (tpl .Values.auth.secretKeys.replicationPasswordKey $) -}} + {{- else -}} + {{- "replication-password" -}} + {{- end -}} +{{- else -}} + {{- "replication-password" -}} +{{- end -}} +{{- end -}} + +{{/* +Get the admin-password key. +*/}} +{{- define "postgresql.v1.adminPasswordKey" -}} +{{- if or .Values.global.postgresql.auth.existingSecret .Values.auth.existingSecret -}} + {{- if .Values.global.postgresql.auth.secretKeys.adminPasswordKey -}} + {{- printf "%s" (tpl .Values.global.postgresql.auth.secretKeys.adminPasswordKey $) -}} + {{- else if .Values.auth.secretKeys.adminPasswordKey -}} + {{- printf "%s" (tpl .Values.auth.secretKeys.adminPasswordKey $) -}} + {{- end -}} +{{- else -}} + {{- "postgres-password" -}} +{{- end -}} +{{- end -}} + +{{/* +Get the user-password key. +*/}} +{{- define "postgresql.v1.userPasswordKey" -}} +{{- if or .Values.global.postgresql.auth.existingSecret .Values.auth.existingSecret -}} + {{- if or (empty (include "postgresql.v1.username" .)) (eq (include "postgresql.v1.username" .) "postgres") -}} + {{- printf "%s" (include "postgresql.v1.adminPasswordKey" .) -}} + {{- else -}} + {{- if .Values.global.postgresql.auth.secretKeys.userPasswordKey -}} + {{- printf "%s" (tpl .Values.global.postgresql.auth.secretKeys.userPasswordKey $) -}} + {{- else if .Values.auth.secretKeys.userPasswordKey -}} + {{- printf "%s" (tpl .Values.auth.secretKeys.userPasswordKey $) -}} + {{- end -}} + {{- end -}} +{{- else -}} + {{- "password" -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a secret object should be created +*/}} +{{- define "postgresql.v1.createSecret" -}} +{{- $customUser := include "postgresql.v1.username" . -}} +{{- $postgresPassword := include "common.secrets.lookup" (dict "secret" (include "postgresql.v1.chart.fullname" .) "key" .Values.auth.secretKeys.adminPasswordKey "defaultValue" (ternary (coalesce .Values.global.postgresql.auth.postgresPassword .Values.auth.postgresPassword .Values.global.postgresql.auth.password .Values.auth.password) (coalesce .Values.global.postgresql.auth.postgresPassword .Values.auth.postgresPassword) (or (empty $customUser) (eq $customUser "postgres"))) "context" $) -}} +{{- if and (not (or .Values.global.postgresql.auth.existingSecret .Values.auth.existingSecret)) (or $postgresPassword .Values.auth.enablePostgresUser (and (not (empty $customUser)) (ne $customUser "postgres")) (eq .Values.architecture "replication") (and .Values.ldap.enabled (or .Values.ldap.bind_password .Values.ldap.bindpw))) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a secret object should be created for PostgreSQL +*/}} +{{- define "postgresql.v1.createPreviousSecret" -}} +{{- if and .Values.passwordUpdateJob.previousPasswords.postgresPassword (not .Values.passwordUpdateJob.previousPasswords.existingSecret) }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the secret with previous PostgreSQL credentials +*/}} +{{- define "postgresql.v1.update-job.previousSecretName" -}} + {{- if .Values.passwordUpdateJob.previousPasswords.existingSecret -}} + {{- /* The secret with the new password is managed externally */ -}} + {{- tpl .Values.passwordUpdateJob.previousPasswords.existingSecret $ -}} + {{- else if .Values.passwordUpdateJob.previousPasswords.postgresPassword -}} + {{- /* The secret with the new password is managed externally */ -}} + {{- printf "%s-previous-secret" (include "postgresql.v1.chart.fullname" .) | trunc 63 | trimSuffix "-" -}} + {{- else -}} + {{- /* The secret with the new password is managed by the helm chart. We use the current secret name as it has the old password */ -}} + {{- include "postgresql.v1.chart.fullname" . -}} + {{- end -}} +{{- end -}} + +{{/* +Return the secret with new PostgreSQL credentials +*/}} +{{- define "postgresql.v1.update-job.newSecretName" -}} + {{- if and (not .Values.passwordUpdateJob.previousPasswords.existingSecret) (not .Values.passwordUpdateJob.previousPasswords.postgresPassword) -}} + {{- /* The secret with the new password is managed by the helm chart. We create a new secret as the current one has the old password */ -}} + {{- printf "%s-new-secret" (include "postgresql.v1.chart.fullname" .) | trunc 63 | trimSuffix "-" -}} + {{- else -}} + {{- /* The secret with the new password is managed externally */ -}} + {{- include "postgresql.v1.secretName" . -}} + {{- end -}} +{{- end -}} + +{{/* +Return PostgreSQL service port +*/}} +{{- define "postgresql.v1.service.port" -}} +{{- if .Values.global.postgresql.service.ports.postgresql -}} + {{- .Values.global.postgresql.service.ports.postgresql -}} +{{- else -}} + {{- .Values.primary.service.ports.postgresql -}} +{{- end -}} +{{- end -}} + +{{/* +Return PostgreSQL service port +*/}} +{{- define "postgresql.v1.readReplica.service.port" -}} +{{- if .Values.global.postgresql.service.ports.postgresql -}} + {{- .Values.global.postgresql.service.ports.postgresql -}} +{{- else -}} + {{- .Values.readReplicas.service.ports.postgresql -}} +{{- end -}} +{{- end -}} + +{{/* +Get the PostgreSQL primary configuration ConfigMap name. +*/}} +{{- define "postgresql.v1.primary.configmapName" -}} +{{- if .Values.primary.existingConfigmap -}} + {{- printf "%s" (tpl .Values.primary.existingConfigmap $) -}} +{{- else -}} + {{- printf "%s-configuration" (include "postgresql.v1.primary.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a configmap object should be created for PostgreSQL primary with the configuration +*/}} +{{- define "postgresql.v1.primary.createConfigmap" -}} +{{- if and (or .Values.primary.configuration .Values.primary.pgHbaConfiguration) (not .Values.primary.existingConfigmap) -}} + {{- true -}} +{{- else -}} +{{- end -}} +{{- end -}} + +{{/* +Get the PostgreSQL primary extended configuration ConfigMap name. +*/}} +{{- define "postgresql.v1.primary.extendedConfigmapName" -}} +{{- if .Values.primary.existingExtendedConfigmap -}} + {{- printf "%s" (tpl .Values.primary.existingExtendedConfigmap $) -}} +{{- else -}} + {{- printf "%s-extended-configuration" (include "postgresql.v1.primary.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Get the PostgreSQL read replica extended configuration ConfigMap name. +*/}} +{{- define "postgresql.v1.readReplicas.extendedConfigmapName" -}} + {{- printf "%s-extended-configuration" (include "postgresql.v1.readReplica.fullname" .) -}} +{{- end -}} + +{{/* +Return true if a configmap object should be created for PostgreSQL primary with the extended configuration +*/}} +{{- define "postgresql.v1.primary.createExtendedConfigmap" -}} +{{- if and .Values.primary.extendedConfiguration (not .Values.primary.existingExtendedConfigmap) -}} + {{- true -}} +{{- else -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a configmap object should be created for PostgreSQL read replica with the extended configuration +*/}} +{{- define "postgresql.v1.readReplicas.createExtendedConfigmap" -}} +{{- if .Values.readReplicas.extendedConfiguration -}} + {{- true -}} +{{- else -}} +{{- end -}} +{{- end -}} + +{{/* + Create the name of the service account to use + */}} +{{- define "postgresql.v1.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "postgresql.v1.chart.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Return true if a configmap should be mounted with PostgreSQL configuration +*/}} +{{- define "postgresql.v1.mountConfigurationCM" -}} +{{- if or .Values.primary.configuration .Values.primary.pgHbaConfiguration .Values.primary.existingConfigmap -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Get the pre-initialization scripts ConfigMap name. +*/}} +{{- define "postgresql.v1.preInitDb.scriptsCM" -}} +{{- if .Values.primary.preInitDb.scriptsConfigMap -}} + {{- printf "%s" (tpl .Values.primary.preInitDb.scriptsConfigMap $) -}} +{{- else -}} + {{- printf "%s-preinit-scripts" (include "postgresql.v1.primary.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Get the initialization scripts ConfigMap name. +*/}} +{{- define "postgresql.v1.initdb.scriptsCM" -}} +{{- if .Values.primary.initdb.scriptsConfigMap -}} + {{- printf "%s" (tpl .Values.primary.initdb.scriptsConfigMap $) -}} +{{- else -}} + {{- printf "%s-init-scripts" (include "postgresql.v1.primary.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if TLS is enabled for LDAP connection +*/}} +{{- define "postgresql.v1.ldap.tls.enabled" -}} +{{- if and (kindIs "string" .Values.ldap.tls) (not (empty .Values.ldap.tls)) -}} + {{- true -}} +{{- else if and (kindIs "map" .Values.ldap.tls) .Values.ldap.tls.enabled -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Get the readiness probe command +*/}} +{{- define "postgresql.v1.readinessProbeCommand" -}} +{{- $customUser := include "postgresql.v1.username" . -}} +- | +{{- if (include "postgresql.v1.database" .) }} + exec pg_isready -U {{ default "postgres" $customUser | quote }} -d "dbname={{ include "postgresql.v1.database" . }} {{- if .Values.tls.enabled }} sslcert={{ include "postgresql.v1.tlsCert" . }} sslkey={{ include "postgresql.v1.tlsCertKey" . }}{{- end }}" -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }} +{{- else }} + exec pg_isready -U {{ default "postgres" $customUser | quote }} {{- if .Values.tls.enabled }} -d "sslcert={{ include "postgresql.v1.tlsCert" . }} sslkey={{ include "postgresql.v1.tlsCertKey" . }}"{{- end }} -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }} +{{- end }} + [ -f /opt/bitnami/postgresql/tmp/.initialized ] || [ -f /bitnami/postgresql/.initialized ] +{{- end -}} + +{{/* +Compile all warnings into a single message, and call fail. +*/}} +{{- define "postgresql.v1.validateValues" -}} +{{- $messages := list -}} +{{- $messages := append $messages (include "postgresql.v1.validateValues.ldapConfigurationMethod" .) -}} +{{- $messages := append $messages (include "postgresql.v1.validateValues.psp" .) -}} +{{- $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.v1.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 -}} + +{{/* +Validate values of Postgresql - If PSP is enabled RBAC should be enabled too +*/}} +{{- define "postgresql.v1.validateValues.psp" -}} +{{- if and .Values.psp.create (not .Values.rbac.create) -}} +postgresql: psp.create, rbac.create + RBAC should be enabled if PSP is enabled in order for PSP to work. + More info at https://kubernetes.io/docs/concepts/policy/pod-security-policy/#authorizing-policies +{{- end -}} +{{- end -}} + +{{/* +Return the path to the cert file. +*/}} +{{- define "postgresql.v1.tlsCert" -}} +{{- if .Values.tls.autoGenerated -}} + {{- printf "/opt/bitnami/postgresql/certs/tls.crt" -}} +{{- else -}} + {{- required "Certificate filename is required when TLS in enabled" .Values.tls.certFilename | printf "/opt/bitnami/postgresql/certs/%s" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the cert key file. +*/}} +{{- define "postgresql.v1.tlsCertKey" -}} +{{- if .Values.tls.autoGenerated -}} + {{- printf "/opt/bitnami/postgresql/certs/tls.key" -}} +{{- else -}} +{{- required "Certificate Key filename is required when TLS in enabled" .Values.tls.certKeyFilename | printf "/opt/bitnami/postgresql/certs/%s" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the CA cert file. +*/}} +{{- define "postgresql.v1.tlsCACert" -}} +{{- if .Values.tls.autoGenerated -}} + {{- printf "/opt/bitnami/postgresql/certs/ca.crt" -}} +{{- else -}} + {{- printf "/opt/bitnami/postgresql/certs/%s" .Values.tls.certCAFilename -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the CRL file. +*/}} +{{- define "postgresql.v1.tlsCRL" -}} +{{- if .Values.tls.crlFilename -}} +{{- printf "/opt/bitnami/postgresql/certs/%s" .Values.tls.crlFilename -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a TLS credentials secret object should be created +*/}} +{{- define "postgresql.v1.createTlsSecret" -}} +{{- if and .Values.tls.autoGenerated (not .Values.tls.certificatesSecret) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the CA cert file. +*/}} +{{- define "postgresql.v1.tlsSecretName" -}} +{{- if .Values.tls.autoGenerated -}} + {{- printf "%s-crt" (include "postgresql.v1.chart.fullname" .) -}} +{{- else -}} + {{ tpl (required "A secret containing TLS certificates is required when TLS is enabled" .Values.tls.certificatesSecret) . }} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/postgresql/templates/backup/cronjob.yaml b/backing-services/gitea/charts/postgresql/templates/backup/cronjob.yaml new file mode 100644 index 0000000..d3afb07 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/backup/cronjob.yaml @@ -0,0 +1,147 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.backup.enabled }} +{{- $customUser := include "postgresql.v1.username" . }} +apiVersion: batch/v1 +kind: CronJob +metadata: + name: {{ include "postgresql.v1.primary.fullname" . }}-pgdumpall + namespace: {{ include "common.names.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.backup.cronjob.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: pg_dumpall + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.backup.cronjob.annotations .Values.commonAnnotations ) "context" . ) }} + {{- if $annotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + schedule: {{ quote .Values.backup.cronjob.schedule }} + {{- if .Values.backup.cronjob.timeZone }} + timeZone: {{ .Values.backup.cronjob.timeZone | quote }} + {{- end }} + concurrencyPolicy: {{ .Values.backup.cronjob.concurrencyPolicy }} + failedJobsHistoryLimit: {{ .Values.backup.cronjob.failedJobsHistoryLimit }} + successfulJobsHistoryLimit: {{ .Values.backup.cronjob.successfulJobsHistoryLimit }} + {{- if .Values.backup.cronjob.startingDeadlineSeconds }} + startingDeadlineSeconds: {{ .Values.backup.cronjob.startingDeadlineSeconds }} + {{- end }} + jobTemplate: + spec: + {{- if .Values.backup.cronjob.ttlSecondsAfterFinished }} + ttlSecondsAfterFinished: {{ .Values.backup.cronjob.ttlSecondsAfterFinished }} + {{- end }} + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 12 }} + app.kubernetes.io/component: pg_dumpall + {{- if $annotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 12 }} + {{- end }} + spec: + {{- include "postgresql.v1.imagePullSecrets" . | nindent 10 }} + {{- if .Values.backup.cronjob.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.nodeSelector "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.backup.cronjob.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.tolerations "context" $) | nindent 12 }} + {{- end }} + containers: + - name: {{ include "postgresql.v1.primary.fullname" . }}-pgdumpall + image: {{ include "postgresql.v1.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + env: + - name: PGUSER + {{- if .Values.auth.enablePostgresUser }} + value: postgres + {{- else }} + value: {{ $customUser | quote }} + {{- end }} + {{- if .Values.auth.usePasswordFiles }} + - name: PGPASSWORD_FILE + value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (include "postgresql.v1.adminPasswordKey" .) }} + {{- else }} + - name: PGPASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql.v1.secretName" . }} + key: {{ include "postgresql.v1.adminPasswordKey" . }} + {{- end }} + - name: PGHOST + value: {{ include "postgresql.v1.primary.fullname" . }} + - name: PGPORT + value: {{ include "postgresql.v1.service.port" . | quote }} + - name: PGDUMP_DIR + value: {{ .Values.backup.cronjob.storage.mountPath }} + {{- if .Values.tls.enabled }} + - name: PGSSLROOTCERT + {{- if .Values.tls.autoGenerated }} + value: /tmp/certs/ca.crt + {{- else }} + value: {{ printf "/tmp/certs/%s" .Values.tls.certCAFilename }} + {{- end }} + {{- end }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.command "context" $) | nindent 14 }} + volumeMounts: + {{- if .Values.tls.enabled }} + - name: raw-certificates + mountPath: /tmp/certs + {{- end }} + {{- if .Values.backup.cronjob.storage.enabled }} + - name: datadir + mountPath: {{ .Values.backup.cronjob.storage.mountPath }} + subPath: {{ .Values.backup.cronjob.storage.subPath }} + {{- end }} + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if .Values.auth.usePasswordFiles }} + - name: postgresql-password + mountPath: /opt/bitnami/postgresql/secrets/ + {{- end }} + {{- if .Values.backup.cronjob.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.extraVolumeMounts "context" $) | nindent 14 }} + {{- end }} + {{- if .Values.backup.cronjob.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.backup.cronjob.containerSecurityContext "context" $) | nindent 14 }} + {{- end }} + {{- if .Values.backup.cronjob.resources }} + resources: {{- toYaml .Values.backup.cronjob.resources | nindent 14 }} + {{- else if ne .Values.backup.cronjob.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.backup.cronjob.resourcesPreset) | nindent 14 }} + {{- end }} + restartPolicy: {{ .Values.backup.cronjob.restartPolicy }} + {{- if .Values.backup.cronjob.podSecurityContext.enabled }} + securityContext: + fsGroup: {{ .Values.backup.cronjob.podSecurityContext.fsGroup }} + {{- end }} + volumes: + {{- if .Values.tls.enabled }} + - name: raw-certificates + secret: + secretName: {{ include "postgresql.v1.tlsSecretName" . }} + {{- end }} + {{- if .Values.backup.cronjob.storage.enabled }} + {{- if .Values.backup.cronjob.storage.existingClaim }} + - name: datadir + persistentVolumeClaim: + claimName: {{ printf "%s" (tpl .Values.backup.cronjob.storage.existingClaim .) }} + {{- else }} + - name: datadir + persistentVolumeClaim: + claimName: {{ include "postgresql.v1.primary.fullname" . }}-pgdumpall + {{- end }} + {{- end }} + - name: empty-dir + emptyDir: {} + {{- if .Values.auth.usePasswordFiles }} + - name: postgresql-password + secret: + secretName: {{ include "postgresql.v1.secretName" . }} + {{- end }} + {{- if .Values.backup.cronjob.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.backup.cronjob.extraVolumes "context" $ ) | nindent 12 }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/backup/networkpolicy.yaml b/backing-services/gitea/charts/postgresql/templates/backup/networkpolicy.yaml new file mode 100644 index 0000000..21e1add --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/backup/networkpolicy.yaml @@ -0,0 +1,32 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.backup.enabled .Values.backup.cronjob.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ include "common.capabilities.networkPolicy.apiVersion" . }} +metadata: + name: {{ include "postgresql.v1.primary.fullname" . }}-pgdumpall + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: pg_dumpall + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.backup.cronjob.podLabels .Values.commonLabels ) "context" . ) }} + podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: pg_dumpall + policyTypes: + - Egress + egress: + - ports: + - port: 5432 + protocol: TCP + - port: 53 + protocol: TCP + - port: 53 + protocol: UDP +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/backup/pvc.yaml b/backing-services/gitea/charts/postgresql/templates/backup/pvc.yaml new file mode 100644 index 0000000..674ac3d --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/backup/pvc.yaml @@ -0,0 +1,34 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.backup.enabled .Values.backup.cronjob.storage.enabled (not .Values.backup.cronjob.storage.existingClaim) -}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "postgresql.v1.primary.fullname" . }}-pgdumpall + namespace: {{ include "common.names.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.backup.cronjob.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: pg_dumpall + {{- if or .Values.backup.cronjob.annotations .Values.commonAnnotations .Values.backup.cronjob.storage.resourcePolicy }} + annotations: + {{- if or .Values.backup.cronjob.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.backup.cronjob.annotations .Values.commonAnnotations ) "context" . ) }} + {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.backup.cronjob.storage.resourcePolicy }} + helm.sh/resource-policy: {{ .Values.backup.cronjob.storage.resourcePolicy | quote }} + {{- end }} + {{- end }} +spec: + accessModes: + {{- range .Values.backup.cronjob.storage.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.backup.cronjob.storage.size | quote }} + {{ include "common.storage.class" (dict "persistence" .Values.backup.cronjob.storage "global" .Values.global) }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/extra-list.yaml b/backing-services/gitea/charts/postgresql/templates/extra-list.yaml new file mode 100644 index 0000000..329f5c6 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/extra-list.yaml @@ -0,0 +1,9 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/primary/configmap.yaml b/backing-services/gitea/charts/postgresql/templates/primary/configmap.yaml new file mode 100644 index 0000000..ad231e5 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/primary/configmap.yaml @@ -0,0 +1,26 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "postgresql.v1.primary.createConfigmap" .) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-configuration" (include "postgresql.v1.primary.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: primary + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + {{- if .Values.primary.configuration }} + postgresql.conf: | + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.configuration "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.primary.pgHbaConfiguration }} + pg_hba.conf: | + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.pgHbaConfiguration "context" $ ) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/primary/extended-configmap.yaml b/backing-services/gitea/charts/postgresql/templates/primary/extended-configmap.yaml new file mode 100644 index 0000000..2d228e4 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/primary/extended-configmap.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "postgresql.v1.primary.createExtendedConfigmap" .) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-extended-configuration" (include "postgresql.v1.primary.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: primary + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + override.conf: |- + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.extendedConfiguration "context" $ ) | nindent 4 }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/primary/initialization-configmap.yaml b/backing-services/gitea/charts/postgresql/templates/primary/initialization-configmap.yaml new file mode 100644 index 0000000..450812a --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/primary/initialization-configmap.yaml @@ -0,0 +1,17 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.primary.initdb.scripts (not .Values.primary.initdb.scriptsConfigMap) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-init-scripts" (include "postgresql.v1.primary.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: {{- include "common.tplvalues.render" (dict "value" .Values.primary.initdb.scripts "context" .) | nindent 2 }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/primary/metrics-configmap.yaml b/backing-services/gitea/charts/postgresql/templates/primary/metrics-configmap.yaml new file mode 100644 index 0000000..9bf889a --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/primary/metrics-configmap.yaml @@ -0,0 +1,18 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.customMetrics }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-metrics" (include "postgresql.v1.primary.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + custom-metrics.yaml: {{ toYaml .Values.metrics.customMetrics | quote }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/primary/metrics-svc.yaml b/backing-services/gitea/charts/postgresql/templates/primary/metrics-svc.yaml new file mode 100644 index 0000000..2e77c5b --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/primary/metrics-svc.yaml @@ -0,0 +1,31 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.metrics.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-metrics" (include "postgresql.v1.primary.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: metrics + {{- if or .Values.commonAnnotations .Values.metrics.service.annotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + sessionAffinity: {{ .Values.metrics.service.sessionAffinity }} + {{- if .Values.metrics.service.clusterIP }} + clusterIP: {{ .Values.metrics.service.clusterIP }} + {{- end }} + ports: + - name: http-metrics + port: {{ .Values.metrics.service.ports.metrics }} + targetPort: http-metrics + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: primary +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/primary/networkpolicy.yaml b/backing-services/gitea/charts/postgresql/templates/primary/networkpolicy.yaml new file mode 100644 index 0000000..6e5e28f --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/primary/networkpolicy.yaml @@ -0,0 +1,78 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.primary.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ include "common.capabilities.networkPolicy.apiVersion" . }} +metadata: + name: {{ include "postgresql.v1.primary.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: primary + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.podLabels .Values.commonLabels ) "context" . ) }} + podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: primary + policyTypes: + - Ingress + - Egress + {{- if .Values.primary.networkPolicy.allowExternalEgress }} + egress: + - {} + {{- else }} + egress: + # Allow dns resolution + - ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + # Allow outbound connections to read-replicas + - ports: + - port: {{ .Values.containerPorts.postgresql }} + to: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }} + app.kubernetes.io/component: read + {{- if .Values.primary.networkPolicy.extraEgress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.networkPolicy.extraEgress "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} + ingress: + - ports: + - port: {{ .Values.containerPorts.postgresql }} + {{- if .Values.metrics.enabled }} + - port: {{ .Values.metrics.containerPorts.metrics }} + {{- end }} + {{- if not .Values.primary.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 14 }} + - podSelector: + matchLabels: + {{ template "postgresql.v1.primary.fullname" . }}-client: "true" + {{- if .Values.primary.networkPolicy.ingressNSMatchLabels }} + - namespaceSelector: + matchLabels: + {{- range $key, $value := .Values.primary.networkPolicy.ingressNSMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{- if .Values.primary.networkPolicy.ingressNSPodMatchLabels }} + podSelector: + matchLabels: + {{- range $key, $value := .Values.primary.networkPolicy.ingressNSPodMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.primary.networkPolicy.extraIngress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.networkPolicy.extraIngress "context" $ ) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/primary/pdb.yaml b/backing-services/gitea/charts/postgresql/templates/primary/pdb.yaml new file mode 100644 index 0000000..a03fb20 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/primary/pdb.yaml @@ -0,0 +1,29 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.primary.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "postgresql.v1.primary.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: primary + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.primary.pdb.minAvailable }} + minAvailable: {{ .Values.primary.pdb.minAvailable }} + {{- end }} + {{- if or .Values.primary.pdb.maxUnavailable ( not .Values.primary.pdb.minAvailable ) }} + maxUnavailable: {{ .Values.primary.pdb.maxUnavailable | default 1 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: primary +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/primary/preinitialization-configmap.yaml b/backing-services/gitea/charts/postgresql/templates/primary/preinitialization-configmap.yaml new file mode 100644 index 0000000..ae6d188 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/primary/preinitialization-configmap.yaml @@ -0,0 +1,17 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.primary.preInitDb.scripts (not .Values.primary.preInitDb.scriptsConfigMap) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-preinit-scripts" (include "postgresql.v1.primary.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: {{- include "common.tplvalues.render" (dict "value" .Values.primary.preInitDb.scripts "context" .) | nindent 2 }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/primary/servicemonitor.yaml b/backing-services/gitea/charts/postgresql/templates/primary/servicemonitor.yaml new file mode 100644 index 0000000..b17d7f5 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/primary/servicemonitor.yaml @@ -0,0 +1,46 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "postgresql.v1.primary.fullname" . }} + namespace: {{ coalesce .Values.metrics.serviceMonitor.namespace (include "common.names.namespace" .) | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.serviceMonitor.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: metrics + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.metrics.serviceMonitor.jobLabel }} + jobLabel: {{ .Values.metrics.serviceMonitor.jobLabel }} + {{- end }} + selector: + {{- $svcLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.serviceMonitor.selector .Values.commonLabels ) "context" . ) }} + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $svcLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: metrics + 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 }} + {{- if .Values.metrics.serviceMonitor.relabelings }} + relabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.relabelings "context" $) | nindent 6 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.metricRelabelings "context" $) | nindent 6 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.honorLabels }} + honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }} + {{- end }} + namespaceSelector: + matchNames: + - {{ include "common.names.namespace" . | quote }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/primary/statefulset.yaml b/backing-services/gitea/charts/postgresql/templates/primary/statefulset.yaml new file mode 100644 index 0000000..d45d617 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/primary/statefulset.yaml @@ -0,0 +1,705 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- $customUser := include "postgresql.v1.username" . }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ include "postgresql.v1.primary.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: primary + {{- if or .Values.commonAnnotations .Values.primary.annotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + replicas: 1 + serviceName: {{ include "postgresql.v1.primary.svc.headless" . }} + {{- if .Values.primary.updateStrategy }} + updateStrategy: {{- toYaml .Values.primary.updateStrategy | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: primary + template: + metadata: + name: {{ include "postgresql.v1.primary.fullname" . }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: primary + {{- if or .Values.passwordUpdateJob.enabled (include "postgresql.v1.primary.createConfigmap" .) (include "postgresql.v1.primary.createExtendedConfigmap" .) .Values.primary.podAnnotations }} + annotations: + {{- if (include "postgresql.v1.primary.createConfigmap" .) }} + checksum/configuration: {{ pick (include (print $.Template.BasePath "/primary/configmap.yaml") . | fromYaml) "data" | toYaml | sha256sum }} + {{- end }} + {{- if (include "postgresql.v1.primary.createExtendedConfigmap" .) }} + checksum/extended-configuration: {{ pick (include (print $.Template.BasePath "/primary/extended-configmap.yaml") . | fromYaml) "data" | toYaml | sha256sum }} + {{- end }} + {{- if .Values.passwordUpdateJob.enabled }} + charts.bitnami.com/password-last-update: {{ now | date "20060102150405" | quote }} + {{- end }} + {{- if .Values.primary.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.podAnnotations "context" $ ) | nindent 8 }} + {{- end }} + {{- end }} + spec: + {{- if .Values.primary.extraPodSpec }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.extraPodSpec "context" $) | nindent 6 }} + {{- end }} + serviceAccountName: {{ include "postgresql.v1.serviceAccountName" . }} + {{- include "postgresql.v1.imagePullSecrets" . | nindent 6 }} + automountServiceAccountToken: {{ .Values.primary.automountServiceAccountToken }} + {{- if .Values.primary.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.primary.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.primary.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.primary.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.primary.podAffinityPreset "component" "primary" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.primary.podAntiAffinityPreset "component" "primary" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.primary.nodeAffinityPreset.type "key" .Values.primary.nodeAffinityPreset.key "values" .Values.primary.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.primary.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.primary.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.primary.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.primary.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.primary.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.primary.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.primary.priorityClassName }} + priorityClassName: {{ .Values.primary.priorityClassName }} + {{- end }} + {{- if .Values.primary.schedulerName }} + schedulerName: {{ .Values.primary.schedulerName | quote }} + {{- end }} + {{- if .Values.primary.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.primary.terminationGracePeriodSeconds }} + {{- end }} + {{- if .Values.primary.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.primary.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + hostNetwork: {{ .Values.primary.hostNetwork }} + hostIPC: {{ .Values.primary.hostIPC }} + {{- if or (and .Values.tls.enabled (not .Values.volumePermissions.enabled)) (and .Values.volumePermissions.enabled (or .Values.primary.persistence.enabled .Values.shmVolume.enabled)) .Values.primary.initContainers }} + initContainers: + {{- if and .Values.tls.enabled (not .Values.volumePermissions.enabled) }} + - name: copy-certs + image: {{ include "postgresql.v1.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + {{- if .Values.primary.resources }} + resources: {{- toYaml .Values.primary.resources | nindent 12 }} + {{- else if ne .Values.primary.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.primary.resourcesPreset) | nindent 12 }} + {{- end }} + # We don't require a privileged container in this case + {{- if .Values.primary.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.primary.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + command: + - /bin/sh + - -ec + - | + cp /tmp/certs/* /opt/bitnami/postgresql/certs/ + chmod 600 {{ include "postgresql.v1.tlsCertKey" . }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: raw-certificates + mountPath: /tmp/certs + - name: postgresql-certificates + mountPath: /opt/bitnami/postgresql/certs + {{- else if and .Values.volumePermissions.enabled (or .Values.primary.persistence.enabled .Values.shmVolume.enabled) }} + - name: init-chmod-data + image: {{ include "postgresql.v1.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- else if ne .Values.volumePermissions.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.volumePermissions.resourcesPreset) | nindent 12 }} + {{- end }} + command: + - /bin/sh + - -ec + - | + {{- if .Values.primary.persistence.enabled }} + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + chown `id -u`:`id -G | cut -d " " -f2` {{ .Values.primary.persistence.mountPath }} + {{- else }} + chown {{ .Values.primary.containerSecurityContext.runAsUser }}:{{ .Values.primary.podSecurityContext.fsGroup }} {{ .Values.primary.persistence.mountPath }} + {{- end }} + mkdir -p {{ .Values.primary.persistence.mountPath }}/data {{- if (include "postgresql.v1.mountConfigurationCM" .) }} {{ .Values.primary.persistence.mountPath }}/conf {{- end }} + chmod 700 {{ .Values.primary.persistence.mountPath }}/data {{- if (include "postgresql.v1.mountConfigurationCM" .) }} {{ .Values.primary.persistence.mountPath }}/conf {{- end }} + find {{ .Values.primary.persistence.mountPath }} -mindepth 1 -maxdepth 1 {{- if not (include "postgresql.v1.mountConfigurationCM" .) }} -not -name "conf" {{- end }} -not -name ".snapshot" -not -name "lost+found" | \ + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + xargs -r chown -R `id -u`:`id -G | cut -d " " -f2` + {{- else }} + xargs -r chown -R {{ .Values.primary.containerSecurityContext.runAsUser }}:{{ .Values.primary.podSecurityContext.fsGroup }} + {{- end }} + {{- end }} + {{- if .Values.shmVolume.enabled }} + chmod -R 777 /dev/shm + {{- end }} + {{- if .Values.tls.enabled }} + cp /tmp/certs/* /opt/bitnami/postgresql/certs/ + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + chown -R `id -u`:`id -G | cut -d " " -f2` /opt/bitnami/postgresql/certs/ + {{- else }} + chown -R {{ .Values.primary.containerSecurityContext.runAsUser }}:{{ .Values.primary.podSecurityContext.fsGroup }} /opt/bitnami/postgresql/certs/ + {{- end }} + chmod 600 {{ include "postgresql.v1.tlsCertKey" . }} + {{- end }} + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.containerSecurityContext "runAsUser" | toYaml | nindent 12 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.containerSecurityContext | toYaml | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: {{ .Values.primary.persistence.volumeName }} + mountPath: {{ .Values.primary.persistence.mountPath }} + {{- if .Values.primary.persistence.subPath }} + subPath: {{ .Values.primary.persistence.subPath }} + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + mountPath: /dev/shm + {{- end }} + {{- if .Values.tls.enabled }} + - name: raw-certificates + mountPath: /tmp/certs + - name: postgresql-certificates + mountPath: /opt/bitnami/postgresql/certs + {{- end }} + {{- end }} + {{- if .Values.primary.initContainers }} + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.initContainers "context" $ ) | nindent 8 }} + {{- end }} + {{- end }} + containers: + - name: postgresql + image: {{ include "postgresql.v1.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.primary.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.primary.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.primary.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.primary.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.primary.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.primary.args "context" $) | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + - name: POSTGRESQL_PORT_NUMBER + value: {{ .Values.containerPorts.postgresql | quote }} + - name: POSTGRESQL_VOLUME_DIR + value: {{ .Values.primary.persistence.mountPath | quote }} + {{- if .Values.primary.persistence.mountPath }} + - name: PGDATA + value: {{ .Values.postgresqlDataDir | quote }} + {{- end }} + # Authentication + {{- if or (eq $customUser "postgres") (empty $customUser) }} + {{- if .Values.auth.enablePostgresUser }} + {{- if .Values.auth.usePasswordFiles }} + - name: POSTGRES_PASSWORD_FILE + value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (include "postgresql.v1.adminPasswordKey" .) }} + {{- else }} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql.v1.secretName" . }} + key: {{ include "postgresql.v1.adminPasswordKey" . }} + {{- end }} + {{- else }} + - name: ALLOW_EMPTY_PASSWORD + value: "true" + {{- end }} + {{- else }} + - name: POSTGRES_USER + value: {{ $customUser | quote }} + {{- if .Values.auth.usePasswordFiles }} + - name: POSTGRES_PASSWORD_FILE + value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (include "postgresql.v1.userPasswordKey" .) }} + {{- else }} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql.v1.secretName" . }} + key: {{ include "postgresql.v1.userPasswordKey" . }} + {{- end }} + {{- if .Values.auth.enablePostgresUser }} + {{- if .Values.auth.usePasswordFiles }} + - name: POSTGRES_POSTGRES_PASSWORD_FILE + value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (include "postgresql.v1.adminPasswordKey" .) }} + {{- else }} + - name: POSTGRES_POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql.v1.secretName" . }} + key: {{ include "postgresql.v1.adminPasswordKey" . }} + {{- end }} + {{- end }} + {{- end }} + {{- if (include "postgresql.v1.database" .) }} + - name: POSTGRES_DATABASE + value: {{ (include "postgresql.v1.database" .) | quote }} + {{- end }} + {{- if or (eq .Values.architecture "replication") .Values.primary.standby.enabled }} + # Replication + - name: POSTGRES_REPLICATION_MODE + value: {{ ternary "slave" "master" .Values.primary.standby.enabled | quote }} + - name: POSTGRES_REPLICATION_USER + value: {{ .Values.auth.replicationUsername | quote }} + {{- if .Values.auth.usePasswordFiles }} + - name: POSTGRES_REPLICATION_PASSWORD_FILE + value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (include "postgresql.v1.replicationPasswordKey" .) }} + {{- else }} + - name: POSTGRES_REPLICATION_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql.v1.secretName" . }} + key: {{ include "postgresql.v1.replicationPasswordKey" . }} + {{- end }} + {{- if ne .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 .Values.primary.initdb.args }} + # Initdb + - name: POSTGRES_INITDB_ARGS + value: {{ .Values.primary.initdb.args | quote }} + {{- end }} + {{- if .Values.primary.initdb.postgresqlWalDir }} + - name: POSTGRES_INITDB_WALDIR + value: {{ .Values.primary.initdb.postgresqlWalDir | quote }} + {{- end }} + {{- if .Values.primary.initdb.user }} + - name: POSTGRES_INITSCRIPTS_USERNAME + value: {{ .Values.primary.initdb.user }} + {{- end }} + {{- if .Values.primary.initdb.password }} + - name: POSTGRES_INITSCRIPTS_PASSWORD + value: {{ .Values.primary.initdb.password | quote }} + {{- end }} + {{- if .Values.primary.standby.enabled }} + # Standby + - name: POSTGRES_MASTER_HOST + value: {{ .Values.primary.standby.primaryHost }} + - name: POSTGRES_MASTER_PORT_NUMBER + value: {{ .Values.primary.standby.primaryPort | quote }} + {{- end }} + # LDAP + - name: POSTGRESQL_ENABLE_LDAP + value: {{ ternary "yes" "no" .Values.ldap.enabled | quote }} + {{- if .Values.ldap.enabled }} + {{- if or .Values.ldap.url .Values.ldap.uri }} + - name: POSTGRESQL_LDAP_URL + value: {{ coalesce .Values.ldap.url .Values.ldap.uri }} + {{- else }} + - 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 (include "postgresql.v1.ldap.tls.enabled" .) }} + - 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: {{ coalesce .Values.ldap.baseDN .Values.ldap.basedn }} + - name: POSTGRESQL_LDAP_BIND_DN + value: {{ coalesce .Values.ldap.bindDN .Values.ldap.binddn}} + {{- if or (not (empty .Values.ldap.bind_password)) (not (empty .Values.ldap.bindpw)) }} + - name: POSTGRESQL_LDAP_BIND_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql.v1.secretName" . }} + key: ldap-password + {{- end }} + - name: POSTGRESQL_LDAP_SEARCH_ATTR + value: {{ coalesce .Values.ldap.search_attr .Values.ldap.searchAttribute }} + - name: POSTGRESQL_LDAP_SEARCH_FILTER + value: {{ coalesce .Values.ldap.search_filter .Values.ldap.searchFilter }} + {{- end }} + {{- end }} + # TLS + - name: POSTGRESQL_ENABLE_TLS + value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} + {{- if .Values.tls.enabled }} + - name: POSTGRESQL_TLS_PREFER_SERVER_CIPHERS + value: {{ ternary "yes" "no" .Values.tls.preferServerCiphers | quote }} + - name: POSTGRESQL_TLS_CERT_FILE + value: {{ include "postgresql.v1.tlsCert" . }} + - name: POSTGRESQL_TLS_KEY_FILE + value: {{ include "postgresql.v1.tlsCertKey" . }} + {{- if .Values.tls.certCAFilename }} + - name: POSTGRESQL_TLS_CA_FILE + value: {{ include "postgresql.v1.tlsCACert" . }} + {{- end }} + {{- if .Values.tls.crlFilename }} + - name: POSTGRESQL_TLS_CRL_FILE + value: {{ include "postgresql.v1.tlsCRL" . }} + {{- end }} + {{- end }} + # Audit + - name: POSTGRESQL_LOG_HOSTNAME + value: {{ .Values.audit.logHostname | quote }} + - name: POSTGRESQL_LOG_CONNECTIONS + value: {{ .Values.audit.logConnections | quote }} + - name: POSTGRESQL_LOG_DISCONNECTIONS + value: {{ .Values.audit.logDisconnections | quote }} + {{- if .Values.audit.logLinePrefix }} + - name: POSTGRESQL_LOG_LINE_PREFIX + value: {{ .Values.audit.logLinePrefix | quote }} + {{- end }} + {{- if .Values.audit.logTimezone }} + - name: POSTGRESQL_LOG_TIMEZONE + value: {{ .Values.audit.logTimezone | quote }} + {{- end }} + {{- if .Values.audit.pgAuditLog }} + - name: POSTGRESQL_PGAUDIT_LOG + value: {{ .Values.audit.pgAuditLog | quote }} + {{- end }} + - name: POSTGRESQL_PGAUDIT_LOG_CATALOG + value: {{ .Values.audit.pgAuditLogCatalog | quote }} + # Others + - name: POSTGRESQL_CLIENT_MIN_MESSAGES + value: {{ .Values.audit.clientMinMessages | quote }} + - name: POSTGRESQL_SHARED_PRELOAD_LIBRARIES + value: {{ .Values.postgresqlSharedPreloadLibraries | quote }} + {{- if .Values.primary.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.primary.extraEnvVarsCM .Values.primary.extraEnvVarsSecret }} + envFrom: + {{- if .Values.primary.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.primary.extraEnvVarsCM }} + {{- end }} + {{- if .Values.primary.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.primary.extraEnvVarsSecret }} + {{- end }} + {{- end }} + ports: + - name: tcp-postgresql + containerPort: {{ .Values.containerPorts.postgresql }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.primary.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.primary.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.primary.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.primary.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bin/sh + - -c + {{- if (include "postgresql.v1.database" .) }} + - exec pg_isready -U {{ default "postgres" $customUser | quote }} -d "dbname={{ include "postgresql.v1.database" . }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} sslcert={{ include "postgresql.v1.tlsCert" . }} sslkey={{ include "postgresql.v1.tlsCertKey" . }}{{- end }}" -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }} + {{- else }} + - exec pg_isready -U {{ default "postgres" $customUser | quote }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} -d "sslcert={{ include "postgresql.v1.tlsCert" . }} sslkey={{ include "postgresql.v1.tlsCertKey" . }}"{{- end }} -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }} + {{- end }} + {{- end }} + {{- if .Values.primary.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.primary.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.primary.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.primary.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bin/sh + - -c + {{- if (include "postgresql.v1.database" .) }} + - exec pg_isready -U {{ default "postgres" $customUser | quote }} -d "dbname={{ include "postgresql.v1.database" . }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} sslcert={{ include "postgresql.v1.tlsCert" . }} sslkey={{ include "postgresql.v1.tlsCertKey" . }}{{- end }}" -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }} + {{- else }} + - exec pg_isready -U {{ default "postgres" $customUser | quote }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} -d "sslcert={{ include "postgresql.v1.tlsCert" . }} sslkey={{ include "postgresql.v1.tlsCertKey" . }}"{{- end }} -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }} + {{- end }} + {{- end }} + {{- if .Values.primary.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.primary.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.primary.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.primary.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bin/sh + - -c + - -e + {{- include "postgresql.v1.readinessProbeCommand" . | nindent 16 }} + {{- end }} + {{- end }} + {{- if .Values.primary.resources }} + resources: {{- toYaml .Values.primary.resources | nindent 12 }} + {{- else if ne .Values.primary.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.primary.resourcesPreset) | nindent 12 }} + {{- end }} + {{- if .Values.primary.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.primary.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/postgresql/conf + subPath: app-conf-dir + - name: empty-dir + mountPath: /opt/bitnami/postgresql/tmp + subPath: app-tmp-dir + {{- if or .Values.primary.preInitDb.scriptsConfigMap .Values.primary.preInitDb.scripts }} + - name: custom-preinit-scripts + mountPath: /docker-entrypoint-preinitdb.d/ + {{- end }} + {{- if .Values.primary.preInitDb.scriptsSecret }} + - name: custom-preinit-scripts-secret + mountPath: /docker-entrypoint-preinitdb.d/secret + {{- end }} + {{- if or .Values.primary.initdb.scriptsConfigMap .Values.primary.initdb.scripts }} + - name: custom-init-scripts + mountPath: /docker-entrypoint-initdb.d/ + {{- end }} + {{- if .Values.primary.initdb.scriptsSecret }} + - name: custom-init-scripts-secret + mountPath: /docker-entrypoint-initdb.d/secret + {{- end }} + {{- if or .Values.primary.extendedConfiguration .Values.primary.existingExtendedConfigmap }} + - name: postgresql-extended-config + mountPath: {{ .Values.primary.persistence.mountPath }}/conf/conf.d/ + {{- end }} + {{- if and .Values.auth.usePasswordFiles (or .Values.auth.enablePostgresUser $customUser) }} + - name: postgresql-password + mountPath: /opt/bitnami/postgresql/secrets/ + {{- end }} + {{- if .Values.tls.enabled }} + - name: postgresql-certificates + mountPath: /opt/bitnami/postgresql/certs + readOnly: true + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + mountPath: /dev/shm + {{- end }} + - name: {{ .Values.primary.persistence.volumeName }} + mountPath: {{ .Values.primary.persistence.mountPath }} + {{- if .Values.primary.persistence.subPath }} + subPath: {{ .Values.primary.persistence.subPath }} + {{- end }} + {{- if or .Values.primary.configuration .Values.primary.pgHbaConfiguration .Values.primary.existingConfigmap }} + - name: postgresql-config + mountPath: {{ .Values.primary.persistence.mountPath }}/conf + {{- end }} + {{- if .Values.primary.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ include "postgresql.v1.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.metrics.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.metrics.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if or .Values.metrics.customMetrics .Values.metrics.collectors }} + args: + {{- if .Values.metrics.customMetrics }} + - --extend.query-path + - /conf/custom-metrics.yaml + {{- end }} + {{- range $name, $enabled := .Values.metrics.collectors }} + - --{{ if not $enabled }}no-{{ end }}collector.{{ $name }} + {{- end }} + {{- end }} + env: + - name: DATA_SOURCE_URI + value: {{ printf "127.0.0.1:%d/postgres?sslmode=disable" (int (include "postgresql.v1.service.port" .)) }} + {{- if .Values.auth.usePasswordFiles }} + - name: DATA_SOURCE_PASS_FILE + value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (include (ternary "postgresql.v1.adminPasswordKey" "postgresql.v1.userPasswordKey" (empty $customUser)) .) }} + {{- else }} + - name: DATA_SOURCE_PASS + valueFrom: + secretKeyRef: + name: {{ include "postgresql.v1.secretName" . }} + key: {{ include (ternary "postgresql.v1.adminPasswordKey" "postgresql.v1.userPasswordKey" (empty $customUser)) . }} + {{- end }} + - name: DATA_SOURCE_USER + value: {{ default "postgres" $customUser | quote }} + {{- if .Values.metrics.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: {{ .Values.metrics.containerPorts.metrics }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: http-metrics + {{- end }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: http-metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: http-metrics + {{- end }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if and .Values.auth.usePasswordFiles (or .Values.auth.enablePostgresUser $customUser) }} + - name: postgresql-password + mountPath: /opt/bitnami/postgresql/secrets/ + {{- end }} + {{- if .Values.metrics.customMetrics }} + - name: custom-metrics + mountPath: /conf + readOnly: true + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- else if ne .Values.metrics.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.metrics.resourcesPreset) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.primary.sidecars }} + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.sidecars "context" $ ) | nindent 8 }} + {{- end }} + volumes: + - name: empty-dir + emptyDir: {} + {{- if or .Values.primary.configuration .Values.primary.pgHbaConfiguration .Values.primary.existingConfigmap }} + - name: postgresql-config + configMap: + name: {{ include "postgresql.v1.primary.configmapName" . }} + {{- end }} + {{- if or .Values.primary.extendedConfiguration .Values.primary.existingExtendedConfigmap }} + - name: postgresql-extended-config + configMap: + name: {{ include "postgresql.v1.primary.extendedConfigmapName" . }} + {{- end }} + {{- if and .Values.auth.usePasswordFiles (or .Values.auth.enablePostgresUser $customUser) }} + - name: postgresql-password + secret: + secretName: {{ include "postgresql.v1.secretName" . }} + {{- end }} + {{- if or .Values.primary.preInitDb.scriptsConfigMap .Values.primary.preInitDb.scripts }} + - name: custom-preinit-scripts + configMap: + name: {{ include "postgresql.v1.preInitDb.scriptsCM" . }} + {{- end }} + {{- if .Values.primary.preInitDb.scriptsSecret }} + - name: custom-preinit-scripts-secret + secret: + secretName: {{ tpl .Values.primary.preInitDb.scriptsSecret $ }} + {{- end }} + {{- if or .Values.primary.initdb.scriptsConfigMap .Values.primary.initdb.scripts }} + - name: custom-init-scripts + configMap: + name: {{ include "postgresql.v1.initdb.scriptsCM" . }} + {{- end }} + {{- if .Values.primary.initdb.scriptsSecret }} + - name: custom-init-scripts-secret + secret: + secretName: {{ tpl .Values.primary.initdb.scriptsSecret $ }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: raw-certificates + secret: + secretName: {{ include "postgresql.v1.tlsSecretName" . }} + - name: postgresql-certificates + emptyDir: {} + {{- end }} + {{- if .Values.primary.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.customMetrics }} + - name: custom-metrics + configMap: + name: {{ printf "%s-metrics" (include "postgresql.v1.primary.fullname" .) }} + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + emptyDir: + medium: Memory + {{- if .Values.shmVolume.sizeLimit }} + sizeLimit: {{ .Values.shmVolume.sizeLimit }} + {{- end }} + {{- end }} + {{- if and .Values.primary.persistence.enabled .Values.primary.persistence.existingClaim }} + - name: {{ .Values.primary.persistence.volumeName }} + persistentVolumeClaim: + claimName: {{ tpl .Values.primary.persistence.existingClaim $ }} + {{- else if not .Values.primary.persistence.enabled }} + - name: {{ .Values.primary.persistence.volumeName }} + emptyDir: {} + {{- else }} + {{- if .Values.primary.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.primary.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.primary.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: {{ .Values.primary.persistence.volumeName }} + {{- if .Values.primary.persistence.annotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.primary.persistence.annotations "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.primary.persistence.labels }} + labels: {{- include "common.tplvalues.render" (dict "value" .Values.primary.persistence.labels "context" $) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.primary.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + {{- if .Values.primary.persistence.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.primary.persistence.dataSource "context" $) | nindent 10 }} + {{- end }} + resources: + requests: + storage: {{ .Values.primary.persistence.size | quote }} + {{- if .Values.primary.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.primary.persistence.selector "context" $) | nindent 10 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" .Values.primary.persistence "global" .Values.global) | nindent 8 }} + {{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/primary/svc-headless.yaml b/backing-services/gitea/charts/postgresql/templates/primary/svc-headless.yaml new file mode 100644 index 0000000..180cfcb --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/primary/svc-headless.yaml @@ -0,0 +1,31 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ include "postgresql.v1.primary.svc.headless" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: primary + annotations: + {{- if or .Values.primary.service.headless.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.service.headless.annotations .Values.commonAnnotations ) "context" . ) }} + {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + # We want all pods in the StatefulSet to have their addresses published for + # the sake of the other Postgresql pods even before they're ready, since they + # have to be able to talk to each other in order to become ready. + publishNotReadyAddresses: true + ports: + - name: tcp-postgresql + port: {{ template "postgresql.v1.service.port" . }} + targetPort: tcp-postgresql + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: primary diff --git a/backing-services/gitea/charts/postgresql/templates/primary/svc.yaml b/backing-services/gitea/charts/postgresql/templates/primary/svc.yaml new file mode 100644 index 0000000..2eeaea1 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/primary/svc.yaml @@ -0,0 +1,58 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ include "postgresql.v1.primary.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $labels := .Values.commonLabels }} + {{- if .Values.primary.service.labels }} + {{- $labels = include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.service.labels $labels ) "context" . ) }} + {{- end }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: primary + {{- if or .Values.commonAnnotations .Values.primary.service.annotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.primary.service.type }} + {{- if or (eq .Values.primary.service.type "LoadBalancer") (eq .Values.primary.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.primary.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.primary.service.type "LoadBalancer") (not (empty .Values.primary.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ .Values.primary.service.loadBalancerSourceRanges | toJson}} + {{- end }} + {{- if and (eq .Values.primary.service.type "LoadBalancer") (not (empty .Values.primary.service.loadBalancerClass)) }} + loadBalancerClass: {{ .Values.primary.service.loadBalancerClass }} + {{- end }} + {{- if and (eq .Values.primary.service.type "LoadBalancer") (not (empty .Values.primary.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.primary.service.loadBalancerIP }} + {{- end }} + {{- if and .Values.primary.service.clusterIP (eq .Values.primary.service.type "ClusterIP") }} + clusterIP: {{ .Values.primary.service.clusterIP }} + {{- end }} + {{- if .Values.primary.service.sessionAffinity }} + sessionAffinity: {{ .Values.primary.service.sessionAffinity }} + {{- end }} + {{- if .Values.primary.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.primary.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + ports: + - name: tcp-postgresql + port: {{ template "postgresql.v1.service.port" . }} + targetPort: tcp-postgresql + {{- if and (or (eq .Values.primary.service.type "NodePort") (eq .Values.primary.service.type "LoadBalancer")) (not (empty .Values.primary.service.nodePorts.postgresql)) }} + nodePort: {{ .Values.primary.service.nodePorts.postgresql }} + {{- else if eq .Values.primary.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.primary.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: primary diff --git a/backing-services/gitea/charts/postgresql/templates/prometheusrule.yaml b/backing-services/gitea/charts/postgresql/templates/prometheusrule.yaml new file mode 100644 index 0000000..fadcd32 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/prometheusrule.yaml @@ -0,0 +1,22 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ include "postgresql.v1.chart.fullname" . }} + namespace: {{ coalesce .Values.metrics.prometheusRule.namespace (include "common.names.namespace" .) | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.prometheusRule.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: metrics + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + groups: + - name: {{ include "postgresql.v1.chart.fullname" . }} + rules: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.prometheusRule.rules "context" $ ) | nindent 8 }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/psp.yaml b/backing-services/gitea/charts/postgresql/templates/psp.yaml new file mode 100644 index 0000000..b15efa3 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/psp.yaml @@ -0,0 +1,42 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (include "common.capabilities.psp.supported" .) .Values.psp.create }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "postgresql.v1.chart.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + privileged: false + volumes: + - 'configMap' + - 'secret' + - 'persistentVolumeClaim' + - 'emptyDir' + - 'projected' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + - min: 1 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 1 + max: 65535 + readOnlyRootFilesystem: false +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/read/extended-configmap.yaml b/backing-services/gitea/charts/postgresql/templates/read/extended-configmap.yaml new file mode 100644 index 0000000..6ffc93c --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/read/extended-configmap.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "postgresql.v1.readReplicas.createExtendedConfigmap" .) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-extended-configuration" (include "postgresql.v1.readReplica.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: read + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + override.conf: |- + {{- include "common.tplvalues.render" ( dict "value" .Values.readReplicas.extendedConfiguration "context" $ ) | nindent 4 }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/read/metrics-configmap.yaml b/backing-services/gitea/charts/postgresql/templates/read/metrics-configmap.yaml new file mode 100644 index 0000000..a4ed6b7 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/read/metrics-configmap.yaml @@ -0,0 +1,18 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.customMetrics (eq .Values.architecture "replication") }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-metrics" (include "postgresql.v1.readReplica.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + custom-metrics.yaml: {{ toYaml .Values.metrics.customMetrics | quote }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/read/metrics-svc.yaml b/backing-services/gitea/charts/postgresql/templates/read/metrics-svc.yaml new file mode 100644 index 0000000..fccd1b9 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/read/metrics-svc.yaml @@ -0,0 +1,31 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled (eq .Values.architecture "replication") }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-metrics" (include "postgresql.v1.readReplica.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: metrics-read + {{- if or .Values.commonAnnotations .Values.metrics.service.annotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + sessionAffinity: {{ .Values.metrics.service.sessionAffinity }} + {{- if .Values.metrics.service.clusterIP }} + clusterIP: {{ .Values.metrics.service.clusterIP }} + {{- end }} + ports: + - name: http-metrics + port: {{ .Values.metrics.service.ports.metrics }} + targetPort: http-metrics + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.readReplicas.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: read +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/read/networkpolicy.yaml b/backing-services/gitea/charts/postgresql/templates/read/networkpolicy.yaml new file mode 100644 index 0000000..9c730d8 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/read/networkpolicy.yaml @@ -0,0 +1,80 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if eq .Values.architecture "replication" }} +{{- if .Values.readReplicas.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ include "common.capabilities.networkPolicy.apiVersion" . }} +metadata: + name: {{ include "postgresql.v1.readReplica.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: read + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.readReplicas.podLabels .Values.commonLabels ) "context" . ) }} + podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: read + policyTypes: + - Ingress + - Egress + {{- if .Values.readReplicas.networkPolicy.allowExternalEgress }} + egress: + - {} + {{- else }} + egress: + # Allow dns resolution + - ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + # Allow outbound connections to primary + - ports: + - port: {{ .Values.containerPorts.postgresql }} + to: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }} + app.kubernetes.io/component: primary + {{- if .Values.readReplicas.networkPolicy.extraEgress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.readReplicas.networkPolicy.extraEgress "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} + ingress: + - ports: + - port: {{ .Values.containerPorts.postgresql }} + {{- if .Values.metrics.enabled }} + - port: {{ .Values.metrics.containerPorts.metrics }} + {{- end }} + {{- if not .Values.readReplicas.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 14 }} + - podSelector: + matchLabels: + {{ template "postgresql.v1.readReplica.fullname" . }}-client: "true" + {{- if .Values.readReplicas.networkPolicy.ingressNSMatchLabels }} + - namespaceSelector: + matchLabels: + {{- range $key, $value := .Values.readReplicas.networkPolicy.ingressNSMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{- if .Values.readReplicas.networkPolicy.ingressNSPodMatchLabels }} + podSelector: + matchLabels: + {{- range $key, $value := .Values.readReplicas.networkPolicy.ingressNSPodMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.readReplicas.networkPolicy.extraIngress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.readReplicas.networkPolicy.extraIngress "context" $ ) | nindent 4 }} + {{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/read/pdb.yaml b/backing-services/gitea/charts/postgresql/templates/read/pdb.yaml new file mode 100644 index 0000000..bd2eaad --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/read/pdb.yaml @@ -0,0 +1,29 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and ( eq .Values.architecture "replication" ) .Values.readReplicas.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "postgresql.v1.readReplica.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.readReplicas.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: read + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.readReplicas.pdb.minAvailable }} + minAvailable: {{ .Values.readReplicas.pdb.minAvailable }} + {{- end }} + {{- if or .Values.readReplicas.pdb.maxUnavailable ( not .Values.readReplicas.pdb.minAvailable ) }} + maxUnavailable: {{ .Values.readReplicas.pdb.maxUnavailable | default 1 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.readReplicas.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: read +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/read/servicemonitor.yaml b/backing-services/gitea/charts/postgresql/templates/read/servicemonitor.yaml new file mode 100644 index 0000000..b1536a6 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/read/servicemonitor.yaml @@ -0,0 +1,46 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled (eq .Values.architecture "replication") }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "postgresql.v1.readReplica.fullname" . }} + namespace: {{ coalesce .Values.metrics.serviceMonitor.namespace (include "common.names.namespace" .) | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.serviceMonitor.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: metrics-read + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.metrics.serviceMonitor.jobLabel }} + jobLabel: {{ .Values.metrics.serviceMonitor.jobLabel }} + {{- end }} + selector: + {{- $svcLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.serviceMonitor.selector .Values.commonLabels ) "context" . ) }} + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $svcLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: metrics-read + 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 }} + {{- if .Values.metrics.serviceMonitor.relabelings }} + relabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.relabelings "context" $) | nindent 6 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.metricRelabelings "context" $) | nindent 6 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.honorLabels }} + honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }} + {{- end }} + namespaceSelector: + matchNames: + - {{ include "common.names.namespace" . | quote }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/read/statefulset.yaml b/backing-services/gitea/charts/postgresql/templates/read/statefulset.yaml new file mode 100644 index 0000000..f7376b5 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/read/statefulset.yaml @@ -0,0 +1,588 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if eq .Values.architecture "replication" }} +{{- $customUser := include "postgresql.v1.username" . }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ include "postgresql.v1.readReplica.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.readReplicas.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: read + {{- if or .Values.commonAnnotations .Values.readReplicas.annotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.readReplicas.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.readReplicas.replicaCount }} + serviceName: {{ include "postgresql.v1.readReplica.svc.headless" . }} + {{- if .Values.readReplicas.updateStrategy }} + updateStrategy: {{- toYaml .Values.readReplicas.updateStrategy | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.readReplicas.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: read + template: + metadata: + name: {{ include "postgresql.v1.readReplica.fullname" . }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: read + {{- if or .Values.passwordUpdateJob.enabled (include "postgresql.v1.readReplicas.createExtendedConfigmap" .) .Values.readReplicas.podAnnotations }} + annotations: + {{- if (include "postgresql.v1.readReplicas.createExtendedConfigmap" .) }} + checksum/extended-configuration: {{ pick (include (print $.Template.BasePath "/primary/extended-configmap.yaml") . | fromYaml) "data" | toYaml | sha256sum }} + {{- end }} + {{- if .Values.passwordUpdateJob.enabled }} + charts.bitnami.com/password-last-update: {{ now | date "20060102150405" | quote }} + {{- end }} + {{- if .Values.readReplicas.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.readReplicas.podAnnotations "context" $ ) | nindent 8 }} + {{- end }} + {{- end }} + spec: + {{- if .Values.readReplicas.extraPodSpec }} + {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.extraPodSpec "context" $) | nindent 6 }} + {{- end }} + serviceAccountName: {{ include "postgresql.v1.serviceAccountName" . }} + {{- include "postgresql.v1.imagePullSecrets" . | nindent 6 }} + automountServiceAccountToken: {{ .Values.readReplicas.automountServiceAccountToken }} + {{- if .Values.readReplicas.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.readReplicas.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.readReplicas.podAffinityPreset "component" "read" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.readReplicas.podAntiAffinityPreset "component" "read" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.readReplicas.nodeAffinityPreset.type "key" .Values.readReplicas.nodeAffinityPreset.key "values" .Values.readReplicas.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.readReplicas.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.readReplicas.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.readReplicas.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.topologySpreadConstraints "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.readReplicas.priorityClassName }} + priorityClassName: {{ .Values.readReplicas.priorityClassName }} + {{- end }} + {{- if .Values.readReplicas.schedulerName }} + schedulerName: {{ .Values.readReplicas.schedulerName | quote }} + {{- end }} + {{- if .Values.readReplicas.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.readReplicas.terminationGracePeriodSeconds }} + {{- end }} + {{- if .Values.readReplicas.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.readReplicas.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + hostNetwork: {{ .Values.readReplicas.hostNetwork }} + hostIPC: {{ .Values.readReplicas.hostIPC }} + {{- if or (and .Values.tls.enabled (not .Values.volumePermissions.enabled)) (and .Values.volumePermissions.enabled (or .Values.readReplicas.persistence.enabled .Values.shmVolume.enabled)) .Values.readReplicas.initContainers }} + initContainers: + {{- if and .Values.tls.enabled (not .Values.volumePermissions.enabled) }} + - name: copy-certs + image: {{ include "postgresql.v1.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + {{- if .Values.readReplicas.resources }} + resources: {{- toYaml .Values.readReplicas.resources | nindent 12 }} + {{- else if ne .Values.readReplicas.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.readReplicas.resourcesPreset) | nindent 12 }} + {{- end }} + # We don't require a privileged container in this case + {{- if .Values.readReplicas.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.readReplicas.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + command: + - /bin/sh + - -ec + - | + cp /tmp/certs/* /opt/bitnami/postgresql/certs/ + chmod 600 {{ include "postgresql.v1.tlsCertKey" . }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: raw-certificates + mountPath: /tmp/certs + - name: postgresql-certificates + mountPath: /opt/bitnami/postgresql/certs + {{- else if and .Values.volumePermissions.enabled (or .Values.readReplicas.persistence.enabled .Values.shmVolume.enabled) }} + - name: init-chmod-data + image: {{ include "postgresql.v1.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + {{- if .Values.readReplicas.resources }} + resources: {{- toYaml .Values.readReplicas.resources | nindent 12 }} + {{- else if ne .Values.readReplicas.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.readReplicas.resourcesPreset) | nindent 12 }} + {{- end }} + command: + - /bin/sh + - -ec + - | + {{- if .Values.readReplicas.persistence.enabled }} + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + chown `id -u`:`id -G | cut -d " " -f2` {{ .Values.readReplicas.persistence.mountPath }} + {{- else }} + chown {{ .Values.readReplicas.containerSecurityContext.runAsUser }}:{{ .Values.readReplicas.podSecurityContext.fsGroup }} {{ .Values.readReplicas.persistence.mountPath }} + {{- end }} + mkdir -p {{ .Values.readReplicas.persistence.mountPath }}/data {{- if (include "postgresql.v1.mountConfigurationCM" .) }} {{ .Values.readReplicas.persistence.mountPath }}/conf {{- end }} + chmod 700 {{ .Values.readReplicas.persistence.mountPath }}/data {{- if (include "postgresql.v1.mountConfigurationCM" .) }} {{ .Values.readReplicas.persistence.mountPath }}/conf {{- end }} + find {{ .Values.readReplicas.persistence.mountPath }} -mindepth 1 -maxdepth 1 {{- if not (include "postgresql.v1.mountConfigurationCM" .) }} -not -name "conf" {{- end }} -not -name ".snapshot" -not -name "lost+found" | \ + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + xargs -r chown -R `id -u`:`id -G | cut -d " " -f2` + {{- else }} + xargs -r chown -R {{ .Values.readReplicas.containerSecurityContext.runAsUser }}:{{ .Values.readReplicas.podSecurityContext.fsGroup }} + {{- end }} + {{- end }} + {{- if .Values.shmVolume.enabled }} + chmod -R 777 /dev/shm + {{- end }} + {{- if .Values.tls.enabled }} + cp /tmp/certs/* /opt/bitnami/postgresql/certs/ + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + chown -R `id -u`:`id -G | cut -d " " -f2` /opt/bitnami/postgresql/certs/ + {{- else }} + chown -R {{ .Values.readReplicas.containerSecurityContext.runAsUser }}:{{ .Values.readReplicas.podSecurityContext.fsGroup }} /opt/bitnami/postgresql/certs/ + {{- end }} + chmod 600 {{ include "postgresql.v1.tlsCertKey" . }} + {{- end }} + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.containerSecurityContext "runAsUser" | toYaml | nindent 12 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.containerSecurityContext | toYaml | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: data + mountPath: {{ .Values.readReplicas.persistence.mountPath }} + {{- if .Values.readReplicas.persistence.subPath }} + subPath: {{ .Values.readReplicas.persistence.subPath }} + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + mountPath: /dev/shm + {{- end }} + {{- if .Values.tls.enabled }} + - name: raw-certificates + mountPath: /tmp/certs + - name: postgresql-certificates + mountPath: /opt/bitnami/postgresql/certs + {{- end }} + {{- end }} + {{- if .Values.readReplicas.initContainers }} + {{- include "common.tplvalues.render" ( dict "value" .Values.readReplicas.initContainers "context" $ ) | nindent 8 }} + {{- end }} + {{- end }} + containers: + - name: postgresql + image: {{ include "postgresql.v1.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.readReplicas.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.readReplicas.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.readReplicas.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.readReplicas.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.args "context" $) | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + - name: POSTGRESQL_PORT_NUMBER + value: {{ .Values.containerPorts.postgresql | quote }} + - name: POSTGRESQL_VOLUME_DIR + value: {{ .Values.readReplicas.persistence.mountPath | quote }} + {{- if .Values.readReplicas.persistence.mountPath }} + - name: PGDATA + value: {{ .Values.postgresqlDataDir | quote }} + {{- end }} + # Authentication + {{- if or (eq $customUser "postgres") (empty $customUser) }} + {{- if .Values.auth.enablePostgresUser }} + {{- if .Values.auth.usePasswordFiles }} + - name: POSTGRES_PASSWORD_FILE + value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (include "postgresql.v1.adminPasswordKey" .) }} + {{- else }} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql.v1.secretName" . }} + key: {{ include "postgresql.v1.adminPasswordKey" . }} + {{- end }} + {{- else }} + - name: ALLOW_EMPTY_PASSWORD + value: "true" + {{- end }} + {{- else }} + - name: POSTGRES_USER + value: {{ $customUser | quote }} + {{- if .Values.auth.usePasswordFiles }} + - name: POSTGRES_PASSWORD_FILE + value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (include "postgresql.v1.userPasswordKey" .) }} + {{- else }} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql.v1.secretName" . }} + key: {{ include "postgresql.v1.userPasswordKey" . }} + {{- end }} + {{- if .Values.auth.enablePostgresUser }} + {{- if .Values.auth.usePasswordFiles }} + - name: POSTGRES_POSTGRES_PASSWORD_FILE + value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (include "postgresql.v1.adminPasswordKey" .) }} + {{- else }} + - name: POSTGRES_POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql.v1.secretName" . }} + key: {{ include "postgresql.v1.adminPasswordKey" . }} + {{- end }} + {{- end }} + {{- end }} + # Replication + - name: POSTGRES_REPLICATION_MODE + value: "slave" + - name: POSTGRES_REPLICATION_USER + value: {{ .Values.auth.replicationUsername | quote }} + {{- if .Values.auth.usePasswordFiles }} + - name: POSTGRES_REPLICATION_PASSWORD_FILE + value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (include "postgresql.v1.replicationPasswordKey" .) }} + {{- else }} + - name: POSTGRES_REPLICATION_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql.v1.secretName" . }} + key: {{ include "postgresql.v1.replicationPasswordKey" . }} + {{- end }} + - name: POSTGRES_CLUSTER_APP_NAME + value: {{ .Values.replication.applicationName }} + - name: POSTGRES_MASTER_HOST + value: {{ include "postgresql.v1.primary.fullname" . }} + - name: POSTGRES_MASTER_PORT_NUMBER + value: {{ include "postgresql.v1.service.port" . | quote }} + # TLS + - name: POSTGRESQL_ENABLE_TLS + value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} + {{- if .Values.tls.enabled }} + - name: POSTGRESQL_TLS_PREFER_SERVER_CIPHERS + value: {{ ternary "yes" "no" .Values.tls.preferServerCiphers | quote }} + - name: POSTGRESQL_TLS_CERT_FILE + value: {{ include "postgresql.v1.tlsCert" . }} + - name: POSTGRESQL_TLS_KEY_FILE + value: {{ include "postgresql.v1.tlsCertKey" . }} + {{- if .Values.tls.certCAFilename }} + - name: POSTGRESQL_TLS_CA_FILE + value: {{ include "postgresql.v1.tlsCACert" . }} + {{- end }} + {{- if .Values.tls.crlFilename }} + - name: POSTGRESQL_TLS_CRL_FILE + value: {{ include "postgresql.v1.tlsCRL" . }} + {{- end }} + {{- end }} + # Audit + - name: POSTGRESQL_LOG_HOSTNAME + value: {{ .Values.audit.logHostname | quote }} + - name: POSTGRESQL_LOG_CONNECTIONS + value: {{ .Values.audit.logConnections | quote }} + - name: POSTGRESQL_LOG_DISCONNECTIONS + value: {{ .Values.audit.logDisconnections | quote }} + {{- if .Values.audit.logLinePrefix }} + - name: POSTGRESQL_LOG_LINE_PREFIX + value: {{ .Values.audit.logLinePrefix | quote }} + {{- end }} + {{- if .Values.audit.logTimezone }} + - name: POSTGRESQL_LOG_TIMEZONE + value: {{ .Values.audit.logTimezone | quote }} + {{- end }} + {{- if .Values.audit.pgAuditLog }} + - name: POSTGRESQL_PGAUDIT_LOG + value: {{ .Values.audit.pgAuditLog | quote }} + {{- end }} + - name: POSTGRESQL_PGAUDIT_LOG_CATALOG + value: {{ .Values.audit.pgAuditLogCatalog | quote }} + # Others + - name: POSTGRESQL_CLIENT_MIN_MESSAGES + value: {{ .Values.audit.clientMinMessages | quote }} + - name: POSTGRESQL_SHARED_PRELOAD_LIBRARIES + value: {{ .Values.postgresqlSharedPreloadLibraries | quote }} + {{- if .Values.readReplicas.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.readReplicas.extraEnvVarsCM .Values.readReplicas.extraEnvVarsSecret }} + envFrom: + {{- if .Values.readReplicas.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.readReplicas.extraEnvVarsCM }} + {{- end }} + {{- if .Values.readReplicas.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.readReplicas.extraEnvVarsSecret }} + {{- end }} + {{- end }} + ports: + - name: tcp-postgresql + containerPort: {{ .Values.containerPorts.postgresql }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.readReplicas.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.readReplicas.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.readReplicas.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bin/sh + - -c + {{- if (include "postgresql.v1.database" .) }} + - exec pg_isready -U {{ default "postgres" $customUser| quote }} -d "dbname={{ include "postgresql.v1.database" . }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} sslcert={{ include "postgresql.v1.tlsCert" . }} sslkey={{ include "postgresql.v1.tlsCertKey" . }}{{- end }}" -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }} + {{- else }} + - exec pg_isready -U {{ default "postgres" $customUser | quote }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} -d "sslcert={{ include "postgresql.v1.tlsCert" . }} sslkey={{ include "postgresql.v1.tlsCertKey" . }}"{{- end }} -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }} + {{- end }} + {{- end }} + {{- if .Values.readReplicas.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.readReplicas.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.readReplicas.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bin/sh + - -c + {{- if (include "postgresql.v1.database" .) }} + - exec pg_isready -U {{ default "postgres" $customUser | quote }} -d "dbname={{ include "postgresql.v1.database" . }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} sslcert={{ include "postgresql.v1.tlsCert" . }} sslkey={{ include "postgresql.v1.tlsCertKey" . }}{{- end }}" -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }} + {{- else }} + - exec pg_isready -U {{default "postgres" $customUser | quote }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} -d "sslcert={{ include "postgresql.v1.tlsCert" . }} sslkey={{ include "postgresql.v1.tlsCertKey" . }}"{{- end }} -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }} + {{- end }} + {{- end }} + {{- if .Values.readReplicas.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.readReplicas.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.readReplicas.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bin/sh + - -c + - -e + {{- include "postgresql.v1.readinessProbeCommand" . | nindent 16 }} + {{- end }} + {{- end }} + {{- if .Values.readReplicas.resources }} + resources: {{- toYaml .Values.readReplicas.resources | nindent 12 }} + {{- else if ne .Values.readReplicas.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.readReplicas.resourcesPreset) | nindent 12 }} + {{- end }} + {{- if .Values.readReplicas.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/postgresql/conf + subPath: app-conf-dir + - name: empty-dir + mountPath: /opt/bitnami/postgresql/tmp + subPath: app-tmp-dir + {{- if and .Values.auth.usePasswordFiles (or .Values.auth.enablePostgresUser $customUser) }} + - name: postgresql-password + mountPath: /opt/bitnami/postgresql/secrets/ + {{- end }} + {{- if .Values.readReplicas.extendedConfiguration }} + - name: postgresql-extended-config + mountPath: {{ .Values.readReplicas.persistence.mountPath }}/conf/conf.d/ + {{- end }} + {{- if .Values.tls.enabled }} + - name: postgresql-certificates + mountPath: /opt/bitnami/postgresql/certs + readOnly: true + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + mountPath: /dev/shm + {{- end }} + - name: data + mountPath: {{ .Values.readReplicas.persistence.mountPath }} + {{- if .Values.readReplicas.persistence.subPath }} + subPath: {{ .Values.readReplicas.persistence.subPath }} + {{- end }} + {{- if .Values.readReplicas.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ include "postgresql.v1.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.metrics.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.metrics.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if or .Values.metrics.customMetrics .Values.metrics.collectors }} + args: + {{- if .Values.metrics.customMetrics }} + - --extend.query-path + - /conf/custom-metrics.yaml + {{- end }} + {{- range $name, $enabled := .Values.metrics.collectors }} + - --{{ if not $enabled }}no-{{ end }}collector.{{ $name }} + {{- end }} + {{- end }} + env: + - name: DATA_SOURCE_URI + value: {{ printf "127.0.0.1:%d/postgres?sslmode=disable" (int (include "postgresql.v1.service.port" .)) }} + {{- if .Values.auth.usePasswordFiles }} + - name: DATA_SOURCE_PASS_FILE + value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (include (ternary "postgresql.v1.adminPasswordKey" "postgresql.v1.userPasswordKey" (empty $customUser)) .) }} + {{- else }} + - name: DATA_SOURCE_PASS + valueFrom: + secretKeyRef: + name: {{ include "postgresql.v1.secretName" . }} + key: {{ include (ternary "postgresql.v1.adminPasswordKey" "postgresql.v1.userPasswordKey" (empty $customUser)) . }} + {{- end }} + - name: DATA_SOURCE_USER + value: {{ default "postgres" $customUser | quote }} + {{- if .Values.metrics.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: {{ .Values.metrics.containerPorts.metrics }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: http-metrics + {{- end }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: http-metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: http-metrics + {{- end }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if and .Values.auth.usePasswordFiles (or .Values.auth.enablePostgresUser $customUser) }} + - name: postgresql-password + mountPath: /opt/bitnami/postgresql/secrets/ + {{- end }} + {{- if .Values.metrics.customMetrics }} + - name: custom-metrics + mountPath: /conf + readOnly: true + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- else if ne .Values.metrics.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.metrics.resourcesPreset) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.readReplicas.sidecars }} + {{- include "common.tplvalues.render" ( dict "value" .Values.readReplicas.sidecars "context" $ ) | nindent 8 }} + {{- end }} + volumes: + {{- if .Values.readReplicas.extendedConfiguration }} + - name: postgresql-extended-config + configMap: + name: {{ include "postgresql.v1.readReplicas.extendedConfigmapName" . }} + {{- end }} + {{- if and .Values.auth.usePasswordFiles (or .Values.auth.enablePostgresUser $customUser) }} + - name: postgresql-password + secret: + secretName: {{ include "postgresql.v1.secretName" . }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: raw-certificates + secret: + secretName: {{ include "postgresql.v1.tlsSecretName" . }} + - name: postgresql-certificates + emptyDir: {} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.customMetrics }} + - name: custom-metrics + configMap: + name: {{ printf "%s-metrics" (include "postgresql.v1.readReplica.fullname" .) }} + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + emptyDir: + medium: Memory + {{- if .Values.shmVolume.sizeLimit }} + sizeLimit: {{ .Values.shmVolume.sizeLimit }} + {{- end }} + {{- end }} + - name: empty-dir + emptyDir: {} + {{- if .Values.readReplicas.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.readReplicas.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if and .Values.readReplicas.persistence.enabled .Values.readReplicas.persistence.existingClaim }} + - name: data + persistentVolumeClaim: + claimName: {{ tpl .Values.readReplicas.persistence.existingClaim $ }} + {{- else if not .Values.readReplicas.persistence.enabled }} + - name: data + emptyDir: {} + {{- else }} + {{- if .Values.readReplicas.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.readReplicas.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.readReplicas.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: data + {{- if .Values.readReplicas.persistence.annotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.persistence.annotations "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.readReplicas.persistence.labels }} + labels: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.persistence.labels "context" $) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.readReplicas.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + {{- if .Values.readReplicas.persistence.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.persistence.dataSource "context" $) | nindent 10 }} + {{- end }} + resources: + requests: + storage: {{ .Values.readReplicas.persistence.size | quote }} + {{- if .Values.readReplicas.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.persistence.selector "context" $) | nindent 10 }} + {{- end -}} + {{- include "common.storage.class" (dict "persistence" .Values.readReplicas.persistence "global" .Values.global) | nindent 8 }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/read/svc-headless.yaml b/backing-services/gitea/charts/postgresql/templates/read/svc-headless.yaml new file mode 100644 index 0000000..15342a3 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/read/svc-headless.yaml @@ -0,0 +1,33 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if eq .Values.architecture "replication" }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "postgresql.v1.readReplica.svc.headless" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: read + annotations: + {{- if or .Values.readReplicas.service.headless.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.readReplicas.service.headless.annotations .Values.commonAnnotations ) "context" . ) }} + {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + # We want all pods in the StatefulSet to have their addresses published for + # the sake of the other Postgresql pods even before they're ready, since they + # have to be able to talk to each other in order to become ready. + publishNotReadyAddresses: true + ports: + - name: tcp-postgresql + port: {{ include "postgresql.v1.readReplica.service.port" . }} + targetPort: tcp-postgresql + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.readReplicas.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: read +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/read/svc.yaml b/backing-services/gitea/charts/postgresql/templates/read/svc.yaml new file mode 100644 index 0000000..7ebace3 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/read/svc.yaml @@ -0,0 +1,60 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if eq .Values.architecture "replication" }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "postgresql.v1.readReplica.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $labels := .Values.commonLabels }} + {{- if .Values.readReplicas.service.labels }} + {{- $labels = include "common.tplvalues.merge" ( dict "values" ( list .Values.readReplicas.service.labels $labels ) "context" . ) }} + {{- end }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: read + {{- if or .Values.commonAnnotations .Values.readReplicas.service.annotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.readReplicas.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.readReplicas.service.type }} + {{- if or (eq .Values.readReplicas.service.type "LoadBalancer") (eq .Values.readReplicas.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.readReplicas.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.readReplicas.service.type "LoadBalancer") (not (empty .Values.readReplicas.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ .Values.readReplicas.service.loadBalancerSourceRanges }} + {{- end }} + {{- if and (eq .Values.readReplicas.service.type "LoadBalancer") (not (empty .Values.readReplicas.service.loadBalancerClass)) }} + loadBalancerClass: {{ .Values.readReplicas.service.loadBalancerClass }} + {{- end }} + {{- if and (eq .Values.readReplicas.service.type "LoadBalancer") (not (empty .Values.readReplicas.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.readReplicas.service.loadBalancerIP }} + {{- end }} + {{- if and .Values.readReplicas.service.clusterIP (eq .Values.readReplicas.service.type "ClusterIP") }} + clusterIP: {{ .Values.readReplicas.service.clusterIP }} + {{- end }} + {{- if .Values.readReplicas.service.sessionAffinity }} + sessionAffinity: {{ .Values.readReplicas.service.sessionAffinity }} + {{- end }} + {{- if .Values.readReplicas.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + ports: + - name: tcp-postgresql + port: {{ include "postgresql.v1.readReplica.service.port" . }} + targetPort: tcp-postgresql + {{- if and (or (eq .Values.readReplicas.service.type "NodePort") (eq .Values.readReplicas.service.type "LoadBalancer")) (not (empty .Values.readReplicas.service.nodePorts.postgresql)) }} + nodePort: {{ .Values.readReplicas.service.nodePorts.postgresql }} + {{- else if eq .Values.readReplicas.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.readReplicas.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.readReplicas.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: read +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/role.yaml b/backing-services/gitea/charts/postgresql/templates/role.yaml new file mode 100644 index 0000000..ba906aa --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/role.yaml @@ -0,0 +1,32 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.rbac.create }} +kind: Role +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ include "postgresql.v1.chart.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +# yamllint disable rule:indentation +rules: + {{- if and (include "common.capabilities.psp.supported" .) .Values.psp.create }} + - apiGroups: + - 'policy' + resources: + - 'podsecuritypolicies' + verbs: + - 'use' + resourceNames: + - {{ include "postgresql.v1.chart.fullname" . }} + {{- end }} + {{- if .Values.rbac.rules }} + {{- include "common.tplvalues.render" ( dict "value" .Values.rbac.rules "context" $ ) | nindent 2 }} + {{- end }} +# yamllint enable rule:indentation +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/rolebinding.yaml b/backing-services/gitea/charts/postgresql/templates/rolebinding.yaml new file mode 100644 index 0000000..974080a --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/rolebinding.yaml @@ -0,0 +1,24 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.rbac.create }} +kind: RoleBinding +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ include "postgresql.v1.chart.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + kind: Role + name: {{ include "postgresql.v1.chart.fullname" . }} + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + name: {{ include "postgresql.v1.serviceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/secrets.yaml b/backing-services/gitea/charts/postgresql/templates/secrets.yaml new file mode 100644 index 0000000..82dfdd4 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/secrets.yaml @@ -0,0 +1,120 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- $host := include "postgresql.v1.primary.fullname" . }} +{{- $port := include "postgresql.v1.service.port" . }} +{{- $customUser := include "postgresql.v1.username" . }} +{{- $postgresPassword := (ternary (coalesce .Values.global.postgresql.auth.password .Values.auth.password .Values.global.postgresql.auth.postgresPassword .Values.auth.postgresPassword) (coalesce .Values.global.postgresql.auth.postgresPassword .Values.auth.postgresPassword) (or (empty $customUser) (eq $customUser "postgres"))) }} +{{- if (not $postgresPassword) }} +{{- $postgresPassword = include "common.secrets.lookup" (dict "secret" (include "postgresql.v1.secretName" .) "key" (coalesce .Values.global.postgresql.auth.secretKeys.adminPasswordKey .Values.auth.secretKeys.adminPasswordKey) "defaultValue" (ternary (coalesce .Values.global.postgresql.auth.password .Values.auth.password .Values.global.postgresql.auth.postgresPassword .Values.auth.postgresPassword) (coalesce .Values.global.postgresql.auth.postgresPassword .Values.auth.postgresPassword) (or (empty $customUser) (eq $customUser "postgres"))) "context" $) | trimAll "\"" | b64dec }} +{{- end }} +{{- if and (not $postgresPassword) .Values.auth.enablePostgresUser }} +{{- $postgresPassword = randAlphaNum 10 }} +{{- end }} +{{- $replicationPassword := "" }} +{{- if eq .Values.architecture "replication" }} +{{- $replicationPassword = include "common.secrets.passwords.manage" (dict "secret" (include "postgresql.v1.secretName" .) "key" (coalesce .Values.global.postgresql.auth.secretKeys.replicationPasswordKey .Values.auth.secretKeys.replicationPasswordKey) "providedValues" (list "auth.replicationPassword") "honorProvidedValues" true "context" $) | trimAll "\"" | b64dec }} +{{- end }} +{{- $ldapPassword := "" }} +{{- if and .Values.ldap.enabled (or .Values.ldap.bind_password .Values.ldap.bindpw) }} +{{- $ldapPassword = coalesce .Values.ldap.bind_password .Values.ldap.bindpw }} +{{- end }} +{{- $password := "" }} +{{- if and (not (empty $customUser)) (ne $customUser "postgres") }} +{{- $password = include "common.secrets.passwords.manage" (dict "secret" (include "postgresql.v1.secretName" .) "key" (coalesce .Values.global.postgresql.auth.secretKeys.userPasswordKey .Values.auth.secretKeys.userPasswordKey) "providedValues" (list "global.postgresql.auth.password" "auth.password") "honorProvidedValues" true "context" $) | trimAll "\"" | b64dec }} +{{- end }} +{{- $database := include "postgresql.v1.database" . }} +{{- if (include "postgresql.v1.createSecret" .) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "postgresql.v1.chart.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.secretAnnotations .Values.commonAnnotations }} + annotations: + {{- if .Values.secretAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.secretAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} +type: Opaque +data: + {{- if $postgresPassword }} + postgres-password: {{ $postgresPassword | b64enc | quote }} + {{- end }} + {{- if $password }} + password: {{ $password | b64enc | quote }} + {{- end }} + {{- if $replicationPassword }} + replication-password: {{ $replicationPassword | b64enc | quote }} + {{- end }} + # We don't auto-generate LDAP password when it's not provided as we do for other passwords + {{- if and .Values.ldap.enabled (or .Values.ldap.bind_password .Values.ldap.bindpw) }} + ldap-password: {{ $ldapPassword | b64enc | quote }} + {{- end }} +{{- end }} +{{- if .Values.serviceBindings.enabled }} +{{- if $postgresPassword }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "postgresql.v1.chart.fullname" . }}-svcbind-postgres + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.secretAnnotations .Values.commonAnnotations }} + annotations: + {{- if .Values.secretAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.secretAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} +type: servicebinding.io/postgresql +data: + provider: {{ print "bitnami" | b64enc | quote }} + type: {{ print "postgresql" | b64enc | quote }} + host: {{ $host | b64enc | quote }} + port: {{ $port | b64enc | quote }} + username: {{ print "postgres" | b64enc | quote }} + database: {{ print "postgres" | b64enc | quote }} + password: {{ $postgresPassword | b64enc | quote }} + uri: {{ printf "postgresql://postgres:%s@%s:%s/postgres" $postgresPassword $host $port | b64enc | quote }} +{{- end }} +{{- if $password }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "postgresql.v1.chart.fullname" . }}-svcbind-custom-user + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.secretAnnotations .Values.commonAnnotations }} + annotations: + {{- if .Values.secretAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.secretAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} +type: servicebinding.io/postgresql +data: + provider: {{ print "bitnami" | b64enc | quote }} + type: {{ print "postgresql" | b64enc | quote }} + host: {{ $host | b64enc | quote }} + port: {{ $port | b64enc | quote }} + username: {{ $customUser | b64enc | quote }} + password: {{ $password | b64enc | quote }} + {{- if $database }} + database: {{ $database | b64enc | quote }} + {{- end }} + uri: {{ printf "postgresql://%s:%s@%s:%s/%s" $customUser $password $host $port $database | b64enc | quote }} +{{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/serviceaccount.yaml b/backing-services/gitea/charts/postgresql/templates/serviceaccount.yaml new file mode 100644 index 0000000..3a0ccf0 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/serviceaccount.yaml @@ -0,0 +1,18 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "postgresql.v1.serviceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/tls-secrets.yaml b/backing-services/gitea/charts/postgresql/templates/tls-secrets.yaml new file mode 100644 index 0000000..350c86e --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/tls-secrets.yaml @@ -0,0 +1,30 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "postgresql.v1.createTlsSecret" . ) }} +{{- $secretName := printf "%s-crt" (include "postgresql.v1.chart.fullname" .) }} +{{- $ca := genCA "postgresql-ca" 365 }} +{{- $fullname := include "postgresql.v1.chart.fullname" . }} +{{- $releaseNamespace := include "common.names.namespace" . }} +{{- $clusterDomain := .Values.clusterDomain }} +{{- $primaryHeadlessServiceName := include "postgresql.v1.primary.svc.headless" . }} +{{- $readHeadlessServiceName := include "postgresql.v1.readReplica.svc.headless" . }} +{{- $altNames := list (printf "*.%s.%s.svc.%s" $fullname $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $fullname $releaseNamespace $clusterDomain) (printf "*.%s.%s.svc.%s" $primaryHeadlessServiceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $primaryHeadlessServiceName $releaseNamespace $clusterDomain) (printf "*.%s.%s.svc.%s" $readHeadlessServiceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $readHeadlessServiceName $releaseNamespace $clusterDomain) $fullname }} +{{- $cert := genSignedCert $fullname nil $altNames 365 $ca }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.crt" "defaultValue" $cert.Cert "context" $) }} + tls.key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.key" "defaultValue" $cert.Key "context" $) }} + ca.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/update-password/job.yaml b/backing-services/gitea/charts/postgresql/templates/update-password/job.yaml new file mode 100644 index 0000000..6b587b6 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/update-password/job.yaml @@ -0,0 +1,235 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.passwordUpdateJob.enabled }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ printf "%s-password-update" (include "postgresql.v1.chart.fullname" .) | trunc 63 | trimSuffix "-" }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: postgresql + app.kubernetes.io/component: update-job + {{- $defaultAnnotations := dict "helm.sh/hook" "pre-upgrade" "helm.sh/hook-delete-policy" "hook-succeeded" }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.passwordUpdateJob.annotations .Values.commonAnnotations $defaultAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} +spec: + backoffLimit: {{ .Values.passwordUpdateJob.backoffLimit }} + template: + metadata: + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.passwordUpdateJob.podLabels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/part-of: postgresql + app.kubernetes.io/component: update-job + {{- if .Values.passwordUpdateJob.podAnnotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.podAnnotations "context" $) | nindent 8 }} + {{- end }} + spec: + {{- include "postgresql.v1.imagePullSecrets" . | nindent 6 }} + restartPolicy: OnFailure + {{- if .Values.passwordUpdateJob.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.passwordUpdateJob.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + automountServiceAccountToken: {{ .Values.passwordUpdateJob.automountServiceAccountToken }} + {{- if .Values.passwordUpdateJob.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.hostAliases "context" $) | nindent 8 }} + {{- end }} + initContainers: + {{- if .Values.passwordUpdateJob.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.initContainers "context" $) | nindent 8 }} + {{- end }} + containers: + - name: update-credentials + image: {{ template "postgresql.v1.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.passwordUpdateJob.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -ec + {{- end }} + {{- if .Values.passwordUpdateJob.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.args "context" $) | nindent 12 }} + {{- else }} + args: + - | + {{- $customUser := include "postgresql.v1.username" . }} + {{- $customDatabase := include "postgresql.v1.database" . | default "postgres" }} + {{- if .Values.auth.usePasswordFiles }} + # We need to load all the secret env vars to the system + for file in $(find /bitnami/postgresql/secrets -type f); do + env_var_name="$(basename $file)" + echo "Exporting $env_var_name" + export $env_var_name="$(< $file)" + done + {{- end }} + + . /opt/bitnami/scripts/postgresql-env.sh + . /opt/bitnami/scripts/libpostgresql.sh + . /opt/bitnami/scripts/liblog.sh + + primary_host={{ include "postgresql.v1.primary.fullname" . }}-0.{{ include "postgresql.v1.primary.svc.headless" . }} + info "Starting password update job" + {{- if .Values.auth.enablePostgresUser }} + if [[ -f /job-status/postgres-password-changed ]]; then + info "Postgres password already updated. Skipping" + else + info "Updating postgres password" + echo "ALTER USER postgres WITH PASSWORD '$POSTGRESQL_NEW_POSTGRES_PASSWORD';" | postgresql_remote_execute $primary_host {{ .Values.containerPorts.postgresql }} "" postgres $POSTGRESQL_PREVIOUS_POSTGRES_PASSWORD + touch /job-status/postgres-password-changed + info "Postgres password successfully updated" + fi + {{- end }} + {{- if and (not (empty $customUser)) (ne $customUser "postgres") }} + if [[ -f /job-status/password-changed ]]; then + info "User password already updated. Skipping" + else + info "Updating user password" + echo "ALTER USER {{ $customUser }} WITH PASSWORD '$POSTGRESQL_NEW_PASSWORD';" | postgresql_remote_execute $primary_host {{ .Values.containerPorts.postgresql }} "{{ $customDatabase }}" $POSTGRESQL_USER $POSTGRESQL_PREVIOUS_PASSWORD + touch /job-status/password-changed + info "User password successfully updated" + fi + {{- end }} + {{- if or (eq .Values.architecture "replication") .Values.primary.standby.enabled }} + if [[ -f /job-status/replication-password-changed ]]; then + info "Replication password already updated. Skipping" + else + info "Updating replication password" + echo "ALTER USER $POSTGRESQL_REPLICATION_USER WITH PASSWORD '$POSTGRESQL_NEW_REPLICATION_PASSWORD';" | postgresql_remote_execute $primary_host {{ .Values.containerPorts.postgresql }} "{{ $customDatabase }}" $POSTGRESQL_REPLICATION_USER $POSTGRESQL_PREVIOUS_REPLICATION_PASSWORD + touch /job-status/replication-password-changed + info "Replication password successfully updated" + fi + {{- end }} + {{- if .Values.passwordUpdateJob.extraCommands }} + info "Running extra commmands" + {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.extraCommands "context" $) | nindent 14 }} + {{- end }} + info "Password update job finished successfully" + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" .Values.image.debug | quote }} + {{- if not .Values.auth.usePasswordFiles }} + - name: POSTGRESQL_PREVIOUS_POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "postgresql.v1.update-job.previousSecretName" . }} + key: {{ include "postgresql.v1.adminPasswordKey" . }} + - name: POSTGRESQL_NEW_POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "postgresql.v1.update-job.newSecretName" . }} + key: {{ include "postgresql.v1.adminPasswordKey" . }} + {{- end }} + {{- if not (empty .Values.auth.username) }} + - name: POSTGRESQL_USER + value: {{ .Values.auth.username | quote }} + {{- if not .Values.auth.usePasswordFiles }} + - name: POSTGRESQL_PREVIOUS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "postgresql.v1.update-job.previousSecretName" . }} + key: {{ include "postgresql.v1.userPasswordKey" . }} + - name: POSTGRESQL_NEW_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "postgresql.v1.update-job.newSecretName" . }} + key: {{ include "postgresql.v1.userPasswordKey" . }} + {{- end }} + {{- end }} + {{- if eq .Values.architecture "replication" }} + - name: POSTGRESQL_REPLICATION_USER + value: {{ .Values.auth.replicationUsername | quote }} + {{- if not .Values.auth.usePasswordFiles }} + - name: POSTGRESQL_PREVIOUS_REPLICATION_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "postgresql.v1.update-job.previousSecretName" . }} + key: {{ include "postgresql.v1.replicationPasswordKey" . }} + - name: POSTGRESQL_NEW_REPLICATION_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "postgresql.v1.update-job.newSecretName" . }} + key: {{ include "postgresql.v1.replicationPasswordKey" . }} + {{- end }} + {{- end }} + {{- if .Values.passwordUpdateJob.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.passwordUpdateJob.extraEnvVarsCM .Values.passwordUpdateJob.extraEnvVarsSecret }} + envFrom: + {{- if .Values.passwordUpdateJob.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.passwordUpdateJob.extraEnvVarsCM }} + {{- end }} + {{- if .Values.passwordUpdateJob.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.passwordUpdateJob.extraEnvVarsSecret }} + {{- end }} + {{- end }} + {{- if .Values.passwordUpdateJob.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.passwordUpdateJob.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.passwordUpdateJob.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.customLivenessProbe "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.passwordUpdateJob.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.customReadinessProbe "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.passwordUpdateJob.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.customStartupProbe "context" $) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /job-status + subPath: job-dir + {{- if .Values.auth.usePasswordFiles }} + - name: postgresql-previous-credentials + mountPath: /bitnami/postgresql/secrets/previous + - name: postgresql-new-credentials + mountPath: /bitnami/postgresql/secrets/new + {{- end }} + {{- if .Values.passwordUpdateJob.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.passwordUpdateJob.resources }} + resources: {{- toYaml .Values.passwordUpdateJob.resources | nindent 12 }} + {{- else if ne .Values.passwordUpdateJob.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.passwordUpdateJob.resourcesPreset) | nindent 12 }} + {{- end }} + volumes: + - name: empty-dir + emptyDir: {} + {{- if .Values.auth.usePasswordFiles }} + - name: postgresql-previous-credentials + secret: + secretName: {{ template "postgresql.v1.update-job.previousSecretName" . }} + items: + - key: {{ include "postgresql.v1.adminPasswordKey" . }} + path: POSTGRESQL_PREVIOUS_POSTGRES_PASSWORD + - key: {{ include "postgresql.v1.userPasswordKey" . }} + path: POSTGRESQL_PREVIOUS_PASSWORD + {{- if eq .Values.architecture "replication" }} + - key: {{ include "postgresql.v1.replicationPasswordKey" . }} + path: POSTGRESQL_PREVIOUS_REPLICATION_PASSWORD + {{- end }} + - name: postgresql-new-credentials + secret: + secretName: {{ template "postgresql.v1.update-job.newSecretName" . }} + items: + - key: {{ include "postgresql.v1.adminPasswordKey" . }} + path: POSTGRESQL_NEW_POSTGRES_PASSWORD + - key: {{ include "postgresql.v1.userPasswordKey" . }} + path: POSTGRESQL_NEW_PASSWORD + {{- if eq .Values.architecture "replication" }} + - key: {{ include "postgresql.v1.replicationPasswordKey" . }} + path: POSTGRESQL_NEW_REPLICATION_PASSWORD + {{- end }} + {{- end }} + {{- if .Values.passwordUpdateJob.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.extraVolumes "context" $) | nindent 8 }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/update-password/new-secret.yaml b/backing-services/gitea/charts/postgresql/templates/update-password/new-secret.yaml new file mode 100644 index 0000000..c02f281 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/update-password/new-secret.yaml @@ -0,0 +1,32 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.passwordUpdateJob.enabled (include "postgresql.v1.createSecret" .) (not ( include "postgresql.v1.createPreviousSecret" . )) (not .Values.passwordUpdateJob.previousPasswords.existingSecret) }} +{{- $customUser := include "postgresql.v1.username" . }} +{{- $postgresPassword := (ternary (coalesce .Values.global.postgresql.auth.password .Values.auth.password .Values.global.postgresql.auth.postgresPassword .Values.auth.postgresPassword) (coalesce .Values.global.postgresql.auth.postgresPassword .Values.auth.postgresPassword) (or (empty $customUser) (eq $customUser "postgres"))) }} +{{- $password := coalesce .Values.global.postgresql.auth.password .Values.auth.password }} +{{- $replicationPassword := .Values.auth.replicationPassword }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ printf "%s-new-secret" (include "postgresql.v1.chart.fullname" .) | trunc 63 | trimSuffix "-" }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: postgresql + {{- $defaultAnnotations := dict "helm.sh/hook" "pre-upgrade" "helm.sh/hook-delete-policy" "hook-succeeded" }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonAnnotations $defaultAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} +type: Opaque +data: + {{- if .Values.auth.enablePostgresUser }} + postgres-password: {{ required "The new postgres password is required!" $postgresPassword | b64enc | quote }} + {{- end }} + {{- if and (not (empty $customUser)) (ne $customUser "postgres") }} + password: {{ required "The new user password is required!" $password | b64enc | quote }} + {{- end }} + {{- if or (eq .Values.architecture "replication") .Values.primary.standby.enabled }} + replication-password: {{ required "The new replication password is required!" $replicationPassword | b64enc | quote }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/templates/update-password/previous-secret.yaml b/backing-services/gitea/charts/postgresql/templates/update-password/previous-secret.yaml new file mode 100644 index 0000000..39087c4 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/templates/update-password/previous-secret.yaml @@ -0,0 +1,32 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.passwordUpdateJob.enabled (include "postgresql.v1.createPreviousSecret" .) }} +{{- $customUser := include "postgresql.v1.username" . }} +{{- $postgresPassword := .Values.passwordUpdateJob.previousPasswords.postgresPassword }} +{{- $password := .Values.passwordUpdateJob.previousPasswords.password }} +{{- $replicationPassword := .Values.passwordUpdateJob.previousPasswords.replicationPassword }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ printf "%s-previous-secret" (include "postgresql.v1.chart.fullname" .) | trunc 63 | trimSuffix "-" }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: postgresql + {{- $defaultAnnotations := dict "helm.sh/hook" "pre-upgrade" "helm.sh/hook-delete-policy" "hook-succeeded" }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonAnnotations $defaultAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} +type: Opaque +data: + {{- if .Values.auth.enablePostgresUser }} + postgres-password: {{ required "The previous postgres password is required!" $postgresPassword | b64enc | quote }} + {{- end }} + {{- if and (not (empty $customUser)) (ne $customUser "postgres") }} + password: {{ required "The previous user password is required!" $password | b64enc | quote }} + {{- end }} + {{- if or (eq .Values.architecture "replication") .Values.primary.standby.enabled }} + replication-password: {{ required "The previous replication password is required!" $replicationPassword | b64enc | quote }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/postgresql/values.schema.json b/backing-services/gitea/charts/postgresql/values.schema.json new file mode 100644 index 0000000..fc41483 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/values.schema.json @@ -0,0 +1,156 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "architecture": { + "type": "string", + "title": "PostgreSQL architecture", + "form": true, + "description": "Allowed values: `standalone` or `replication`" + }, + "auth": { + "type": "object", + "title": "Authentication configuration", + "form": true, + "properties": { + "enablePostgresUser": { + "type": "boolean", + "title": "Enable \"postgres\" admin user", + "description": "Assign a password to the \"postgres\" admin user. Otherwise, remote access will be blocked for this user", + "form": true + }, + "postgresPassword": { + "type": "string", + "title": "Password for the \"postgres\" admin user", + "description": "Defaults to a random 10-character alphanumeric string if not set", + "form": true + }, + "database": { + "type": "string", + "title": "PostgreSQL custom database", + "description": "Name of the custom database to be created during the 1st initialization of PostgreSQL", + "form": true + }, + "username": { + "type": "string", + "title": "PostgreSQL custom user", + "description": "Name of the custom user to be created during the 1st initialization of PostgreSQL. This user only has permissions on the PostgreSQL custom database", + "form": true + }, + "password": { + "type": "string", + "title": "Password for the custom user to create", + "description": "Defaults to a random 10-character alphanumeric string if not set", + "form": true + }, + "replicationUsername": { + "type": "string", + "title": "PostgreSQL replication user", + "description": "Name of user used to manage replication.", + "form": true, + "hidden": { + "value": "standalone", + "path": "architecture" + } + }, + "replicationPassword": { + "type": "string", + "title": "Password for PostgreSQL replication user", + "description": "Defaults to a random 10-character alphanumeric string if not set", + "form": true, + "hidden": { + "value": "standalone", + "path": "architecture" + } + } + } + }, + "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 + }, + "readReplicas": { + "type": "integer", + "title": "read Replicas", + "form": true, + "hidden": { + "value": "standalone", + "path": "architecture" + } + } + } + }, + "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/backing-services/gitea/charts/postgresql/values.yaml b/backing-services/gitea/charts/postgresql/values.yaml new file mode 100644 index 0000000..01c3ed1 --- /dev/null +++ b/backing-services/gitea/charts/postgresql/values.yaml @@ -0,0 +1,1933 @@ +# Copyright Broadcom, Inc. All Rights Reserved. +# SPDX-License-Identifier: APACHE-2.0 + +## @section Global parameters +## Please, note that this will override the parameters, including dependencies, configured to use the global value +## +global: + ## @param global.imageRegistry Global Docker image registry + ## + imageRegistry: "" + ## @param global.imagePullSecrets Global Docker registry secret names as an array + ## e.g. + ## imagePullSecrets: + ## - myRegistryKeySecretName + ## + imagePullSecrets: [] + ## @param global.defaultStorageClass Global default StorageClass for Persistent Volume(s) +## @param global.storageClass DEPRECATED: use global.defaultStorageClass instead + ## + defaultStorageClass: "" + storageClass: "" + ## Security parameters + ## + security: + ## @param global.security.allowInsecureImages Allows skipping image verification + allowInsecureImages: false + postgresql: + ## @param global.postgresql.fullnameOverride Full chart name (overrides `fullnameOverride`) + ## @param global.postgresql.auth.postgresPassword Password for the "postgres" admin user (overrides `auth.postgresPassword`) + ## @param global.postgresql.auth.username Name for a custom user to create (overrides `auth.username`) + ## @param global.postgresql.auth.password Password for the custom user to create (overrides `auth.password`) + ## @param global.postgresql.auth.database Name for a custom database to create (overrides `auth.database`) + ## @param global.postgresql.auth.existingSecret Name of existing secret to use for PostgreSQL credentials (overrides `auth.existingSecret`). + ## @param global.postgresql.auth.secretKeys.adminPasswordKey Name of key in existing secret to use for PostgreSQL credentials (overrides `auth.secretKeys.adminPasswordKey`). Only used when `global.postgresql.auth.existingSecret` is set. + ## @param global.postgresql.auth.secretKeys.userPasswordKey Name of key in existing secret to use for PostgreSQL credentials (overrides `auth.secretKeys.userPasswordKey`). Only used when `global.postgresql.auth.existingSecret` is set. + ## @param global.postgresql.auth.secretKeys.replicationPasswordKey Name of key in existing secret to use for PostgreSQL credentials (overrides `auth.secretKeys.replicationPasswordKey`). Only used when `global.postgresql.auth.existingSecret` is set. + ## + fullnameOverride: "" + + auth: + postgresPassword: "" + username: "" + password: "" + database: "" + existingSecret: "" + secretKeys: + adminPasswordKey: "" + userPasswordKey: "" + replicationPasswordKey: "" + ## @param global.postgresql.service.ports.postgresql PostgreSQL service port (overrides `service.ports.postgresql`) + ## + service: + ports: + postgresql: "" + ## Compatibility adaptations for Kubernetes platforms + ## + compatibility: + ## Compatibility adaptations for Openshift + ## + openshift: + ## @param global.compatibility.openshift.adaptSecurityContext Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) + ## + adaptSecurityContext: auto +## @section Common parameters +## + +## @param kubeVersion Override Kubernetes version +## +kubeVersion: "" +## @param nameOverride String to partially override common.names.fullname template (will maintain the release name) +## +nameOverride: "" +## @param fullnameOverride String to fully override common.names.fullname template +## +fullnameOverride: "" +## @param namespaceOverride String to fully override common.names.namespace +## +namespaceOverride: "" +## @param clusterDomain Kubernetes Cluster Domain +## +clusterDomain: cluster.local +## @param extraDeploy Array of extra objects to deploy with the release (evaluated as a template) +## +extraDeploy: [] +## @param commonLabels Add labels to all the deployed resources +## +commonLabels: {} +## @param commonAnnotations Add annotations to all the deployed resources +## +commonAnnotations: {} +## @param secretAnnotations Add annotations to the secrets +## +secretAnnotations: {} +## Enable diagnostic mode in the statefulset +## +diagnosticMode: + ## @param diagnosticMode.enabled Enable diagnostic mode (all probes will be disabled and the command will be overridden) + ## + enabled: false + ## @param diagnosticMode.command Command to override all containers in the statefulset + ## + command: + - sleep + ## @param diagnosticMode.args Args to override all containers in the statefulset + ## + args: + - infinity +## @section PostgreSQL common parameters +## + +## Bitnami PostgreSQL image version +## ref: https://hub.docker.com/r/bitnami/postgresql/tags/ +## @param image.registry [default: REGISTRY_NAME] PostgreSQL image registry +## @param image.repository [default: REPOSITORY_NAME/postgresql] PostgreSQL image repository +## @skip image.tag PostgreSQL image tag (immutable tags are recommended) +## @param image.digest PostgreSQL image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag +## @param image.pullPolicy PostgreSQL image pull policy +## @param image.pullSecrets Specify image pull secrets +## @param image.debug Specify if debug values should be set +## +image: + registry: docker.io + repository: bitnami/postgresql + tag: 17.6.0-debian-12-r4 + digest: "" + ## Specify a imagePullPolicy + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-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/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Set to true if you would like to see extra information on logs + ## + debug: false +## Authentication parameters +## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql#setting-the-root-password-on-first-run +## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql#creating-a-database-on-first-run +## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql#creating-a-database-user-on-first-run +## +auth: + ## @param auth.enablePostgresUser Assign a password to the "postgres" admin user. Otherwise, remote access will be blocked for this user + ## + enablePostgresUser: true + ## @param auth.postgresPassword Password for the "postgres" admin user. Ignored if `auth.existingSecret` is provided + ## + postgresPassword: "" + ## @param auth.username Name for a custom user to create + ## + username: "" + ## @param auth.password Password for the custom user to create. Ignored if `auth.existingSecret` is provided + ## + password: "" + ## @param auth.database Name for a custom database to create + ## + database: "" + ## @param auth.replicationUsername Name of the replication user + ## + replicationUsername: repl_user + ## @param auth.replicationPassword Password for the replication user. Ignored if `auth.existingSecret` is provided + ## + replicationPassword: "" + ## @param auth.existingSecret Name of existing secret to use for PostgreSQL credentials. `auth.postgresPassword`, `auth.password`, and `auth.replicationPassword` will be ignored and picked up from this secret. The secret might also contains the key `ldap-password` if LDAP is enabled. `ldap.bind_password` will be ignored and picked from this secret in this case. + ## + existingSecret: "" + ## @param auth.secretKeys.adminPasswordKey Name of key in existing secret to use for PostgreSQL credentials. Only used when `auth.existingSecret` is set. + ## @param auth.secretKeys.userPasswordKey Name of key in existing secret to use for PostgreSQL credentials. Only used when `auth.existingSecret` is set. + ## @param auth.secretKeys.replicationPasswordKey Name of key in existing secret to use for PostgreSQL credentials. Only used when `auth.existingSecret` is set. + ## + secretKeys: + adminPasswordKey: postgres-password + userPasswordKey: password + replicationPasswordKey: replication-password + ## @param auth.usePasswordFiles Mount credentials as a files instead of using an environment variable + ## + usePasswordFiles: true +## @param architecture PostgreSQL architecture (`standalone` or `replication`) +## +architecture: standalone +## Replication configuration +## Ignored if `architecture` is `standalone` +## +replication: + ## @param replication.synchronousCommit Set synchronous commit mode. Allowed values: `on`, `remote_apply`, `remote_write`, `local` and `off` + ## @param replication.numSynchronousReplicas Number of replicas that will have synchronous replication. Note: Cannot be greater than `readReplicas.replicaCount`. + ## ref: https://www.postgresql.org/docs/current/runtime-config-wal.html#GUC-SYNCHRONOUS-COMMIT + ## + synchronousCommit: "off" + numSynchronousReplicas: 0 + ## @param replication.applicationName Cluster application name. Useful for advanced replication settings + ## + applicationName: my_application +## @param containerPorts.postgresql PostgreSQL container port +## +containerPorts: + postgresql: 5432 +## Audit settings +## https://github.com/bitnami/containers/tree/main/bitnami/postgresql#auditing +## @param audit.logHostname Log client hostnames +## @param audit.logConnections Add client log-in operations to the log file +## @param audit.logDisconnections Add client log-outs operations to the log file +## @param audit.pgAuditLog Add operations to log using the pgAudit extension +## @param audit.pgAuditLogCatalog Log catalog using pgAudit +## @param audit.clientMinMessages Message log level to share with the user +## @param audit.logLinePrefix Template for log line prefix (default if not set) +## @param audit.logTimezone Timezone for the log timestamps +## +audit: + logHostname: false + logConnections: false + logDisconnections: false + pgAuditLog: "" + pgAuditLogCatalog: "off" + clientMinMessages: error + logLinePrefix: "" + logTimezone: "" +## LDAP configuration +## @param ldap.enabled Enable LDAP support +## @param ldap.server IP address or name of the LDAP server. +## @param ldap.port Port number on the LDAP server to connect to +## @param ldap.prefix String to prepend to the user name when forming the DN to bind +## @param ldap.suffix String to append to the user name when forming the DN to bind +## DEPRECATED ldap.baseDN It will removed in a future, please use 'ldap.basedn' instead +## DEPRECATED ldap.bindDN It will removed in a future, please use 'ldap.binddn' instead +## DEPRECATED ldap.bind_password It will removed in a future, please use 'ldap.bindpw' instead +## @param ldap.basedn Root DN to begin the search for the user in +## @param ldap.binddn DN of user to bind to LDAP +## @param ldap.bindpw Password for the user to bind to LDAP +## DEPRECATED ldap.search_attr It will removed in a future, please use 'ldap.searchAttribute' instead +## DEPRECATED ldap.search_filter It will removed in a future, please use 'ldap.searchFilter' instead +## @param ldap.searchAttribute Attribute to match against the user name in the search +## @param ldap.searchFilter The search filter to use when doing search+bind authentication +## @param ldap.scheme Set to `ldaps` to use LDAPS +## DEPRECATED ldap.tls as string is deprecated, please use 'ldap.tls.enabled' instead +## @param ldap.tls.enabled Se to true to enable TLS encryption +## +ldap: + enabled: false + server: "" + port: "" + prefix: "" + suffix: "" + basedn: "" + binddn: "" + bindpw: "" + searchAttribute: "" + searchFilter: "" + scheme: "" + tls: + enabled: false + ## @param ldap.uri LDAP URL beginning in the form `ldap[s]://host[:port]/basedn`. If provided, all the other LDAP parameters will be ignored. + ## Ref: https://www.postgresql.org/docs/current/auth-ldap.html + ## + uri: "" +## @param postgresqlDataDir PostgreSQL data dir folder +## +postgresqlDataDir: /bitnami/postgresql/data +## @param postgresqlSharedPreloadLibraries Shared preload libraries (comma-separated list) +## +postgresqlSharedPreloadLibraries: "pgaudit" +## Start PostgreSQL pod(s) without limitations on shm memory. +## By default docker and containerd (and possibly other container runtimes) limit `/dev/shm` to `64M` +## ref: https://github.com/docker-library/postgres/issues/416 +## ref: https://github.com/containerd/containerd/issues/3654 +## +shmVolume: + ## @param shmVolume.enabled Enable emptyDir volume for /dev/shm for PostgreSQL pod(s) + ## + enabled: true + ## @param shmVolume.sizeLimit Set this to enable a size limit on the shm tmpfs + ## Note: the size of the tmpfs counts against container's memory limit + ## e.g: + ## sizeLimit: 1Gi + ## + sizeLimit: "" +## TLS configuration +## +tls: + ## @param tls.enabled Enable TLS traffic support + ## + enabled: false + ## @param tls.autoGenerated Generate automatically self-signed TLS certificates + ## + autoGenerated: false + ## @param tls.preferServerCiphers Whether to use the server's TLS cipher preferences rather than the client's + ## + preferServerCiphers: true + ## @param tls.certificatesSecret Name of an existing secret that contains the certificates + ## + certificatesSecret: "" + ## @param tls.certFilename Certificate filename + ## + certFilename: "" + ## @param tls.certKeyFilename Certificate key filename + ## + certKeyFilename: "" + ## @param tls.certCAFilename CA Certificate filename + ## If provided, PostgreSQL will authenticate TLS/SSL clients by requesting them a certificate + ## ref: https://www.postgresql.org/docs/9.6/auth-methods.html + ## + certCAFilename: "" + ## @param tls.crlFilename File containing a Certificate Revocation List + ## + crlFilename: "" +## @section PostgreSQL Primary parameters +## +primary: + ## @param primary.name Name of the primary database (eg primary, master, leader, ...) + ## + name: primary + ## @param primary.configuration PostgreSQL Primary main configuration to be injected as ConfigMap + ## ref: https://www.postgresql.org/docs/current/static/runtime-config.html + ## + configuration: "" + ## @param primary.pgHbaConfiguration PostgreSQL Primary client authentication configuration + ## ref: https://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html + ## e.g:# + ## pgHbaConfiguration: |- + ## local all all trust + ## host all all localhost trust + ## host mydatabase mysuser 192.168.0.0/24 md5 + ## + pgHbaConfiguration: "" + ## @param primary.existingConfigmap Name of an existing ConfigMap with PostgreSQL Primary configuration + ## NOTE: `primary.configuration` and `primary.pgHbaConfiguration` will be ignored + ## + existingConfigmap: "" + ## @param primary.extendedConfiguration Extended PostgreSQL Primary configuration (appended to main or default configuration) + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql#allow-settings-to-be-loaded-from-files-other-than-the-default-postgresqlconf + ## + extendedConfiguration: "" + ## @param primary.existingExtendedConfigmap Name of an existing ConfigMap with PostgreSQL Primary extended configuration + ## NOTE: `primary.extendedConfiguration` will be ignored + ## + existingExtendedConfigmap: "" + ## Initdb configuration + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql#specifying-initdb-arguments + ## + initdb: + ## @param primary.initdb.args PostgreSQL initdb extra arguments + ## + args: "" + ## @param primary.initdb.postgresqlWalDir Specify a custom location for the PostgreSQL transaction log + ## + postgresqlWalDir: "" + ## @param primary.initdb.scripts Dictionary of initdb scripts + ## Specify dictionary of scripts to be run at first boot + ## e.g: + ## scripts: + ## my_init_script.sh: | + ## #!/bin/sh + ## echo "Do something." + ## + scripts: {} + ## @param primary.initdb.scriptsConfigMap ConfigMap with scripts to be run at first boot + ## NOTE: This will override `primary.initdb.scripts` + ## + scriptsConfigMap: "" + ## @param primary.initdb.scriptsSecret Secret with scripts to be run at first boot (in case it contains sensitive information) + ## NOTE: This can work along `primary.initdb.scripts` or `primary.initdb.scriptsConfigMap` + ## + scriptsSecret: "" + ## @param primary.initdb.user Specify the PostgreSQL username to execute the initdb scripts + ## + user: "" + ## @param primary.initdb.password Specify the PostgreSQL password to execute the initdb scripts + ## + password: "" + ## Pre-init configuration + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql/#on-container-start + preInitDb: + ## @param primary.preInitDb.scripts Dictionary of pre-init scripts + ## Specify dictionary of shell scripts to be run before db boot + ## e.g: + ## scripts: + ## my_pre_init_script.sh: | + ## #!/bin/sh + ## echo "Do something." + scripts: {} + ## @param primary.preInitDb.scriptsConfigMap ConfigMap with pre-init scripts to be run + ## NOTE: This will override `primary.preInitDb.scripts` + scriptsConfigMap: "" + ## @param primary.preInitDb.scriptsSecret Secret with pre-init scripts to be run + ## NOTE: This can work along `primary.preInitDb.scripts` or `primary.preInitDb.scriptsConfigMap` + scriptsSecret: "" + ## Configure current cluster's primary server to be the standby server in other cluster. + ## This will allow cross cluster replication and provide cross cluster high availability. + ## You will need to configure pgHbaConfiguration if you want to enable this feature with local cluster replication enabled. + ## @param primary.standby.enabled Whether to enable current cluster's primary as standby server of another cluster or not + ## @param primary.standby.primaryHost The Host of replication primary in the other cluster + ## @param primary.standby.primaryPort The Port of replication primary in the other cluster + ## + standby: + enabled: false + primaryHost: "" + primaryPort: "" + ## @param primary.extraEnvVars Array with extra environment variables to add to PostgreSQL Primary nodes + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param primary.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for PostgreSQL Primary nodes + ## + extraEnvVarsCM: "" + ## @param primary.extraEnvVarsSecret Name of existing Secret containing extra env vars for PostgreSQL Primary nodes + ## + extraEnvVarsSecret: "" + ## @param primary.command Override default container command (useful when using custom images) + ## + command: [] + ## @param primary.args Override default container args (useful when using custom images) + ## + args: [] + ## Configure extra options for PostgreSQL Primary containers' liveness, readiness and startup probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#configure-probes + ## @param primary.livenessProbe.enabled Enable livenessProbe on PostgreSQL Primary containers + ## @param primary.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param primary.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param primary.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param primary.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param primary.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param primary.readinessProbe.enabled Enable readinessProbe on PostgreSQL Primary containers + ## @param primary.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param primary.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param primary.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param primary.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param primary.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param primary.startupProbe.enabled Enable startupProbe on PostgreSQL Primary containers + ## @param primary.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param primary.startupProbe.periodSeconds Period seconds for startupProbe + ## @param primary.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param primary.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param primary.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 15 + successThreshold: 1 + ## @param primary.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param primary.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param primary.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param primary.lifecycleHooks for the PostgreSQL Primary container to automate configuration before or after startup + ## + lifecycleHooks: {} + ## PostgreSQL Primary resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param primary.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if primary.resources is set (primary.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param primary.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Pod Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + ## @param primary.podSecurityContext.enabled Enable security context + ## @param primary.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy + ## @param primary.podSecurityContext.sysctls Set kernel settings using the sysctl interface + ## @param primary.podSecurityContext.supplementalGroups Set filesystem extra groups + ## @param primary.podSecurityContext.fsGroup Group ID for the pod + ## + podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + sysctls: [] + supplementalGroups: [] + fsGroup: 1001 + ## Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + ## @param primary.containerSecurityContext.enabled Enabled containers' Security Context + ## @param primary.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param primary.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param primary.containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup + ## @param primary.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param primary.containerSecurityContext.privileged Set container's Security Context privileged + ## @param primary.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param primary.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param primary.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param primary.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## @param primary.automountServiceAccountToken Mount Service Account token in pod + ## + automountServiceAccountToken: false + ## @param primary.hostAliases PostgreSQL primary pods host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param primary.hostNetwork Specify if host network should be enabled for PostgreSQL pod (postgresql primary) + ## + hostNetwork: false + ## @param primary.hostIPC Specify if host IPC should be enabled for PostgreSQL pod (postgresql primary) + ## + hostIPC: false + ## @param primary.labels Map of labels to add to the statefulset (postgresql primary) + ## + labels: {} + ## @param primary.annotations Annotations for PostgreSQL primary pods + ## + annotations: {} + ## @param primary.podLabels Map of labels to add to the pods (postgresql primary) + ## + podLabels: {} + ## @param primary.podAnnotations Map of annotations to add to the pods (postgresql primary) + ## + podAnnotations: {} + ## @param primary.podAffinityPreset PostgreSQL primary pod affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param primary.podAntiAffinityPreset PostgreSQL primary pod anti-affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## PostgreSQL Primary node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param primary.nodeAffinityPreset.type PostgreSQL primary node affinity preset type. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param primary.nodeAffinityPreset.key PostgreSQL primary node label key to match Ignored if `primary.affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param primary.nodeAffinityPreset.values PostgreSQL primary node label values to match. Ignored if `primary.affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param primary.affinity Affinity for PostgreSQL primary pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## Note: primary.podAffinityPreset, primary.podAntiAffinityPreset, and primary.nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## @param primary.nodeSelector Node labels for PostgreSQL primary pods assignment + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: {} + ## @param primary.tolerations Tolerations for PostgreSQL primary pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param primary.topologySpreadConstraints Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#spread-constraints-for-pods + ## + topologySpreadConstraints: [] + ## @param primary.priorityClassName Priority Class to use for each pod (postgresql primary) + ## + priorityClassName: "" + ## @param primary.schedulerName Use an alternate scheduler, e.g. "stork". + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param primary.terminationGracePeriodSeconds Seconds PostgreSQL primary pod needs to terminate gracefully + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods + ## + terminationGracePeriodSeconds: "" + ## @param primary.updateStrategy.type PostgreSQL Primary statefulset strategy type + ## @param primary.updateStrategy.rollingUpdate PostgreSQL Primary statefulset rolling update configuration parameters + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## + updateStrategy: + type: RollingUpdate + rollingUpdate: {} + ## @param primary.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the PostgreSQL Primary container(s) + ## + extraVolumeMounts: [] + ## @param primary.extraVolumes Optionally specify extra list of additional volumes for the PostgreSQL Primary pod(s) + ## + extraVolumes: [] + ## @param primary.sidecars Add additional sidecar containers to the PostgreSQL Primary pod(s) + ## For example: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param primary.initContainers Add additional init containers to the PostgreSQL Primary pod(s) + ## Example + ## + ## initContainers: + ## - name: do-something + ## image: busybox + ## command: ['do', 'something'] + ## + initContainers: [] + ## Pod Disruption Budget configuration + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb + ## @param primary.pdb.create Enable/disable a Pod Disruption Budget creation + ## @param primary.pdb.minAvailable Minimum number/percentage of pods that should remain scheduled + ## @param primary.pdb.maxUnavailable Maximum number/percentage of pods that may be made unavailable. Defaults to `1` if both `primary.pdb.minAvailable` and `primary.pdb.maxUnavailable` are empty. + ## + pdb: + create: true + minAvailable: "" + maxUnavailable: "" + ## @param primary.extraPodSpec Optionally specify extra PodSpec for the PostgreSQL Primary pod(s) + ## + extraPodSpec: {} + ## Network Policies + ## Ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ + ## + networkPolicy: + ## @param primary.networkPolicy.enabled Specifies whether a NetworkPolicy should be created + ## + enabled: true + ## @param primary.networkPolicy.allowExternal Don't require server label for connections + ## The Policy model to apply. When set to false, only pods with the correct + ## server label will have network access to the ports server is listening + ## on. When true, server will accept connections from any source + ## (with the correct destination port). + ## + allowExternal: true + ## @param primary.networkPolicy.allowExternalEgress Allow the pod to access any range of port and all destinations. + ## + allowExternalEgress: true + ## @param primary.networkPolicy.extraIngress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraIngress: + ## - ports: + ## - port: 1234 + ## from: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + extraIngress: [] + ## @param primary.networkPolicy.extraEgress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraEgress: + ## - ports: + ## - port: 1234 + ## to: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraEgress: [] + ## @param primary.networkPolicy.ingressNSMatchLabels [object] Labels to match to allow traffic from other namespaces + ## @param primary.networkPolicy.ingressNSPodMatchLabels [object] Pod labels to match to allow traffic from other namespaces + ## + ingressNSMatchLabels: {} + ingressNSPodMatchLabels: {} + ## PostgreSQL Primary service configuration + ## + service: + ## @param primary.service.type Kubernetes Service type + ## + type: ClusterIP + ## @param primary.service.ports.postgresql PostgreSQL service port + ## + ports: + postgresql: 5432 + ## Node ports to expose + ## NOTE: choose port between <30000-32767> + ## @param primary.service.nodePorts.postgresql Node port for PostgreSQL + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + nodePorts: + postgresql: "" + ## @param primary.service.clusterIP Static clusterIP or None for headless services + ## e.g: + ## clusterIP: None + ## + clusterIP: "" + ## @param primary.service.labels Map of labels to add to the primary service + ## + labels: {} + ## @param primary.service.annotations Annotations for PostgreSQL primary service + ## + annotations: {} + ## @param primary.service.loadBalancerClass Load balancer class if service type is `LoadBalancer` + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + ## + loadBalancerClass: "" + ## @param primary.service.loadBalancerIP Load balancer IP if service type is `LoadBalancer` + ## Set the LoadBalancer service type to internal only + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param primary.service.externalTrafficPolicy Enable client source IP preservation + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param primary.service.loadBalancerSourceRanges Addresses that are allowed when service is LoadBalancer + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param primary.service.extraPorts Extra ports to expose in the PostgreSQL primary service + ## + extraPorts: [] + ## @param primary.service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param primary.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## Headless service properties + ## + headless: + ## @param primary.service.headless.annotations Additional custom annotations for headless PostgreSQL primary service + ## + annotations: {} + ## PostgreSQL Primary persistence configuration + ## + persistence: + ## @param primary.persistence.enabled Enable PostgreSQL Primary data persistence using PVC + ## + enabled: true + ## @param primary.persistence.volumeName Name to assign the volume + ## + volumeName: "data" + ## @param primary.persistence.existingClaim Name of an existing PVC to use + ## + existingClaim: "" + ## @param primary.persistence.mountPath The path the volume will be mounted at + ## Note: useful when using custom PostgreSQL images + ## + mountPath: /bitnami/postgresql + ## @param primary.persistence.subPath The subdirectory of the volume to mount to + ## Useful in dev environments and one PV for multiple services + ## + subPath: "" + ## @param primary.persistence.storageClass PVC Storage Class for PostgreSQL Primary data volume + ## 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: "" + ## @param primary.persistence.accessModes PVC Access Mode for PostgreSQL volume + ## + accessModes: + - ReadWriteOnce + ## @param primary.persistence.size PVC Storage Request for PostgreSQL volume + ## + size: 8Gi + ## @param primary.persistence.annotations Annotations for the PVC + ## + annotations: {} + ## @param primary.persistence.labels Labels for the PVC + ## + labels: {} + ## @param primary.persistence.selector Selector to match an existing Persistent Volume (this value is evaluated as a template) + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## @param primary.persistence.dataSource Custom PVC data source + ## + dataSource: {} + ## PostgreSQL Primary Persistent Volume Claim Retention Policy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention + ## + persistentVolumeClaimRetentionPolicy: + ## @param primary.persistentVolumeClaimRetentionPolicy.enabled Enable Persistent volume retention policy for Primary Statefulset + ## + enabled: false + ## @param primary.persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced + ## + whenScaled: Retain + ## @param primary.persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted + ## + whenDeleted: Retain +## @section PostgreSQL read only replica parameters (only used when `architecture` is set to `replication`) +## +readReplicas: + ## @param readReplicas.name Name of the read replicas database (eg secondary, slave, ...) + ## + name: read + ## @param readReplicas.replicaCount Number of PostgreSQL read only replicas + ## + replicaCount: 1 + ## @param readReplicas.extendedConfiguration Extended PostgreSQL read only replicas configuration (appended to main or default configuration) + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql#allow-settings-to-be-loaded-from-files-other-than-the-default-postgresqlconf + ## + extendedConfiguration: "" + ## @param readReplicas.extraEnvVars Array with extra environment variables to add to PostgreSQL read only nodes + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param readReplicas.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for PostgreSQL read only nodes + ## + extraEnvVarsCM: "" + ## @param readReplicas.extraEnvVarsSecret Name of existing Secret containing extra env vars for PostgreSQL read only nodes + ## + extraEnvVarsSecret: "" + ## @param readReplicas.command Override default container command (useful when using custom images) + ## + command: [] + ## @param readReplicas.args Override default container args (useful when using custom images) + ## + args: [] + ## Configure extra options for PostgreSQL read only containers' liveness, readiness and startup probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#configure-probes + ## @param readReplicas.livenessProbe.enabled Enable livenessProbe on PostgreSQL read only containers + ## @param readReplicas.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param readReplicas.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param readReplicas.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param readReplicas.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param readReplicas.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param readReplicas.readinessProbe.enabled Enable readinessProbe on PostgreSQL read only containers + ## @param readReplicas.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param readReplicas.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param readReplicas.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param readReplicas.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param readReplicas.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param readReplicas.startupProbe.enabled Enable startupProbe on PostgreSQL read only containers + ## @param readReplicas.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param readReplicas.startupProbe.periodSeconds Period seconds for startupProbe + ## @param readReplicas.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param readReplicas.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param readReplicas.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 15 + successThreshold: 1 + ## @param readReplicas.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param readReplicas.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param readReplicas.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param readReplicas.lifecycleHooks for the PostgreSQL read only container to automate configuration before or after startup + ## + lifecycleHooks: {} + ## PostgreSQL read only resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param readReplicas.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if readReplicas.resources is set (readReplicas.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param readReplicas.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Pod Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + ## @param readReplicas.podSecurityContext.enabled Enable security context + ## @param readReplicas.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy + ## @param readReplicas.podSecurityContext.sysctls Set kernel settings using the sysctl interface + ## @param readReplicas.podSecurityContext.supplementalGroups Set filesystem extra groups + ## @param readReplicas.podSecurityContext.fsGroup Group ID for the pod + ## + podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + sysctls: [] + supplementalGroups: [] + fsGroup: 1001 + ## Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + ## @param readReplicas.containerSecurityContext.enabled Enabled containers' Security Context + ## @param readReplicas.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param readReplicas.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param readReplicas.containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup + ## @param readReplicas.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param readReplicas.containerSecurityContext.privileged Set container's Security Context privileged + ## @param readReplicas.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param readReplicas.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param readReplicas.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param readReplicas.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## @param readReplicas.automountServiceAccountToken Mount Service Account token in pod + ## + automountServiceAccountToken: false + ## @param readReplicas.hostAliases PostgreSQL read only pods host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param readReplicas.hostNetwork Specify if host network should be enabled for PostgreSQL pod (PostgreSQL read only) + ## + hostNetwork: false + ## @param readReplicas.hostIPC Specify if host IPC should be enabled for PostgreSQL pod (postgresql primary) + ## + hostIPC: false + ## @param readReplicas.labels Map of labels to add to the statefulset (PostgreSQL read only) + ## + labels: {} + ## @param readReplicas.annotations Annotations for PostgreSQL read only pods + ## + annotations: {} + ## @param readReplicas.podLabels Map of labels to add to the pods (PostgreSQL read only) + ## + podLabels: {} + ## @param readReplicas.podAnnotations Map of annotations to add to the pods (PostgreSQL read only) + ## + podAnnotations: {} + ## @param readReplicas.podAffinityPreset PostgreSQL read only pod affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param readReplicas.podAntiAffinityPreset PostgreSQL read only pod anti-affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## PostgreSQL read only node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param readReplicas.nodeAffinityPreset.type PostgreSQL read only node affinity preset type. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param readReplicas.nodeAffinityPreset.key PostgreSQL read only node label key to match Ignored if `primary.affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param readReplicas.nodeAffinityPreset.values PostgreSQL read only node label values to match. Ignored if `primary.affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param readReplicas.affinity Affinity for PostgreSQL read only pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## Note: primary.podAffinityPreset, primary.podAntiAffinityPreset, and primary.nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## @param readReplicas.nodeSelector Node labels for PostgreSQL read only pods assignment + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: {} + ## @param readReplicas.tolerations Tolerations for PostgreSQL read only pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param readReplicas.topologySpreadConstraints Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#spread-constraints-for-pods + ## + topologySpreadConstraints: [] + ## @param readReplicas.priorityClassName Priority Class to use for each pod (PostgreSQL read only) + ## + priorityClassName: "" + ## @param readReplicas.schedulerName Use an alternate scheduler, e.g. "stork". + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param readReplicas.terminationGracePeriodSeconds Seconds PostgreSQL read only pod needs to terminate gracefully + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods + ## + terminationGracePeriodSeconds: "" + ## @param readReplicas.updateStrategy.type PostgreSQL read only statefulset strategy type + ## @param readReplicas.updateStrategy.rollingUpdate PostgreSQL read only statefulset rolling update configuration parameters + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## + updateStrategy: + type: RollingUpdate + rollingUpdate: {} + ## @param readReplicas.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the PostgreSQL read only container(s) + ## + extraVolumeMounts: [] + ## @param readReplicas.extraVolumes Optionally specify extra list of additional volumes for the PostgreSQL read only pod(s) + ## + extraVolumes: [] + ## @param readReplicas.sidecars Add additional sidecar containers to the PostgreSQL read only pod(s) + ## For example: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param readReplicas.initContainers Add additional init containers to the PostgreSQL read only pod(s) + ## Example + ## + ## initContainers: + ## - name: do-something + ## image: busybox + ## command: ['do', 'something'] + ## + initContainers: [] + ## Pod Disruption Budget configuration + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb + ## @param readReplicas.pdb.create Enable/disable a Pod Disruption Budget creation + ## @param readReplicas.pdb.minAvailable Minimum number/percentage of pods that should remain scheduled + ## @param readReplicas.pdb.maxUnavailable Maximum number/percentage of pods that may be made unavailable. Defaults to `1` if both `readReplicas.pdb.minAvailable` and `readReplicas.pdb.maxUnavailable` are empty. + ## + pdb: + create: true + minAvailable: "" + maxUnavailable: "" + ## @param readReplicas.extraPodSpec Optionally specify extra PodSpec for the PostgreSQL read only pod(s) + ## + extraPodSpec: {} + ## Network Policies + ## Ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ + ## + networkPolicy: + ## @param readReplicas.networkPolicy.enabled Specifies whether a NetworkPolicy should be created + ## + enabled: true + ## @param readReplicas.networkPolicy.allowExternal Don't require server label for connections + ## The Policy model to apply. When set to false, only pods with the correct + ## server label will have network access to the ports server is listening + ## on. When true, server will accept connections from any source + ## (with the correct destination port). + ## + allowExternal: true + ## @param readReplicas.networkPolicy.allowExternalEgress Allow the pod to access any range of port and all destinations. + ## + allowExternalEgress: true + ## @param readReplicas.networkPolicy.extraIngress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraIngress: + ## - ports: + ## - port: 1234 + ## from: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + extraIngress: [] + ## @param readReplicas.networkPolicy.extraEgress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraEgress: + ## - ports: + ## - port: 1234 + ## to: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraEgress: [] + ## @param readReplicas.networkPolicy.ingressNSMatchLabels [object] Labels to match to allow traffic from other namespaces + ## @param readReplicas.networkPolicy.ingressNSPodMatchLabels [object] Pod labels to match to allow traffic from other namespaces + ## + ingressNSMatchLabels: {} + ingressNSPodMatchLabels: {} + ## PostgreSQL read only service configuration + ## + service: + ## @param readReplicas.service.type Kubernetes Service type + ## + type: ClusterIP + ## @param readReplicas.service.ports.postgresql PostgreSQL service port + ## + ports: + postgresql: 5432 + ## Node ports to expose + ## NOTE: choose port between <30000-32767> + ## @param readReplicas.service.nodePorts.postgresql Node port for PostgreSQL + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + nodePorts: + postgresql: "" + ## @param readReplicas.service.clusterIP Static clusterIP or None for headless services + ## e.g: + ## clusterIP: None + ## + clusterIP: "" + ## @param readReplicas.service.labels Map of labels to add to the read service + ## + labels: {} + ## @param readReplicas.service.annotations Annotations for PostgreSQL read only service + ## + annotations: {} + ## @param readReplicas.service.loadBalancerClass Load balancer class if service type is `LoadBalancer` + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + ## + loadBalancerClass: "" + ## @param readReplicas.service.loadBalancerIP Load balancer IP if service type is `LoadBalancer` + ## Set the LoadBalancer service type to internal only + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param readReplicas.service.externalTrafficPolicy Enable client source IP preservation + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param readReplicas.service.loadBalancerSourceRanges Addresses that are allowed when service is LoadBalancer + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param readReplicas.service.extraPorts Extra ports to expose in the PostgreSQL read only service + ## + extraPorts: [] + ## @param readReplicas.service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param readReplicas.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## Headless service properties + ## + headless: + ## @param readReplicas.service.headless.annotations Additional custom annotations for headless PostgreSQL read only service + ## + annotations: {} + ## PostgreSQL read only persistence configuration + ## + persistence: + ## @param readReplicas.persistence.enabled Enable PostgreSQL read only data persistence using PVC + ## + enabled: true + ## @param readReplicas.persistence.existingClaim Name of an existing PVC to use + ## + existingClaim: "" + ## @param readReplicas.persistence.mountPath The path the volume will be mounted at + ## Note: useful when using custom PostgreSQL images + ## + mountPath: /bitnami/postgresql + ## @param readReplicas.persistence.subPath The subdirectory of the volume to mount to + ## Useful in dev environments and one PV for multiple services + ## + subPath: "" + ## @param readReplicas.persistence.storageClass PVC Storage Class for PostgreSQL read only data volume + ## 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: "" + ## @param readReplicas.persistence.accessModes PVC Access Mode for PostgreSQL volume + ## + accessModes: + - ReadWriteOnce + ## @param readReplicas.persistence.size PVC Storage Request for PostgreSQL volume + ## + size: 8Gi + ## @param readReplicas.persistence.annotations Annotations for the PVC + ## + annotations: {} + ## @param readReplicas.persistence.labels Labels for the PVC + ## + labels: {} + ## @param readReplicas.persistence.selector Selector to match an existing Persistent Volume (this value is evaluated as a template) + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## @param readReplicas.persistence.dataSource Custom PVC data source + ## + dataSource: {} + ## PostgreSQL Read only Persistent Volume Claim Retention Policy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention + ## + persistentVolumeClaimRetentionPolicy: + ## @param readReplicas.persistentVolumeClaimRetentionPolicy.enabled Enable Persistent volume retention policy for read only Statefulset + ## + enabled: false + ## @param readReplicas.persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced + ## + whenScaled: Retain + ## @param readReplicas.persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted + ## + whenDeleted: Retain +## @section Backup parameters +## This section implements a trivial logical dump cronjob of the database. +## This only comes with the consistency guarantees of the dump program. +## This is not a snapshot based roll forward/backward recovery backup. +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/ +backup: + ## @param backup.enabled Enable the logical dump of the database "regularly" + enabled: false + cronjob: + ## @param backup.cronjob.schedule Set the cronjob parameter schedule + schedule: "@daily" + ## @param backup.cronjob.timeZone Set the cronjob parameter timeZone + timeZone: "" + ## @param backup.cronjob.concurrencyPolicy Set the cronjob parameter concurrencyPolicy + concurrencyPolicy: Allow + ## @param backup.cronjob.failedJobsHistoryLimit Set the cronjob parameter failedJobsHistoryLimit + failedJobsHistoryLimit: 1 + ## @param backup.cronjob.successfulJobsHistoryLimit Set the cronjob parameter successfulJobsHistoryLimit + successfulJobsHistoryLimit: 3 + ## @param backup.cronjob.startingDeadlineSeconds Set the cronjob parameter startingDeadlineSeconds + startingDeadlineSeconds: "" + ## @param backup.cronjob.ttlSecondsAfterFinished Set the cronjob parameter ttlSecondsAfterFinished + ttlSecondsAfterFinished: "" + ## @param backup.cronjob.restartPolicy Set the cronjob parameter restartPolicy + restartPolicy: OnFailure + ## @param backup.cronjob.podSecurityContext.enabled Enable PodSecurityContext for CronJob/Backup + ## @param backup.cronjob.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy + ## @param backup.cronjob.podSecurityContext.sysctls Set kernel settings using the sysctl interface + ## @param backup.cronjob.podSecurityContext.supplementalGroups Set filesystem extra groups + ## @param backup.cronjob.podSecurityContext.fsGroup Group ID for the CronJob + podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + sysctls: [] + supplementalGroups: [] + fsGroup: 1001 + ## backup container's Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param backup.cronjob.containerSecurityContext.enabled Enabled containers' Security Context + ## @param backup.cronjob.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param backup.cronjob.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param backup.cronjob.containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup + ## @param backup.cronjob.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param backup.cronjob.containerSecurityContext.privileged Set container's Security Context privileged + ## @param backup.cronjob.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param backup.cronjob.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param backup.cronjob.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param backup.cronjob.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## @param backup.cronjob.command Set backup container's command to run + command: + - /bin/bash + - -c + - PGPASSWORD="${PGPASSWORD:-$(< "$PGPASSWORD_FILE")}" pg_dumpall --clean --if-exists --load-via-partition-root --quote-all-identifiers --no-password --file="${PGDUMP_DIR}/pg_dumpall-$(date '+%Y-%m-%d-%H-%M').pgdump" + ## @param backup.cronjob.labels Set the cronjob labels + labels: {} + ## @param backup.cronjob.annotations Set the cronjob annotations + annotations: {} + ## @param backup.cronjob.nodeSelector Node labels for PostgreSQL backup CronJob pod assignment + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/ + ## + nodeSelector: {} + ## @param backup.cronjob.tolerations Tolerations for PostgreSQL backup CronJob pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## backup cronjob container resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param backup.cronjob.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if backup.cronjob.resources is set (backup.cronjob.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param backup.cronjob.resources Set container requests and limits for different resources like CPU or memory + ## Example: + resources: {} + ## resources: + ## requests: + ## cpu: 1 + ## memory: 512Mi + ## limits: + ## cpu: 2 + ## memory: 1024Mi + networkPolicy: + ## @param backup.cronjob.networkPolicy.enabled Specifies whether a NetworkPolicy should be created + ## + enabled: true + storage: + ## @param backup.cronjob.storage.enabled Enable using a `PersistentVolumeClaim` as backup data volume + ## + enabled: true + ## @param backup.cronjob.storage.existingClaim Provide an existing `PersistentVolumeClaim` (only when `architecture=standalone`) + ## If defined, PVC must be created manually before volume will be bound + ## + existingClaim: "" + ## @param backup.cronjob.storage.resourcePolicy Setting it to "keep" to avoid removing PVCs during a helm delete operation. Leaving it empty will delete PVCs after the chart deleted + ## + resourcePolicy: "" + ## @param backup.cronjob.storage.storageClass PVC Storage Class for the backup data volume + ## 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. + ## + storageClass: "" + ## @param backup.cronjob.storage.accessModes PV Access Mode + ## + accessModes: + - ReadWriteOnce + ## @param backup.cronjob.storage.size PVC Storage Request for the backup data volume + ## + size: 8Gi + ## @param backup.cronjob.storage.annotations PVC annotations + ## + annotations: {} + ## @param backup.cronjob.storage.mountPath Path to mount the volume at + ## + mountPath: /backup/pgdump + ## @param backup.cronjob.storage.subPath Subdirectory of the volume to mount at + ## and one PV for multiple services. + ## + subPath: "" + ## Fine tuning for volumeClaimTemplates + ## + volumeClaimTemplates: + ## @param backup.cronjob.storage.volumeClaimTemplates.selector A label query over volumes to consider for binding (e.g. when using local volumes) + ## A label query over volumes to consider for binding (e.g. when using local volumes) + ## See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#labelselector-v1-meta for more details + ## + selector: {} + ## @param backup.cronjob.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the backup container + ## + extraVolumeMounts: [] + ## @param backup.cronjob.extraVolumes Optionally specify extra list of additional volumes for the backup container + ## + extraVolumes: [] + +## @section Password update job +## +passwordUpdateJob: + ## @param passwordUpdateJob.enabled Enable password update job + ## + enabled: false + ## @param passwordUpdateJob.backoffLimit set backoff limit of the job + ## + backoffLimit: 10 + ## @param passwordUpdateJob.command Override default container command on mysql Primary container(s) (useful when using custom images) + ## + command: [] + ## @param passwordUpdateJob.args Override default container args on mysql Primary container(s) (useful when using custom images) + ## + args: [] + ## @param passwordUpdateJob.extraCommands Extra commands to pass to the generation job + ## + extraCommands: "" + ## @param passwordUpdateJob.previousPasswords.postgresPassword Previous postgres password (set if the password secret was already changed) + ## @param passwordUpdateJob.previousPasswords.password Previous password (set if the password secret was already changed) + ## @param passwordUpdateJob.previousPasswords.replicationPassword Previous replication password (set if the password secret was already changed) + ## @param passwordUpdateJob.previousPasswords.existingSecret Name of a secret containing the previous passwords (set if the password secret was already changed) + previousPasswords: + postgresPassword: "" + password: "" + replicationPassword: "" + existingSecret: "" + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param passwordUpdateJob.containerSecurityContext.enabled Enabled containers' Security Context + ## @param passwordUpdateJob.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param passwordUpdateJob.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param passwordUpdateJob.containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup + ## @param passwordUpdateJob.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param passwordUpdateJob.containerSecurityContext.privileged Set container's Security Context privileged + ## @param passwordUpdateJob.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param passwordUpdateJob.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param passwordUpdateJob.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param passwordUpdateJob.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## Configure Pods Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param passwordUpdateJob.podSecurityContext.enabled Enabled credential init job pods' Security Context + ## @param passwordUpdateJob.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy + ## @param passwordUpdateJob.podSecurityContext.sysctls Set kernel settings using the sysctl interface + ## @param passwordUpdateJob.podSecurityContext.supplementalGroups Set filesystem extra groups + ## @param passwordUpdateJob.podSecurityContext.fsGroup Set credential init job pod's Security Context fsGroup + ## + podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + sysctls: [] + supplementalGroups: [] + fsGroup: 1001 + ## @param passwordUpdateJob.extraEnvVars Array containing extra env vars to configure the credential init job + ## For example: + ## extraEnvVars: + ## - name: GF_DEFAULT_INSTANCE_NAME + ## value: my-instance + ## + extraEnvVars: [] + ## @param passwordUpdateJob.extraEnvVarsCM ConfigMap containing extra env vars to configure the credential init job + ## + extraEnvVarsCM: "" + ## @param passwordUpdateJob.extraEnvVarsSecret Secret containing extra env vars to configure the credential init job (in case of sensitive data) + ## + extraEnvVarsSecret: "" + ## @param passwordUpdateJob.extraVolumes Optionally specify extra list of additional volumes for the credential init job + ## + extraVolumes: [] + ## @param passwordUpdateJob.extraVolumeMounts Array of extra volume mounts to be added to the jwt Container (evaluated as template). Normally used with `extraVolumes`. + ## + extraVolumeMounts: [] + ## @param passwordUpdateJob.initContainers Add additional init containers for the mysql Primary pod(s) + ## + initContainers: [] + ## Container resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param passwordUpdateJob.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if passwordUpdateJob.resources is set (passwordUpdateJob.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "micro" + ## @param passwordUpdateJob.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## @param passwordUpdateJob.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param passwordUpdateJob.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param passwordUpdateJob.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param passwordUpdateJob.automountServiceAccountToken Mount Service Account token in pod + ## + automountServiceAccountToken: false + ## @param passwordUpdateJob.hostAliases Add deployment host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param passwordUpdateJob.annotations [object] Add annotations to the job + ## + annotations: {} + ## @param passwordUpdateJob.podLabels Additional pod labels + ## Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param passwordUpdateJob.podAnnotations Additional pod annotations + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + +## @section Volume Permissions parameters +## + +## Init containers parameters: +## volumePermissions: Change the owner and group of the persistent volume(s) mountpoint(s) to 'runAsUser:fsGroup' on each node +## +volumePermissions: + ## @param volumePermissions.enabled Enable init container that changes the owner and group of the persistent volume + ## + enabled: false + ## @param volumePermissions.image.registry [default: REGISTRY_NAME] Init container volume-permissions image registry + ## @param volumePermissions.image.repository [default: REPOSITORY_NAME/os-shell] Init container volume-permissions image repository + ## @skip volumePermissions.image.tag Init container volume-permissions image tag (immutable tags are recommended) + ## @param volumePermissions.image.digest Init container volume-permissions image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param volumePermissions.image.pullPolicy Init container volume-permissions image pull policy + ## @param volumePermissions.image.pullSecrets Init container volume-permissions image pull secrets + ## + image: + registry: docker.io + repository: bitnami/os-shell + tag: 12-debian-12-r51 + digest: "" + 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/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Init container resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param volumePermissions.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if volumePermissions.resources is set (volumePermissions.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param volumePermissions.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Init container' Security Context + ## Note: the chown of the data folder is done to containerSecurityContext.runAsUser + ## and not the below volumePermissions.containerSecurityContext.runAsUser + ## @param volumePermissions.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param volumePermissions.containerSecurityContext.runAsUser User ID for the init container + ## @param volumePermissions.containerSecurityContext.runAsGroup Group ID for the init container + ## @param volumePermissions.containerSecurityContext.runAsNonRoot runAsNonRoot for the init container + ## @param volumePermissions.containerSecurityContext.seccompProfile.type seccompProfile.type for the init container + ## + containerSecurityContext: + seLinuxOptions: {} + runAsUser: 0 + runAsGroup: 0 + runAsNonRoot: false + seccompProfile: + type: RuntimeDefault +## @section Other Parameters +## + +## @param serviceBindings.enabled Create secret for service binding (Experimental) +## Ref: https://servicebinding.io/service-provider/ +## +serviceBindings: + enabled: false +## Service account for PostgreSQL to use. +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ +## +serviceAccount: + ## @param serviceAccount.create Enable creation of ServiceAccount for PostgreSQL pod + ## + create: true + ## @param serviceAccount.name The name of the ServiceAccount to use. + ## If not set and create is true, a name is generated using the common.names.fullname template + ## + name: "" + ## @param serviceAccount.automountServiceAccountToken Allows auto mount of ServiceAccountToken on the serviceAccount created + ## Can be set to false if pods using this serviceAccount do not need to use K8s API + ## + automountServiceAccountToken: false + ## @param serviceAccount.annotations Additional custom annotations for the ServiceAccount + ## + annotations: {} +## Creates role for ServiceAccount +## @param rbac.create Create Role and RoleBinding (required for PSP to work) +## +rbac: + create: false + ## @param rbac.rules Custom RBAC rules to set + ## e.g: + ## rules: + ## - apiGroups: + ## - "" + ## resources: + ## - pods + ## verbs: + ## - get + ## - list + ## + rules: [] +## Pod Security Policy +## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ +## @param psp.create Whether to create a PodSecurityPolicy. WARNING: PodSecurityPolicy is deprecated in Kubernetes v1.21 or later, unavailable in v1.25 or later +## +psp: + create: false +## @section Metrics Parameters +## +metrics: + ## @param metrics.enabled Start a prometheus exporter + ## + enabled: false + ## @param metrics.image.registry [default: REGISTRY_NAME] PostgreSQL Prometheus Exporter image registry + ## @param metrics.image.repository [default: REPOSITORY_NAME/postgres-exporter] PostgreSQL Prometheus Exporter image repository + ## @skip metrics.image.tag PostgreSQL Prometheus Exporter image tag (immutable tags are recommended) + ## @param metrics.image.digest PostgreSQL image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param metrics.image.pullPolicy PostgreSQL Prometheus Exporter image pull policy + ## @param metrics.image.pullSecrets Specify image pull secrets + ## + image: + registry: docker.io + repository: bitnami/postgres-exporter + tag: 0.17.1-debian-12-r16 + digest: "" + 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/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## @param metrics.collectors Control enabled collectors + ## ref: https://github.com/prometheus-community/postgres_exporter#flags + ## Example: + ## collectors: + ## wal: false + collectors: {} + ## @param metrics.customMetrics Define additional custom metrics + ## ref: https://github.com/prometheus-community/postgres_exporter#adding-new-metrics-via-a-config-file-deprecated + ## 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_bytes 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" + ## + customMetrics: {} + ## @param metrics.extraEnvVars Extra environment variables to add to PostgreSQL Prometheus exporter + ## see: https://github.com/prometheus-community/postgres_exporter#environment-variables + ## For example: + ## extraEnvVars: + ## - name: PG_EXPORTER_DISABLE_DEFAULT_METRICS + ## value: "true" + ## + extraEnvVars: [] + ## PostgreSQL Prometheus exporter containers' Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param metrics.containerSecurityContext.enabled Enabled containers' Security Context + ## @param metrics.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param metrics.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param metrics.containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup + ## @param metrics.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param metrics.containerSecurityContext.privileged Set container's Security Context privileged + ## @param metrics.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param metrics.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param metrics.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param metrics.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## Configure extra options for PostgreSQL Prometheus exporter containers' liveness, readiness and startup probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#configure-probes + ## @param metrics.livenessProbe.enabled Enable livenessProbe on PostgreSQL Prometheus exporter containers + ## @param metrics.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param metrics.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param metrics.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param metrics.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param metrics.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param metrics.readinessProbe.enabled Enable readinessProbe on PostgreSQL Prometheus exporter containers + ## @param metrics.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param metrics.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param metrics.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param metrics.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param metrics.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param metrics.startupProbe.enabled Enable startupProbe on PostgreSQL Prometheus exporter containers + ## @param metrics.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param metrics.startupProbe.periodSeconds Period seconds for startupProbe + ## @param metrics.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param metrics.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param metrics.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 15 + successThreshold: 1 + ## @param metrics.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param metrics.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param metrics.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param metrics.containerPorts.metrics PostgreSQL Prometheus exporter metrics container port + ## + containerPorts: + metrics: 9187 + ## PostgreSQL Prometheus exporter resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param metrics.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if metrics.resources is set (metrics.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param metrics.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Service configuration + ## + service: + ## @param metrics.service.ports.metrics PostgreSQL Prometheus Exporter service port + ## + ports: + metrics: 9187 + ## @param metrics.service.clusterIP Static clusterIP or None for headless services + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#choosing-your-own-ip-address + ## + clusterIP: "" + ## @param metrics.service.sessionAffinity Control where client requests go, to the same pod or round-robin + ## Values: ClientIP or None + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/ + ## + sessionAffinity: None + ## @param metrics.service.annotations [object] Annotations for Prometheus to auto-discover the metrics endpoint + ## + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "{{ .Values.metrics.service.ports.metrics }}" + ## Prometheus Operator ServiceMonitor configuration + ## + serviceMonitor: + ## @param metrics.serviceMonitor.enabled Create ServiceMonitor Resource for scraping metrics using Prometheus Operator + ## + enabled: false + ## @param metrics.serviceMonitor.namespace Namespace for the ServiceMonitor Resource (defaults to the Release Namespace) + ## + namespace: "" + ## @param metrics.serviceMonitor.interval Interval at which metrics should be scraped. + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint + ## + interval: "" + ## @param metrics.serviceMonitor.scrapeTimeout Timeout after which the scrape is ended + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint + ## + scrapeTimeout: "" + ## @param metrics.serviceMonitor.labels Additional labels that can be used so ServiceMonitor will be discovered by Prometheus + ## + labels: {} + ## @param metrics.serviceMonitor.selector Prometheus instance selector labels + ## ref: https://github.com/bitnami/charts/tree/main/bitnami/prometheus-operator#prometheus-configuration + ## + selector: {} + ## @param metrics.serviceMonitor.relabelings RelabelConfigs to apply to samples before scraping + ## + relabelings: [] + ## @param metrics.serviceMonitor.metricRelabelings MetricRelabelConfigs to apply to samples before ingestion + ## + metricRelabelings: [] + ## @param metrics.serviceMonitor.honorLabels Specify honorLabels parameter to add the scrape endpoint + ## + honorLabels: false + ## @param metrics.serviceMonitor.jobLabel The name of the label on the target service to use as the job name in prometheus. + ## + jobLabel: "" + ## 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: + ## @param metrics.prometheusRule.enabled Create a PrometheusRule for Prometheus Operator + ## + enabled: false + ## @param metrics.prometheusRule.namespace Namespace for the PrometheusRule Resource (defaults to the Release Namespace) + ## + namespace: "" + ## @param metrics.prometheusRule.labels Additional labels that can be used so PrometheusRule will be discovered by Prometheus + ## + labels: {} + ## @param metrics.prometheusRule.rules PrometheusRule definitions + ## Make sure to constraint the rules to the current postgresql service. + ## rules: + ## - alert: HugeReplicationLag + ## expr: pg_replication_lag{service="{{ printf "%s-metrics" (include "postgresql.v1.chart.fullname" .) }}"} / 3600 > 1 + ## for: 1m + ## labels: + ## severity: critical + ## annotations: + ## description: replication for {{ include "postgresql.v1.chart.fullname" . }} PostgreSQL is lagging by {{ "{{ $value }}" }} hour(s). + ## summary: PostgreSQL replication is lagging by {{ "{{ $value }}" }} hour(s). + ## + rules: [] diff --git a/backing-services/gitea/charts/valkey-cluster/.helmignore b/backing-services/gitea/charts/valkey-cluster/.helmignore new file mode 100644 index 0000000..207983f --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/.helmignore @@ -0,0 +1,25 @@ +# 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 +# img folder +img/ +# Changelog +CHANGELOG.md diff --git a/backing-services/gitea/charts/valkey-cluster/Chart.lock b/backing-services/gitea/charts/valkey-cluster/Chart.lock new file mode 100644 index 0000000..ba31610 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + version: 2.31.4 +digest: sha256:fc442e77200e1914dd46fe26490dcf62f44caa51db673c2f8e67d5319cd4c163 +generated: "2025-08-13T18:18:55.966303827Z" diff --git a/backing-services/gitea/charts/valkey-cluster/Chart.yaml b/backing-services/gitea/charts/valkey-cluster/Chart.yaml new file mode 100644 index 0000000..ab79fb3 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/Chart.yaml @@ -0,0 +1,36 @@ +annotations: + category: Database + images: | + - name: os-shell + image: docker.io/bitnami/os-shell:12-debian-12-r51 + - name: redis-exporter + image: docker.io/bitnami/redis-exporter:1.76.0-debian-12-r0 + - name: valkey-cluster + image: docker.io/bitnami/valkey-cluster:8.1.3-debian-12-r3 + licenses: Apache-2.0 + tanzuCategory: service +apiVersion: v2 +appVersion: 8.1.3 +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + tags: + - bitnami-common + version: 2.x.x +description: Valkey is an open source (BSD) high-performance key/value datastore that + supports a variety workloads such as caching, message queues, and can act as a primary + database. +home: https://bitnami.com +icon: https://dyltqmyl993wv.cloudfront.net/assets/stacks/valkey/img/valkey-stack-220x234.png +keywords: +- valkey +- keyvalue +- database +maintainers: +- name: Broadcom, Inc. All Rights Reserved. + url: https://github.com/bitnami/charts +name: valkey-cluster +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/valkey-cluster +- https://github.com/bitnami/containers/tree/main/bitnami/vakey-cluster +version: 3.0.24 diff --git a/backing-services/gitea/charts/valkey-cluster/README.md b/backing-services/gitea/charts/valkey-cluster/README.md new file mode 100644 index 0000000..e34360a --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/README.md @@ -0,0 +1,763 @@ + + +# Bitnami package for Valkey Cluster + +Valkey is an open source (BSD) high-performance key/value datastore that supports a variety workloads such as caching, message queues, and can act as a primary database. + +[Overview of Valkey Cluster](https://valkey.io/) + +Trademarks: This software listing is packaged by Bitnami. The respective trademarks mentioned in the offering are owned by the respective companies, and use of them does not imply any affiliation or endorsement. + +## TL;DR + +```console +helm install my-release oci://registry-1.docker.io/bitnamicharts/valkey-cluster +``` + +Looking to use Valkey Cluster in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the commercial edition of the Bitnami catalog. + +## ⚠️ Important Notice: Upcoming changes to the Bitnami Catalog + +Beginning August 28th, 2025, Bitnami will evolve its public catalog to offer a curated set of hardened, security-focused images under the new [Bitnami Secure Images initiative](https://news.broadcom.com/app-dev/broadcom-introduces-bitnami-secure-images-for-production-ready-containerized-applications). As part of this transition: + +- Granting community users access for the first time to security-optimized versions of popular container images. +- Bitnami will begin deprecating support for non-hardened, Debian-based software images in its free tier and will gradually remove non-latest tags from the public catalog. As a result, community users will have access to a reduced number of hardened images. These images are published only under the “latest” tag and are intended for development purposes +- Starting August 28th, over two weeks, all existing container images, including older or versioned tags (e.g., 2.50.0, 10.6), will be migrated from the public catalog (docker.io/bitnami) to the “Bitnami Legacy” repository (docker.io/bitnamilegacy), where they will no longer receive updates. +- For production workloads and long-term support, users are encouraged to adopt Bitnami Secure Images, which include hardened containers, smaller attack surfaces, CVE transparency (via VEX/KEV), SBOMs, and enterprise support. + +These changes aim to improve the security posture of all Bitnami users by promoting best practices for software supply chain integrity and up-to-date deployments. For more details, visit the [Bitnami Secure Images announcement](https://github.com/bitnami/containers/issues/83267). + +## Introduction + +This chart bootstraps a [Valkey](https://github.com/bitnami/containers/tree/main/bitnami/valkey) deployment on a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +### Choose between Valkey Helm Chart and Valkey Cluster Helm Chart + +You can choose any of the two Valkey Helm charts for deploying a Valkey cluster. +While [Valkey Helm Chart](https://github.com/bitnami/charts/tree/main/bitnami/valkey) will deploy a primary-replica cluster using Valkey Sentinel, the [Valkey Cluster Helm Chart](https://github.com/bitnami/charts/tree/main/bitnami/valkey-cluster) will deploy a Valkey Cluster with sharding. +The main features of each chart are the following: + +| Valkey | Valkey Cluster | +|--------------------------------------------|------------------------------------------------------------------| +| Supports multiple databases | Supports only one database. Better if you have a big dataset | +| Single write point (single primary) | Multiple write points (multiple primary nodes) | +| ![Valkey Topology](img/valkey-topology.png)| ![Valkey Cluster Topology](img/valkey-cluster-topology.png) | + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ +- 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 oci://REGISTRY_NAME/REPOSITORY_NAME/valkey-cluster +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The command deploys Valkey on the Kubernetes cluster in the default configuration. The [Parameters](#parameters) section lists the parameters that can be configured during installation. + +NOTE: if you get a timeout error waiting for the hook to complete increase the default timeout (300s) to a higher one, for example: + +```console +helm install --timeout 600s myrelease oci://REGISTRY_NAME/REPOSITORY_NAME/valkey-cluster +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> **Tip**: List all releases using `helm list` + +## Configuration and installation details + +### Resource requests and limits + +Bitnami charts allow setting resource requests and limits for all containers inside the chart deployment. These are inside the `resources` value (check parameter table). Setting requests is essential for production workloads and these should be adapted to your specific use case. + +To make this process easier, the chart contains the `resourcesPreset` values, which automatically sets the `resources` section according to different presets. Check these presets in [the bitnami/common chart](https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15). However, in production workloads using `resourcesPreset` is discouraged as it may not fully adapt to your specific needs. Find more information on container resource management in the [official Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). + +### Update credentials + +The Bitnami Valkey Cluster chart, when upgrading, reuses the secret previously rendered by the chart or the one specified in `existingSecret`. To update credentials, use one of the following: + +- Run `helm upgrade` specifying a new password in `password` +- Run `helm upgrade` specifying a new secret in `existingSecret` + +### Prometheus metrics + +This chart can be integrated with Prometheus by setting `metrics.enabled` to `true`. This will deploy a sidecar container with [redis_exporter](https://github.com/oliver006/redis_exporter) in all pods and a `metrics` service, which can be configured under the `metrics.service` section. This `metrics` service will have the necessary annotations to be automatically scraped by Prometheus. + +#### Prometheus requirements + +It is necessary to have a working installation of Prometheus or Prometheus Operator for the integration to work. Install the [Bitnami Prometheus helm chart](https://github.com/bitnami/charts/tree/main/bitnami/prometheus) or the [Bitnami Kube Prometheus helm chart](https://github.com/bitnami/charts/tree/main/bitnami/kube-prometheus) to easily have a working Prometheus in your cluster. + +#### Integration with Prometheus Operator + +The chart can deploy `ServiceMonitor` objects for integration with Prometheus Operator installations. To do so, set the value `metrics.serviceMonitor.enabled=true`. Ensure that the Prometheus Operator `CustomResourceDefinitions` are installed in the cluster or it will fail with the following error: + +```text +no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1" +``` + +Install the [Bitnami Kube Prometheus helm chart](https://github.com/bitnami/charts/tree/main/bitnami/kube-prometheus) for having the necessary CRDs and the Prometheus Operator. + +### [Rolling VS Immutable tags](https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-understand-rolling-tags-containers-index.html) + +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. + +### Use a different Valkey version + +To modify the application version used in this chart, specify a different version of the image using the `image.tag` parameter and/or a different repository using the `image.repository` parameter. + +### Cluster topology + +To successfully set the cluster up, it will need to have at least 3 primary nodes. The total number of nodes is calculated like- `nodes = numOfPrimaryNodes + numOfPrimaryNodes * replicas`. Hence, the defaults `cluster.nodes = 6` and `cluster.replicas = 1` means, 3 primary and 3 replica nodes will be deployed by the chart. + +By default the Valkey Cluster is not accessible from outside the Kubernetes cluster, to access the Valkey Cluster from outside you have to set `cluster.externalAccess.enabled=true` at deployment time. It will create in the first installation only 6 LoadBalancer services, one for each Valkey node, once you have the external IPs of each service you will need to perform an upgrade passing those IPs to the `cluster.externalAccess.service.loadbalancerIP` array. + +The replicas will be read-only replicas of the primary nodes. By default only one service is exposed (when not using the external access mode). You will connect your client to the exposed service, regardless you need to read or write. When a write operation arrives to a replica it will redirect the client to the proper primary node. For example, using `valkey-cli` you will need to provide the `-c` flag for `valkey-cli` to follow the redirection automatically. + +Using the external access mode, you can connect to any of the pods and the replicas will redirect the client in the same way as explained before, but the all the IPs will be public. + +In case the primary crashes, one of his replicas will be promoted to primary. The slots stored by the crashed primary will be unavailable until the replica finish the promotion. If a primary and all his replicas crash, the cluster will be down until one of them is up again. To avoid downtime, it is possible to configure the number of Valkey nodes with `cluster.nodes` and the number of replicas that will be assigned to each primary with `cluster.replicas`. For example: + +- `cluster.nodes=9` ( 3 primary plus 2 replicas for each primary) +- `cluster.replicas=2` + +Providing the values above, the cluster will have 3 primarys and, each primary, will have 2 replicas. + +> NOTE: By default `cluster.init` will be set to `true` in order to initialize the Valkey Cluster in the first installation. If for testing purposes you only want to deploy or upgrade the nodes but avoiding the creation of the cluster you can set `cluster.init` to `false`. + +#### Adding a new node to the cluster + +There is a job that will be executed using a `post-upgrade` hook that will allow you to add a new node. To use it, you should provide some parameters to the upgrade: + +- Pass as `password` the password used in the installation time. If you did not provide a password follow the instructions from the NOTES.txt to get the generated password. +- Set the desired number of nodes at `cluster.nodes`. +- Set the number of current nodes at `cluster.update.currentNumberOfNodes`. +- Set to true `cluster.update.addNodes`. + +The following will be an example to add one more node: + +```console +helm upgrade --timeout 600s --set "password=${VALKEY_PASSWORD},cluster.nodes=7,cluster.update.addNodes=true,cluster.update.currentNumberOfNodes=6" oci://REGISTRY_NAME/REPOSITORY_NAME/valkey-cluster +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +Where `VALKEY_PASSWORD` is the password obtained with the command that appears after the first installation of the Helm Chart. +The cluster will continue up while restarting pods one by one as the quorum is not lost. + +##### External Access + +If you are using external access, to add a new node you will need to perform two upgrades. First upgrade the release to add a new Valkey node and to get a LoadBalancerIP service. For example: + +```console +helm upgrade --set "password=${VALKEY_PASSWORD},cluster.externalAccess.enabled=true,cluster.externalAccess.service.type=LoadBalancer,cluster.externalAccess.service.loadBalancerIP[0]=,cluster.externalAccess.service.loadBalancerIP[1]=,cluster.externalAccess.service.loadBalancerIP[2]=,cluster.externalAccess.service.loadBalancerIP[3]=,cluster.externalAccess.service.loadBalancerIP[4]=,cluster.externalAccess.service.loadBalancerIP[5]=,cluster.externalAccess.service.loadBalancerIP[6]=,cluster.nodes=7,cluster.init=false oci://REGISTRY_NAME/REPOSITORY_NAME/valkey-cluster +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> Important here to provide the loadBalancerIP parameters for the new nodes empty to not get an index error. + +As we want to add a new node, we are setting `cluster.nodes=7` and we leave empty the LoadBalancerIP for the new node, so the cluster will provide the correct one. +`VALKEY_PASSWORD` is the password obtained with the command that appears after the first installation of the Helm Chart. +At this point, you will have a new Valkey Pod that will remain in `crashLoopBackOff` state until we provide the LoadBalancerIP for the new service. +Now, wait until the cluster provides the new LoadBalancerIP for the new service and perform the second upgrade: + +```console +helm upgrade --set "password=${VALKEY_PASSWORD},cluster.externalAccess.enabled=true,cluster.externalAccess.service.type=LoadBalancer,cluster.externalAccess.service.loadBalancerIP[0]=,cluster.externalAccess.service.loadBalancerIP[1]=,cluster.externalAccess.service.loadBalancerIP[2]=,cluster.externalAccess.service.loadBalancerIP[3]=,cluster.externalAccess.service.loadBalancerIP[4]=,cluster.externalAccess.service.loadBalancerIP[5]=,cluster.externalAccess.service.loadBalancerIP[6]=,cluster.nodes=7,cluster.init=false,cluster.update.addNodes=true,cluster.update.newExternalIPs[0]=" oci://REGISTRY_NAME/REPOSITORY_NAME/valkey-cluster +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +Note we are providing the new IPs at `cluster.update.newExternalIPs`, the flag `cluster.update.addNodes=true` to enable the creation of the Job that adds a new node and now we are setting the LoadBalancerIP of the new service instead of leave it empty. + +> NOTE: To avoid the creation of the Job that initializes the Valkey Cluster again, you will need to provide `cluster.init=false`. + +#### Scale down the cluster + +To scale down the Valkey Cluster, follow these steps: + +First perform a normal upgrade setting the `cluster.nodes` value to the desired number of nodes. It should not be less than `6` and the difference between current number of nodes and the desired should be less or equal to `cluster.replicas` to avoid removing primary node an its replicas at the same time. Also it is needed to provide the password using the `password`. For example, having more than 6 nodes, to scale down the cluster to 6 nodes: + +```console +helm upgrade --timeout 600s --set "password=${VALKEY_PASSWORD},cluster.nodes=6" . +``` + +The cluster will continue working during the update as long as the quorum is not lost. + +> NOTE: To avoid the creation of the Job that initializes the Valkey Cluster again, you will need to provide `cluster.init=false`. + +Once all the nodes are ready, get the list of nodes in the cluster using the `CLUSTER NODES` command. You will see references to the ones that were removed. Write down the node IDs of the nodes that show `fail`. In the following example the cluster scaled down from 7 to 6 nodes. + +```console +valkey-cli -a $VALKEY_PASSWORD CLUSTER NODES + +... +b23bcffa1fd64368d445c1d9bd9aeb92641105f7 10.0.0.70:6379@16379 slave,fail - 1645633139060 0 0 connected +... +``` + +In each cluster node, execute the following command. Replace the NODE_ID placeholder. + +```console +valkey-cli -a $VALKEY_PASSWORD CLUSTER FORGET NODE_ID +``` + +In the previous example the commands would look like this in each cluster node: + +```console +valkey-cli -a $VALKEY_PASSWORD CLUSTER FORGET b23bcffa1fd64368d445c1d9bd9aeb92641105f7 +``` + +### Using password file + +To use a password file for Valkey you need to create a secret containing the password. + +> *NOTE*: It is important that the file with the password must be called `valkey-password` + +And then deploy the Helm Chart using the secret name as parameter: + +```text +usePassword=true +usePasswordFile=true +existingSecret=valkey-password-secret +metrics.enabled=true +``` + +### Securing traffic using TLS + +TLS support can be enabled in the chart by specifying the `tls.` parameters while creating a release. The following parameters should be configured to properly enable the TLS support in the cluster: + +- `tls.enabled`: Enable TLS support. Defaults to `false` +- `tls.existingSecret`: Name of the secret that contains the certificates. No defaults. +- `tls.certFilename`: Certificate filename. No defaults. +- `tls.certKeyFilename`: Certificate key filename. No defaults. +- `tls.certCAFilename`: CA Certificate filename. No defaults. + +For example: + +First, create the secret with the certificates files: + +```console +kubectl create secret generic certificates-tls-secret --from-file=./cert.pem --from-file=./cert.key --from-file=./ca.pem +``` + +Then, use the following parameters: + +```console +tls.enabled="true" +tls.existingSecret="certificates-tls-secret" +tls.certFilename="cert.pem" +tls.certKeyFilename="cert.key" +tls.certCAFilename="ca.pem" +``` + +### Sidecars and Init Containers + +If you have a need for additional containers to run within the same pod as Valkey (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 +sidecars: + - name: your-image-name + image: your-image + imagePullPolicy: Always + ports: + - name: portname + containerPort: 1234 +``` + +Similarly, you can add extra init containers using the `initContainers` parameter. + +```yaml +initContainers: + - name: your-image-name + image: your-image + imagePullPolicy: Always + ports: + - name: portname + containerPort: 1234 +``` + +### Adding extra environment variables + +In case you want to add extra environment variables (useful for advanced operations like custom init scripts), you can use the `extraEnvVars` property. + +```yaml +extraEnvVars: + - name: VALKEY_WHATEVER + value: value +``` + +Alternatively, you can use a ConfigMap or a Secret with the environment variables. To do so, use the `extraEnvVarsCM` or the `extraEnvVarsSecret` values. + +### Metrics + +The chart optionally can start a metrics exporter for [prometheus](https://prometheus.io). The metrics endpoint (port 9121) is exposed in the service. Metrics can be scraped from within the 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). If metrics are to be scraped from outside the cluster, the Kubernetes API proxy can be utilized to access the endpoint. + +### Host Kernel Settings + +Valkey may require some changes in the kernel of the host machine to work as expected, in particular increasing the `somaxconn` value and disabling transparent huge pages. +To do so, you can set up a privileged initContainer with the `sysctlImage` config values, for example: + +```yaml +sysctlImage: + enabled: true + mountHostSys: true + command: + - /bin/sh + - -c + - |- + sysctl -w net.core.somaxconn=10000 + echo never > /host-sys/kernel/mm/transparent_hugepage/enabled +``` + +Alternatively, for Kubernetes 1.12+ you can set `podSecurityContext.sysctls` which will configure sysctls for primary and replica pods. Example: + +```yaml +podSecurityContext: + sysctls: + - name: net.core.somaxconn + value: "10000" +``` + +Note that this will not disable transparent huge tables. + +### Helm Upgrade + +By default `cluster.init` will be set to `true` in order to initialize the Valkey Cluster in the first installation. If for testing purposes you only want to deploy or upgrade the nodes but avoiding the creation of the cluster you can set `cluster.init` to `false`. + +### Backup and restore + +To back up and restore Valkey Cluster Helm chart deployments on Kubernetes, you need to back up the persistent volumes from the source deployment and attach them to a new deployment using [Velero](https://velero.io/), a Kubernetes backup/restore tool. + +These are the steps you will usually follow to back up and restore your Valkey Cluster database cluster data: + +- Install Velero on the source and destination clusters. +- Use Velero to back up the PersistentVolumes (PVs) used by the deployment on the source cluster. +- Use Velero to restore the backed-up PVs on the destination cluster. +- Create a new deployment on the destination cluster with the same chart, deployment name, credentials and other parameters as the original. This new deployment will use the restored PVs and hence the original data. + +### NetworkPolicy + +To enable network policy for Valkey, 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, only pods with the generated client label will be +able to connect to Valkey. This label will be displayed in the output +after a successful install. + +With `networkPolicy.ingressNSMatchLabels` pods from other namespaces can connect to valkey. Set `networkPolicy.ingressNSPodMatchLabels` to match pod labels in matched namespace. For example, for a namespace labeled `valkey=external` and pods in that namespace labeled `valkey-client=true` the fields should be set: + +```yaml +networkPolicy: + enabled: true + ingressNSMatchLabels: + valkey: external + ingressNSPodMatchLabels: + valkey-client: true +``` + +#### Setting Pod's affinity + +This chart allows you to set your custom affinity using the `XXX.affinity` paremeter(s). Find more information about Pod's affinity in the [kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). + +As an alternative, you can use of the preset configurations for pod affinity, pod anti-affinity, and node affinity available at the [bitnami/common](https://github.com/bitnami/charts/tree/main/bitnami/common#affinities) chart. To do so, set the `XXX.podAffinityPreset`, `XXX.podAntiAffinityPreset`, or `XXX.nodeAffinityPreset` parameters. + +## Persistence + +By default, the chart mounts a [Persistent Volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) at the `/bitnami` path. The volume is created using dynamic volume provisioning. + +If persistence is disabled, an emptyDir volume is used. **This is only recommended for testing environments** because the required information included in the nodes.conf file is missing. This file contains the relationship between the nodes and the cluster. For example, if any node is down or faulty, when it starts again, it is a self-proclaimed primary and also acts as an independent node outside the main cluster as it doesn't have the necessary information to connect to it. + +To reconnect the failed node, run the following: + +See nodes.sh + +```console +$ cat /bitnami/valkey/data/nodes.sh +declare -A host_2_ip_array=([valkey-node-0]="192.168.192.6" [valkey-node-1]="192.168.192.2" [valkey-node-2]="192.168.192.4" [valkey-node-3]="192.168.192.5" [valkey-node-4]="192.168.192.3" [valkey-node-5]="192.168.192.7" ) +``` + +Run valkey-cli and run CLUSTER MEET to any other node in the cluster. Now the node has connected to the main cluster. + +```console +$ REDISCLI_AUTH=bitnami valkey-cli +127.0.0.1:6379> cluster meet 192.168.192.7 6379 +OK +``` + +## Parameters + +### Global parameters + +| Name | Description | Value | +| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `global.imageRegistry` | Global Docker image registry | `""` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | +| `global.defaultStorageClass` | Global default StorageClass for Persistent Volume(s) | `""` | +| `global.storageClass` | DEPRECATED: use global.defaultStorageClass instead | `""` | +| `global.valkey.password` | Valkey password (overrides `password`) | `""` | +| `global.security.allowInsecureImages` | Allows skipping image verification | `false` | +| `global.compatibility.openshift.adaptSecurityContext` | Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) | `auto` | + +### Valkey Cluster Common parameters + +| Name | Description | Value | +| ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | +| `nameOverride` | String to partially override common.names.fullname template (will maintain the release name) | `""` | +| `fullnameOverride` | String to fully override common.names.fullname template | `""` | +| `clusterDomain` | Kubernetes Cluster Domain | `cluster.local` | +| `commonAnnotations` | Annotations to add to all deployed objects | `{}` | +| `commonLabels` | Labels to add to all deployed objects | `{}` | +| `extraDeploy` | Array of extra objects to deploy with the release (evaluated as a template) | `[]` | +| `diagnosticMode.enabled` | Enable diagnostic mode (all probes will be disabled and the command will be overridden) | `false` | +| `diagnosticMode.command` | Command to override all containers in the deployment | `["sleep"]` | +| `diagnosticMode.args` | Args to override all containers in the deployment | `["infinity"]` | +| `image.registry` | Valkey cluster image registry | `REGISTRY_NAME` | +| `image.repository` | Valkey cluster image repository | `REPOSITORY_NAME/valkey-cluster` | +| `image.digest` | Valkey cluster image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `image.pullPolicy` | Valkey cluster image pull policy | `IfNotPresent` | +| `image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `image.debug` | Enable image debug mode | `false` | +| `networkPolicy.enabled` | Enable creation of NetworkPolicy resources | `true` | +| `networkPolicy.allowExternal` | The Policy model to apply | `true` | +| `networkPolicy.allowExternalEgress` | Allow the pod to access any range of port and all destinations. | `true` | +| `networkPolicy.extraIngress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `networkPolicy.extraEgress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `networkPolicy.ingressNSMatchLabels` | Labels to match to allow traffic from other namespaces | `{}` | +| `networkPolicy.ingressNSPodMatchLabels` | Pod labels to match to allow traffic from other namespaces | `{}` | +| `serviceAccount.create` | Specifies whether a ServiceAccount should be created | `true` | +| `serviceAccount.name` | The name of the ServiceAccount to create | `""` | +| `serviceAccount.annotations` | Annotations for Cassandra Service Account | `{}` | +| `serviceAccount.automountServiceAccountToken` | Automount API credentials for a service account. | `false` | +| `rbac.create` | Specifies whether RBAC resources should be created | `false` | +| `rbac.role.rules` | Rules to create. It follows the role specification | `[]` | +| `podSecurityContext.enabled` | Enable Valkey pod Security Context | `true` | +| `podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `podSecurityContext.fsGroup` | Group ID for the pods | `1001` | +| `podSecurityContext.sysctls` | Set namespaced sysctls for the pods | `[]` | +| `podDisruptionBudget` | DEPRECATED please use pdb instead | `{}` | +| `pdb.create` | Created a PodDisruptionBudget | `true` | +| `pdb.minAvailable` | Min number of pods that must still be available after the eviction. | `""` | +| `pdb.maxUnavailable` | Max number of pods that can be unavailable after the eviction. | `""` | +| `containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `usePassword` | Use password authentication | `true` | +| `password` | Valkey password (ignored if existingSecret set) | `""` | +| `existingSecret` | Name of existing secret object (for password authentication) | `""` | +| `existingSecretPasswordKey` | Name of key containing password to be retrieved from the existing secret | `""` | +| `usePasswordFiles` | Mount passwords as files instead of environment variables | `true` | +| `tls.enabled` | Enable TLS support for replication traffic | `false` | +| `tls.authClients` | Require clients to authenticate or not | `true` | +| `tls.autoGenerated` | Generate automatically self-signed TLS certificates | `false` | +| `tls.existingSecret` | The name of the existing secret that contains the TLS certificates | `""` | +| `tls.certificatesSecret` | DEPRECATED. Use tls.existingSecret instead | `""` | +| `tls.certFilename` | Certificate filename | `""` | +| `tls.certKeyFilename` | Certificate key filename | `""` | +| `tls.certCAFilename` | CA Certificate filename | `""` | +| `tls.dhParamsFilename` | File containing DH params (in order to support DH based ciphers) | `""` | +| `service.ports.valkey` | Kubernetes Valkey service port | `6379` | +| `service.nodePorts.valkey` | Node port for Valkey | `""` | +| `service.extraPorts` | Extra ports to expose in the service (normally used with the `sidecar` value) | `[]` | +| `service.annotations` | Provide any additional annotations which may be required. | `{}` | +| `service.labels` | Additional labels for valkey service | `{}` | +| `service.type` | Service type for default valkey service | `ClusterIP` | +| `service.clusterIP` | Service Cluster IP | `""` | +| `service.loadBalancerIP` | Load balancer IP if `service.type` is `LoadBalancer` | `""` | +| `service.loadBalancerSourceRanges` | Service Load Balancer sources | `[]` | +| `service.externalTrafficPolicy` | Service external traffic policy | `Cluster` | +| `service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` | +| `service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `service.headless.annotations` | Annotations for the headless service. | `{}` | +| `persistence.enabled` | Enable persistence on Valkey | `true` | +| `persistence.path` | Path to mount the volume at, to use other images Valkey images. | `/bitnami/valkey/data` | +| `persistence.subPath` | The subdirectory of the volume to mount to, useful in dev environments and one PV for multiple services | `""` | +| `persistence.storageClass` | Storage class of backing PVC | `""` | +| `persistence.annotations` | Persistent Volume Claim annotations | `{}` | +| `persistence.labels` | Persistent Volume Claim labels | `{}` | +| `persistence.accessModes` | Persistent Volume Access Modes | `["ReadWriteOnce"]` | +| `persistence.size` | Size of data volume | `8Gi` | +| `persistence.matchLabels` | Persistent Volume selectors | `{}` | +| `persistence.matchExpressions` | matchExpressions Persistent Volume selectors | `{}` | +| `persistentVolumeClaimRetentionPolicy.enabled` | Controls if and how PVCs are deleted during the lifecycle of a StatefulSet | `false` | +| `persistentVolumeClaimRetentionPolicy.whenScaled` | Volume retention behavior when the replica count of the StatefulSet is reduced | `Retain` | +| `persistentVolumeClaimRetentionPolicy.whenDeleted` | Volume retention behavior that applies when the StatefulSet is deleted | `Retain` | +| `volumePermissions.enabled` | Enable init container that changes volume permissions in the registry (for cases where the default k8s `runAsUser` and `fsUser` values do not work) | `false` | +| `volumePermissions.image.registry` | Init container volume-permissions image registry | `REGISTRY_NAME` | +| `volumePermissions.image.repository` | Init container volume-permissions image repository | `REPOSITORY_NAME/os-shell` | +| `volumePermissions.image.digest` | Init container volume-permissions image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `volumePermissions.image.pullPolicy` | Init container volume-permissions image pull policy | `IfNotPresent` | +| `volumePermissions.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `volumePermissions.containerSecurityContext.enabled` | Enable Containers' Security Context | `true` | +| `volumePermissions.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `volumePermissions.containerSecurityContext.runAsUser` | User ID for the containers. | `0` | +| `volumePermissions.containerSecurityContext.privileged` | Run container as privileged | `false` | +| `volumePermissions.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if volumePermissions.resources is set (volumePermissions.resources is recommended for production). | `nano` | +| `volumePermissions.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | + +### Valkey statefulset parameters + +| Name | Description | Value | +| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | +| `valkey.command` | Valkey entrypoint string. The command `valkey-server` is executed if this is not provided | `[]` | +| `valkey.args` | Arguments for the provided command if needed | `[]` | +| `valkey.updateStrategy.type` | Argo Workflows statefulset strategy type | `RollingUpdate` | +| `valkey.updateStrategy.rollingUpdate.partition` | Partition update strategy | `0` | +| `valkey.podManagementPolicy` | Statefulset Pod management policy, it needs to be Parallel to be able to complete the cluster join | `Parallel` | +| `valkey.automountServiceAccountToken` | Mount Service Account token in pod | `false` | +| `valkey.hostAliases` | Deployment pod host aliases | `[]` | +| `valkey.hostNetwork` | Host networking requested for this pod. Use the host's network namespace. | `false` | +| `valkey.useAOFPersistence` | Whether to use AOF Persistence mode or not | `yes` | +| `valkey.containerPorts.valkey` | Valkey port | `6379` | +| `valkey.containerPorts.bus` | The busPort should be obtained adding 10000 to the valkeyPort. By default: 10000 + 6379 = 16379 | `16379` | +| `valkey.lifecycleHooks` | LifecycleHook to set additional configuration before or after startup. Evaluated as a template | `{}` | +| `valkey.extraVolumes` | Extra volumes to add to the deployment | `[]` | +| `valkey.extraVolumeMounts` | Extra volume mounts to add to the container | `[]` | +| `valkey.customLivenessProbe` | Override default liveness probe | `{}` | +| `valkey.customReadinessProbe` | Override default readiness probe | `{}` | +| `valkey.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `valkey.initContainers` | Extra init containers to add to the deployment | `[]` | +| `valkey.sidecars` | Extra sidecar containers to add to the deployment | `[]` | +| `valkey.podLabels` | Additional labels for Valkey pod | `{}` | +| `valkey.priorityClassName` | Valkey Primary pod priorityClassName | `""` | +| `valkey.defaultConfigOverride` | Optional default Valkey configuration for the nodes | `""` | +| `valkey.configmap` | Additional Valkey configuration for the nodes | `""` | +| `valkey.extraEnvVars` | An array to add extra environment variables | `[]` | +| `valkey.extraEnvVarsCM` | ConfigMap with extra environment variables | `""` | +| `valkey.extraEnvVarsSecret` | Secret with extra environment variables | `""` | +| `valkey.podAnnotations` | Valkey additional annotations | `{}` | +| `valkey.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if valkey.resources is set (valkey.resources is recommended for production). | `nano` | +| `valkey.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `valkey.schedulerName` | Use an alternate scheduler, e.g. "stork". | `""` | +| `valkey.shareProcessNamespace` | Enable shared process namespace in a pod. | `false` | +| `valkey.livenessProbe.enabled` | Enable livenessProbe | `true` | +| `valkey.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `5` | +| `valkey.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `5` | +| `valkey.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `valkey.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `5` | +| `valkey.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `valkey.readinessProbe.enabled` | Enable readinessProbe | `true` | +| `valkey.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `valkey.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `5` | +| `valkey.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `1` | +| `valkey.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `5` | +| `valkey.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `valkey.startupProbe.enabled` | Enable startupProbe | `false` | +| `valkey.startupProbe.path` | Path to check for startupProbe | `/` | +| `valkey.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `300` | +| `valkey.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `valkey.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `valkey.startupProbe.failureThreshold` | Failure threshold for startupProbe | `6` | +| `valkey.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `valkey.podAffinityPreset` | Valkey pod affinity preset. Ignored if `valkey.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `valkey.podAntiAffinityPreset` | Valkey pod anti-affinity preset. Ignored if `valkey.affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `valkey.nodeAffinityPreset.type` | Valkey node affinity preset type. Ignored if `valkey.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `valkey.nodeAffinityPreset.key` | Valkey node label key to match Ignored if `valkey.affinity` is set. | `""` | +| `valkey.nodeAffinityPreset.values` | Valkey node label values to match. Ignored if `valkey.affinity` is set. | `[]` | +| `valkey.affinity` | Affinity settings for Valkey pod assignment | `{}` | +| `valkey.nodeSelector` | Node labels for Valkey pods assignment | `{}` | +| `valkey.tolerations` | Tolerations for Valkey pods assignment | `[]` | +| `valkey.topologySpreadConstraints` | Pod topology spread constraints for Valkey pod | `[]` | + +### Cluster update job parameters + +| Name | Description | Value | +| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | +| `updateJob.activeDeadlineSeconds` | Number of seconds the Job to create the cluster will be waiting for the Nodes to be ready. | `600` | +| `updateJob.command` | Container command (using container default if not set) | `[]` | +| `updateJob.args` | Container args (using container default if not set) | `[]` | +| `updateJob.automountServiceAccountToken` | Mount Service Account token in pod | `false` | +| `updateJob.hostAliases` | Deployment pod host aliases | `[]` | +| `updateJob.helmHook` | Job Helm hook | `post-upgrade` | +| `updateJob.annotations` | Job annotations | `{}` | +| `updateJob.podAnnotations` | Job pod annotations | `{}` | +| `updateJob.podLabels` | Pod extra labels | `{}` | +| `updateJob.extraEnvVars` | An array to add extra environment variables | `[]` | +| `updateJob.extraEnvVarsCM` | ConfigMap containing extra environment variables | `""` | +| `updateJob.extraEnvVarsSecret` | Secret containing extra environment variables | `""` | +| `updateJob.extraVolumes` | Extra volumes to add to the deployment | `[]` | +| `updateJob.extraVolumeMounts` | Extra volume mounts to add to the container | `[]` | +| `updateJob.initContainers` | Extra init containers to add to the deployment | `[]` | +| `updateJob.podAffinityPreset` | Update job pod affinity preset. Ignored if `updateJob.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `updateJob.podAntiAffinityPreset` | Update job pod anti-affinity preset. Ignored if `updateJob.affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `updateJob.nodeAffinityPreset.type` | Update job node affinity preset type. Ignored if `updateJob.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `updateJob.nodeAffinityPreset.key` | Update job node label key to match Ignored if `updateJob.affinity` is set. | `""` | +| `updateJob.nodeAffinityPreset.values` | Update job node label values to match. Ignored if `updateJob.affinity` is set. | `[]` | +| `updateJob.affinity` | Affinity for update job pods assignment | `{}` | +| `updateJob.nodeSelector` | Node labels for update job pods assignment | `{}` | +| `updateJob.tolerations` | Tolerations for update job pods assignment | `[]` | +| `updateJob.priorityClassName` | Priority class name | `""` | +| `updateJob.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if updateJob.resources is set (updateJob.resources is recommended for production). | `nano` | +| `updateJob.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | + +### Cluster management parameters + +| Name | Description | Value | +| --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | -------------- | +| `cluster.init` | Enable the initialization of the Valkey Cluster | `true` | +| `cluster.nodes` | The number of primary nodes should always be >= 3, otherwise cluster creation will fail | `6` | +| `cluster.replicas` | Number of replicas for every primary in the cluster | `1` | +| `cluster.externalAccess.enabled` | Enable access to the Valkey | `false` | +| `cluster.externalAccess.hostMode` | Set cluster preferred endpoint type as hostname | `false` | +| `cluster.externalAccess.service.disableLoadBalancerIP` | Disable use of `Service.spec.loadBalancerIP` | `false` | +| `cluster.externalAccess.service.loadBalancerIPAnnotaion` | Name of annotation to specify fixed IP for service in. Disables `Service.spec.loadBalancerIP` if not empty | `""` | +| `cluster.externalAccess.service.type` | Type for the services used to expose every Pod | `LoadBalancer` | +| `cluster.externalAccess.service.port` | Port for the services used to expose every Pod | `6379` | +| `cluster.externalAccess.service.loadBalancerIP` | Array of load balancer IPs for each Valkey node. Length must be the same as cluster.nodes | `[]` | +| `cluster.externalAccess.service.loadBalancerSourceRanges` | Service Load Balancer sources | `[]` | +| `cluster.externalAccess.service.annotations` | Annotations to add to the services used to expose every Pod of the Valkey Cluster | `{}` | +| `cluster.update.addNodes` | Boolean to specify if you want to add nodes after the upgrade | `false` | +| `cluster.update.currentNumberOfNodes` | Number of currently deployed Valkey nodes | `6` | +| `cluster.update.currentNumberOfReplicas` | Number of currently deployed Valkey replicas | `1` | +| `cluster.update.newExternalIPs` | External IPs obtained from the services for the new nodes to add to the cluster | `[]` | + +### Metrics sidecar parameters + +| Name | Description | Value | +| ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | +| `metrics.enabled` | Start a side-car prometheus exporter | `false` | +| `metrics.image.registry` | Valkey exporter image registry | `REGISTRY_NAME` | +| `metrics.image.repository` | Valkey exporter image name | `REPOSITORY_NAME/redis-exporter` | +| `metrics.image.digest` | Valkey exporter image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `metrics.image.pullPolicy` | Valkey exporter image pull policy | `IfNotPresent` | +| `metrics.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `metrics.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if metrics.resources is set (metrics.resources is recommended for production). | `nano` | +| `metrics.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `metrics.extraArgs` | Extra arguments for the binary; possible values [here](https://github.com/oliver006/redis_exporter) | `{}` | +| `metrics.extraEnvVars` | Array with extra environment variables to add to Valkey exporter | `[]` | +| `metrics.containerPorts.http` | Metrics HTTP container port | `9121` | +| `metrics.podAnnotations` | Additional annotations for Metrics exporter pod | `{}` | +| `metrics.podLabels` | Additional labels for Metrics exporter pod | `{}` | +| `metrics.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `metrics.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `metrics.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `metrics.containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `metrics.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `metrics.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `metrics.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `metrics.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `metrics.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `metrics.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `metrics.serviceMonitor.enabled` | If `true`, creates a Prometheus Operator ServiceMonitor (also requires `metrics.enabled` to be `true`) | `false` | +| `metrics.serviceMonitor.namespace` | Optional namespace which Prometheus is running in | `""` | +| `metrics.serviceMonitor.interval` | How frequently to scrape metrics (use by default, falling back to Prometheus' default) | `""` | +| `metrics.serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended | `""` | +| `metrics.serviceMonitor.selector` | Prometheus instance selector labels | `{}` | +| `metrics.serviceMonitor.labels` | ServiceMonitor extra labels | `{}` | +| `metrics.serviceMonitor.annotations` | ServiceMonitor annotations | `{}` | +| `metrics.serviceMonitor.jobLabel` | The name of the label on the target service to use as the job name in prometheus. | `""` | +| `metrics.serviceMonitor.relabelings` | RelabelConfigs to apply to samples before scraping | `[]` | +| `metrics.serviceMonitor.metricRelabelings` | MetricRelabelConfigs to apply to samples before ingestion | `[]` | +| `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 | `""` | +| `metrics.prometheusRule.rules` | Create specified [rules](https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/), check values for an example. | `[]` | +| `metrics.priorityClassName` | Metrics exporter pod priorityClassName | `""` | +| `metrics.service.type` | Kubernetes Service type (valkey metrics) | `ClusterIP` | +| `metrics.service.loadBalancerIP` | Use serviceLoadBalancerIP to request a specific static IP, otherwise leave blank | `""` | +| `metrics.service.annotations` | Annotations for the services to monitor. | `{}` | +| `metrics.service.labels` | Additional labels for the metrics service | `{}` | +| `metrics.service.ports.http` | Metrics HTTP service port | `9121` | +| `metrics.service.clusterIP` | Service Cluster IP | `""` | + +### Sysctl Image parameters + +| Name | Description | Value | +| ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | +| `sysctlImage.enabled` | Enable an init container to modify Kernel settings | `false` | +| `sysctlImage.command` | sysctlImage command to execute | `[]` | +| `sysctlImage.registry` | sysctlImage Init container registry | `REGISTRY_NAME` | +| `sysctlImage.repository` | sysctlImage Init container repository | `REPOSITORY_NAME/os-shell` | +| `sysctlImage.digest` | sysctlImage Init container digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `sysctlImage.pullPolicy` | sysctlImage Init container pull policy | `IfNotPresent` | +| `sysctlImage.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `sysctlImage.mountHostSys` | Mount the host `/sys` folder to `/host-sys` | `false` | +| `sysctlImage.containerSecurityContext.enabled` | Enable Containers' Security Context | `true` | +| `sysctlImage.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `sysctlImage.containerSecurityContext.runAsUser` | User ID for the containers. | `0` | +| `sysctlImage.containerSecurityContext.privileged` | Run privileged as privileged | `true` | +| `sysctlImage.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if sysctlImage.resources is set (sysctlImage.resources is recommended for production). | `nano` | +| `sysctlImage.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +helm install my-release \ + --set password=secretpassword \ + oci://REGISTRY_NAME/REPOSITORY_NAME/valkey-cluster +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The above command sets the Valkey server password to `secretpassword`. + +> NOTE: Once this chart is deployed, it is not possible to change the application's access credentials, such as usernames or passwords, using Helm. To change these application credentials after deployment, delete any persistent volumes (PVs) used by the chart and re-deploy it, or use the application's built-in administrative tools if available. + +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 oci://REGISTRY_NAME/REPOSITORY_NAME/valkey-cluster +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> **Tip**: You can use the default [values.yaml](https://github.com/bitnami/charts/tree/main/bitnami/valkey-cluster/values.yaml) +> **Note for minikube users**: Current versions of minikube (v0.24.1 at the time of writing) provision `hostPath` persistent volumes that are only writable by root. Using chart defaults cause pod failure for the Valkey pod as it attempts to write to the `/bitnami` directory. See minikube issue [1990](https://github.com/kubernetes/minikube/issues/1990) for more information. + +## Troubleshooting + +Find more information about how to deal with common errors related to Bitnami's Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues). + +## Upgrading + +### To 2.1.0 + +This version introduces image verification for security purposes. To disable it, set `global.security.allowInsecureImages` to `true`. More details at [GitHub issue](https://github.com/bitnami/charts/issues/30850). + +### To 2.0.0 + +This major updates all the references from `master/slave` to `primary/replica` to follow the upstream project strategy: + +- The term *master* has been replaced by the term *primary*. Therefore, parameters prefixed with `master` are now prefixed with `primary`. +- Environment variables previously prefixed as `VALKEY_MASTER` or `VALKEY_SENTINEL_MASTER` use `VALKEY_PRIMARY` and `VALKEY_SENTINEL_PRIMARY` now. + +Consequences: + +Backwards compatibility is not guaranteed. To upgrade to `2.0.0`, install a new release of the Valkey chart, and migrate the data from your previous release. You have to create a backup of the database, and restore it on the new release as explained in the [Backup and restore](#backup-and-restore) section. + +## License + +Copyright © 2025 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/.helmignore b/backing-services/gitea/charts/valkey-cluster/charts/common/.helmignore new file mode 100644 index 0000000..d0e1084 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/.helmignore @@ -0,0 +1,26 @@ +# 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 +.vscode/ +# img folder +img/ +# Changelog +CHANGELOG.md diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/Chart.yaml b/backing-services/gitea/charts/valkey-cluster/charts/common/Chart.yaml new file mode 100644 index 0000000..fb04f76 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/Chart.yaml @@ -0,0 +1,23 @@ +annotations: + category: Infrastructure + licenses: Apache-2.0 +apiVersion: v2 +appVersion: 2.31.4 +description: A Library Helm Chart for grouping common logic between bitnami charts. + This chart is not deployable by itself. +home: https://bitnami.com +icon: https://dyltqmyl993wv.cloudfront.net/downloads/logos/bitnami-mark.png +keywords: +- common +- helper +- template +- function +- bitnami +maintainers: +- name: Broadcom, Inc. All Rights Reserved. + url: https://github.com/bitnami/charts +name: common +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/common +type: library +version: 2.31.4 diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/README.md b/backing-services/gitea/charts/valkey-cluster/charts/common/README.md new file mode 100644 index 0000000..71368aa --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/README.md @@ -0,0 +1,387 @@ +# Bitnami Common Library Chart + +A [Helm Library Chart](https://helm.sh/docs/topics/library_charts/#helm) for grouping common logic between Bitnami charts. + +## TL;DR + +```yaml +dependencies: + - name: common + version: 2.x.x + repository: oci://registry-1.docker.io/bitnamicharts +``` + +```console +helm dependency update +``` + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "common.names.fullname" . }} +data: + myvalue: "Hello World" +``` + +Looking to use our applications in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the commercial edition of the Bitnami catalog. + +## ⚠️ Important Notice: Upcoming changes to the Bitnami Catalog + +Beginning August 28th, 2025, Bitnami will evolve its public catalog to offer a curated set of hardened, security-focused images under the new [Bitnami Secure Images initiative](https://news.broadcom.com/app-dev/broadcom-introduces-bitnami-secure-images-for-production-ready-containerized-applications). As part of this transition: + +- Granting community users access for the first time to security-optimized versions of popular container images. +- Bitnami will begin deprecating support for non-hardened, Debian-based software images in its free tier and will gradually remove non-latest tags from the public catalog. As a result, community users will have access to a reduced number of hardened images. These images are published only under the “latest” tag and are intended for development purposes +- Starting August 28th, over two weeks, all existing container images, including older or versioned tags (e.g., 2.50.0, 10.6), will be migrated from the public catalog (docker.io/bitnami) to the “Bitnami Legacy” repository (docker.io/bitnamilegacy), where they will no longer receive updates. +- For production workloads and long-term support, users are encouraged to adopt Bitnami Secure Images, which include hardened containers, smaller attack surfaces, CVE transparency (via VEX/KEV), SBOMs, and enterprise support. + +These changes aim to improve the security posture of all Bitnami users by promoting best practices for software supply chain integrity and up-to-date deployments. For more details, visit the [Bitnami Secure Images announcement](https://github.com/bitnami/containers/issues/83267). + +## Introduction + +This chart provides a common template helpers which can be used to develop new charts using [Helm](https://helm.sh) package manager. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ + +## Parameters + +The following table lists the helpers available in the library which are scoped in different sections. + +### Affinities + +| Helper identifier | Description | Expected Input | +| ------------------------------- | ---------------------------------------------------- | ------------------------------------------------------------ | +| `common.affinities.nodes.soft` | Return a soft nodeAffinity definition | `dict "key" "FOO" "values" (list "BAR" "BAZ")` | +| `common.affinities.nodes.hard` | Return a hard nodeAffinity definition | `dict "key" "FOO" "values" (list "BAR" "BAZ")` | +| `common.affinities.nodes` | Return a nodeAffinity definition | `dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")` | +| `common.affinities.topologyKey` | Return a topologyKey definition | `dict "topologyKey" "FOO"` | +| `common.affinities.pods.soft` | Return a soft podAffinity/podAntiAffinity definition | `dict "component" "FOO" "context" $` | +| `common.affinities.pods.hard` | Return a hard podAffinity/podAntiAffinity definition | `dict "component" "FOO" "context" $` | +| `common.affinities.pods` | Return a podAffinity/podAntiAffinity definition | `dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")` | + +### Capabilities + +| Helper identifier | Description | Expected Input | +| --------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------- | +| `common.capabilities.kubeVersion` | Return the target Kubernetes version (using client default if .Values.kubeVersion is not set). | `.` Chart context | +| `common.capabilities.apiVersions.has` | Return true if the apiVersion is supported | `dict "version" "batch/v1" "context" $` | +| `common.capabilities.job.apiVersion` | Return the appropriate apiVersion for job. | `.` Chart context | +| `common.capabilities.cronjob.apiVersion` | Return the appropriate apiVersion for cronjob. | `.` Chart context | +| `common.capabilities.daemonset.apiVersion` | Return the appropriate apiVersion for daemonset. | `.` Chart context | +| `common.capabilities.deployment.apiVersion` | Return the appropriate apiVersion for deployment. | `.` Chart context | +| `common.capabilities.statefulset.apiVersion` | Return the appropriate apiVersion for statefulset. | `.` Chart context | +| `common.capabilities.ingress.apiVersion` | Return the appropriate apiVersion for ingress. | `.` Chart context | +| `common.capabilities.rbac.apiVersion` | Return the appropriate apiVersion for RBAC resources. | `.` Chart context | +| `common.capabilities.crd.apiVersion` | Return the appropriate apiVersion for CRDs. | `.` Chart context | +| `common.capabilities.policy.apiVersion` | Return the appropriate apiVersion for podsecuritypolicy. | `.` Chart context | +| `common.capabilities.networkPolicy.apiVersion` | Return the appropriate apiVersion for networkpolicy. | `.` Chart context | +| `common.capabilities.apiService.apiVersion` | Return the appropriate apiVersion for APIService. | `.` Chart context | +| `common.capabilities.hpa.apiVersion` | Return the appropriate apiVersion for Horizontal Pod Autoscaler | `.` Chart context | +| `common.capabilities.vpa.apiVersion` | Return the appropriate apiVersion for Vertical Pod Autoscaler. | `.` Chart context | +| `common.capabilities.psp.supported` | Returns true if PodSecurityPolicy is supported | `.` Chart context | +| `common.capabilities.supportsHelmVersion` | Returns true if the used Helm version is 3.3+ | `.` Chart context | +| `common.capabilities.admissionConfiguration.supported` | Returns true if AdmissionConfiguration is supported | `.` Chart context | +| `common.capabilities.admissionConfiguration.apiVersion` | Return the appropriate apiVersion for AdmissionConfiguration. | `.` Chart context | +| `common.capabilities.podSecurityConfiguration.apiVersion` | Return the appropriate apiVersion for PodSecurityConfiguration. | `.` Chart context | + +### Compatibility + +| Helper identifier | Description | Expected Input | +| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | +| `common.compatibility.isOpenshift` | Return true if the detected platform is Openshift | `.` Chart context | +| `common.compatibility.renderSecurityContext` | Render a compatible securityContext depending on the platform. By default it is maintained as it is. In other platforms like Openshift we remove default user/group values that do not work out of the box with the restricted-v1 SCC | `dict "secContext" .Values.containerSecurityContext "context" $` | + +### Errors + +| Helper identifier | Description | Expected Input | +| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | +| `common.errors.upgrade.passwords.empty` | It will ensure required passwords are given when we are upgrading a chart. If `validationErrors` is not empty it will throw an error and will stop the upgrade action. | `dict "validationErrors" (list $validationError00 $validationError01) "context" $` | +| `common.errors.insecureImages` | Throw error when original container images are replaced. The error can be bypassed by setting the `global.security.allowInsecureImages` to true. | `dict "images" (list .Values.path.to.the.imageRoot) "context" $` | + +### Images + +| Helper identifier | Description | Expected Input | +| --------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | +| `common.images.image` | Return the proper and full image name | `dict "imageRoot" .Values.path.to.the.image "global" $`, see [ImageRoot](#imageroot) for the structure. | +| `common.images.pullSecrets` | Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead) | `dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global` | +| `common.images.renderPullSecrets` | Return the proper Docker Image Registry Secret Names (evaluates values as templates) | `dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $` | +| `common.images.version` | Return the proper image version | `dict "imageRoot" .Values.path.to.the.image "chart" .Chart` , see [ImageRoot](#imageroot) for the structure. | + +### Ingress + +| Helper identifier | Description | Expected Input | +| ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `common.ingress.backend` | Generate a proper Ingress backend entry depending on the API version | `dict "serviceName" "foo" "servicePort" "bar"`, see the [Ingress deprecation notice](https://kubernetes.io/blog/2019/07/18/api-deprecations-in-1-16/) for the syntax differences | +| `common.ingress.certManagerRequest` | Prints "true" if required cert-manager annotations for TLS signed certificates are set in the Ingress annotations | `dict "annotations" .Values.path.to.the.ingress.annotations` | + +### Labels + +| Helper identifier | Description | Expected Input | +| --------------------------- | --------------------------------------------------------------------------- | ----------------- | +| `common.labels.standard` | Return Kubernetes standard labels | `.` Chart context | +| `common.labels.matchLabels` | Labels to use on `deploy.spec.selector.matchLabels` and `svc.spec.selector` | `.` Chart context | + +### Names + +| Helper identifier | Description | Expected Input | +| ---------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | +| `common.names.name` | Expand the name of the chart or use `.Values.nameOverride` | `.` Chart context | +| `common.names.fullname` | Create a default fully qualified app name. | `.` Chart context | +| `common.names.namespace` | Allow the release namespace to be overridden | `.` Chart context | +| `common.names.fullname.namespace` | Create a fully qualified app name adding the installation's namespace | `.` Chart context | +| `common.names.chart` | Chart name plus version | `.` Chart context | +| `common.names.dependency.fullname` | Create a default fully qualified dependency name. | `dict "chartName" "dependency-chart-name" "chartValues" .Values.dependency-chart "context" $` | + +### Resources + +| Helper identifier | Description | Expected Input | +| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | +| `common.resources.preset` | Return a resource request/limit object based on a given preset. These presets are for basic testing and not meant to be used in production. | `dict "type" "nano"` | + +### Secrets + +| Helper identifier | Description | Expected Input | +| --------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `common.secrets.name` | Generate the name of the secret. | `dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $` see [ExistingSecret](#existingsecret) for the structure. | +| `common.secrets.key` | Generate secret key. | `dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName"` see [ExistingSecret](#existingsecret) for the structure. | +| `common.secrets.passwords.manage` | Generate secret password or retrieve one if already created. | `dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "honorProvidedValues" false "context" $`, length, strong, honorProvidedValues and chartName fields are optional. | +| `common.secrets.exists` | Returns whether a previous generated secret already exists. | `dict "secret" "secret-name" "context" $` | +| `common.secrets.lookup` | Reuses the value from an existing secret, otherwise sets its value to a default value. | `dict "secret" "secret-name" "key" "keyName" "defaultValue" .Values.myValue "context" $` | + +### Storage + +| Helper identifier | Description | Expected Input | +| ---------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------- | +| `common.storage.class` | Return the proper Storage Class | `dict "persistence" .Values.path.to.the.persistence "global" $`, see [Persistence](#persistence) for the structure. | + +### TplValues + +| Helper identifier | Description | Expected Input | +| ---------------------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `common.tplvalues.render` | Renders a value that contains template | `dict "value" .Values.path.to.the.Value "context" $`, value is the value should rendered as template, context frequently is the chart context `$` or `.` | +| `common.tplvalues.merge` | Merge a list of values that contains template after rendering them. | `dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $` | +| `common.tplvalues.merge-overwrite` | Merge a list of values that contains template after rendering them. | `dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $` | + +### Utils + +| Helper identifier | Description | Expected Input | +| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | +| `common.utils.fieldToEnvVar` | Build environment variable name given a field. | `dict "field" "my-password"` | +| `common.utils.secret.getvalue` | Print instructions to get a secret value. | `dict "secret" "secret-name" "field" "secret-value-field" "context" $` | +| `common.utils.getValueFromKey` | Gets a value from `.Values` object given its key path | `dict "key" "path.to.key" "context" $` | +| `common.utils.getKeyFromList` | Returns first `.Values` key with a defined value or first of the list if all non-defined | `dict "keys" (list "path.to.key1" "path.to.key2") "context" $` | +| `common.utils.checksumTemplate` | Checksum a template at "path" containing a *single* resource (ConfigMap,Secret) for use in pod annotations, excluding the metadata (see #18376) | `dict "path" "/configmap.yaml" "context" $` | + +### Validations + +| Helper identifier | Description | Expected Input | +| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `common.validations.values.single.empty` | Validate a value must not be empty. | `dict "valueKey" "path.to.value" "secret" "secret.name" "field" "my-password" "subchart" "subchart" "context" $` secret, field and subchart are optional. In case they are given, the helper will generate a how to get instruction. See [ValidateValue](#validatevalue) | +| `common.validations.values.multiple.empty` | Validate a multiple values must not be empty. It returns a shared error for all the values. | `dict "required" (list $validateValueConf00 $validateValueConf01) "context" $`. See [ValidateValue](#validatevalue) | +| `common.validations.values.mariadb.passwords` | This helper will ensure required password for MariaDB are not empty. It returns a shared error for all the values. | `dict "secret" "mariadb-secret" "subchart" "true" "context" $` subchart field is optional and could be true or false it depends on where you will use mariadb chart and the helper. | + +### Warnings + +| Helper identifier | Description | Expected Input | +| -------------------------------- | ----------------------------------------------------------------- | ---------------------------------------------------------- | +| `common.warnings.rollingTag` | Warning about using rolling tag. | `ImageRoot` see [ImageRoot](#imageroot) for the structure. | +| `common.warnings.modifiedImages` | Warning about replaced images from the original. | `ImageRoot` see [ImageRoot](#imageroot) for the structure. | +| `common.warnings.resources` | Warning about not setting the resource object in all deployments. | `dict "sections" (list "path1" "path2") context $` | + +## Special input schemas + +### ImageRoot + +```yaml +registry: + type: string + description: Docker registry where the image is located + example: docker.io + +repository: + type: string + description: Repository and image name + example: bitnami/nginx + +tag: + type: string + description: image tag + example: 1.16.1-debian-10-r63 + +pullPolicy: + type: string + description: Specify a imagePullPolicy.' + +pullSecrets: + type: array + items: + type: string + description: Optionally specify an array of imagePullSecrets (evaluated as templates). + +debug: + type: boolean + description: Set to true if you would like to see extra information on logs + example: false + +## An instance would be: +# registry: docker.io +# repository: bitnami/nginx +# tag: 1.16.1-debian-10-r63 +# pullPolicy: IfNotPresent +# debug: false +``` + +### Persistence + +```yaml +enabled: + type: boolean + description: Whether enable persistence. + example: true + +storageClass: + type: string + description: Ghost data Persistent Volume Storage Class, If set to "-", storageClassName: "" which disables dynamic provisioning. + example: "-" + +accessMode: + type: string + description: Access mode for the Persistent Volume Storage. + example: ReadWriteOnce + +size: + type: string + description: Size the Persistent Volume Storage. + example: 8Gi + +path: + type: string + description: Path to be persisted. + example: /bitnami + +## An instance would be: +# enabled: true +# storageClass: "-" +# accessMode: ReadWriteOnce +# size: 8Gi +# path: /bitnami +``` + +### ExistingSecret + +```yaml +name: + type: string + description: Name of the existing secret. + example: mySecret +keyMapping: + description: Mapping between the expected key name and the name of the key in the existing secret. + type: object + +## An instance would be: +# name: mySecret +# keyMapping: +# password: myPasswordKey +``` + +#### Example of use + +When we store sensitive data for a deployment in a secret, some times we want to give to users the possibility of using theirs existing secrets. + +```yaml +# templates/secret.yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }} + labels: + app: {{ include "common.names.fullname" . }} +type: Opaque +data: + password: {{ .Values.password | b64enc | quote }} + +# templates/dpl.yaml +--- +... + env: + - name: PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "common.secrets.name" (dict "existingSecret" .Values.existingSecret "context" $) }} + key: {{ include "common.secrets.key" (dict "existingSecret" .Values.existingSecret "key" "password") }} +... + +# values.yaml +--- +name: mySecret +keyMapping: + password: myPasswordKey +``` + +### ValidateValue + +#### NOTES.txt + +```console +{{- $validateValueConf00 := (dict "valueKey" "path.to.value00" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value01" "secret" "secretName" "field" "password-01") -}} + +{{ include "common.validations.values.multiple.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} +``` + +If we force those values to be empty we will see some alerts + +```console +helm install test mychart --set path.to.value00="",path.to.value01="" + 'path.to.value00' must not be empty, please add '--set path.to.value00=$PASSWORD_00' to the command. To get the current value: + + export PASSWORD_00=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-00}" | base64 -d) + + 'path.to.value01' must not be empty, please add '--set path.to.value01=$PASSWORD_01' to the command. To get the current value: + + export PASSWORD_01=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-01}" | base64 -d) +``` + +## Upgrading + +### To 1.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +#### What changes were introduced in this major version? + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- Use `type: library`. [Here](https://v3.helm.sh/docs/faq/#library-chart-support) you can find more information. +- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts + +#### Considerations when upgrading to this version + +- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues +- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore +- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 + +#### Useful links + +- +- +- + +## License + +Copyright © 2025 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_affinities.tpl b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_affinities.tpl new file mode 100644 index 0000000..c6ccc62 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_affinities.tpl @@ -0,0 +1,169 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a soft nodeAffinity definition +{{ include "common.affinities.nodes.soft" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.soft" -}} +preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} + weight: 1 +{{- end -}} + +{{/* +Return a hard nodeAffinity definition +{{ include "common.affinities.nodes.hard" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.hard" -}} +requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} +{{- end -}} + +{{/* +Return a nodeAffinity definition +{{ include "common.affinities.nodes" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.nodes.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.nodes.hard" . -}} + {{- end -}} +{{- end -}} + +{{/* +Return a topologyKey definition +{{ include "common.affinities.topologyKey" (dict "topologyKey" "BAR") -}} +*/}} +{{- define "common.affinities.topologyKey" -}} +{{ .topologyKey | default "kubernetes.io/hostname" -}} +{{- end -}} + +{{/* +Return a soft podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.soft" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "extraNamespaces" (list "namespace1" "namespace2") "context" $) -}} +*/}} +{{- define "common.affinities.pods.soft" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +{{- $extraNamespaces := default (list) .extraNamespaces -}} +preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if $extraNamespaces }} + namespaces: + - {{ .context.Release.Namespace }} + {{- with $extraNamespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: 1 + {{- range $extraPodAffinityTerms }} + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if .namespaces }} + namespaces: + - {{ $.context.Release.Namespace }} + {{- with .namespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: {{ .weight | default 1 -}} + {{- end -}} +{{- end -}} + +{{/* +Return a hard podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.hard" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "extraNamespaces" (list "namespace1" "namespace2") "context" $) -}} +*/}} +{{- define "common.affinities.pods.hard" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +{{- $extraNamespaces := default (list) .extraNamespaces -}} +requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if $extraNamespaces }} + namespaces: + - {{ .context.Release.Namespace }} + {{- with $extraNamespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 6 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- range $extraPodAffinityTerms }} + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if .namespaces }} + namespaces: + - {{ $.context.Release.Namespace }} + {{- with .namespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 6 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- end -}} +{{- end -}} + +{{/* +Return a podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.pods" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.pods.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.pods.hard" . -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_capabilities.tpl b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_capabilities.tpl new file mode 100644 index 0000000..58f58c1 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_capabilities.tpl @@ -0,0 +1,178 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the target Kubernetes version +*/}} +{{- define "common.capabilities.kubeVersion" -}} +{{- default (default .Capabilities.KubeVersion.Version .Values.kubeVersion) ((.Values.global).kubeVersion) -}} +{{- end -}} + +{{/* +Return true if the apiVersion is supported +Usage: +{{ include "common.capabilities.apiVersions.has" (dict "version" "batch/v1" "context" $) }} +*/}} +{{- define "common.capabilities.apiVersions.has" -}} +{{- $providedAPIVersions := default .context.Values.apiVersions ((.context.Values.global).apiVersions) -}} +{{- if and (empty $providedAPIVersions) (.context.Capabilities.APIVersions.Has .version) -}} + {{- true -}} +{{- else if has .version $providedAPIVersions -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for poddisruptionbudget. +*/}} +{{- define "common.capabilities.policy.apiVersion" -}} +{{- print "policy/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "common.capabilities.networkPolicy.apiVersion" -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for job. +*/}} +{{- define "common.capabilities.job.apiVersion" -}} +{{- print "batch/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for cronjob. +*/}} +{{- define "common.capabilities.cronjob.apiVersion" -}} +{{- print "batch/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for daemonset. +*/}} +{{- define "common.capabilities.daemonset.apiVersion" -}} +{{- print "apps/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for deployment. +*/}} +{{- define "common.capabilities.deployment.apiVersion" -}} +{{- print "apps/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for statefulset. +*/}} +{{- define "common.capabilities.statefulset.apiVersion" -}} +{{- print "apps/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "common.capabilities.ingress.apiVersion" -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for RBAC resources. +*/}} +{{- define "common.capabilities.rbac.apiVersion" -}} +{{- print "rbac.authorization.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for CRDs. +*/}} +{{- define "common.capabilities.crd.apiVersion" -}} +{{- print "apiextensions.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for APIService. +*/}} +{{- define "common.capabilities.apiService.apiVersion" -}} +{{- print "apiregistration.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Horizontal Pod Autoscaler. +*/}} +{{- define "common.capabilities.hpa.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" .context -}} +{{- print "autoscaling/v2" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Vertical Pod Autoscaler. +*/}} +{{- define "common.capabilities.vpa.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "autoscaling/v1beta2" -}} +{{- else -}} +{{- print "autoscaling/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if PodSecurityPolicy is supported +*/}} +{{- define "common.capabilities.psp.supported" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if or (empty $kubeVersion) (semverCompare "<1.25-0" $kubeVersion) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if AdmissionConfiguration is supported +*/}} +{{- define "common.capabilities.admissionConfiguration.supported" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} + {{- true -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for AdmissionConfiguration. +*/}} +{{- define "common.capabilities.admissionConfiguration.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "apiserver.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiserver.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for PodSecurityConfiguration. +*/}} +{{- define "common.capabilities.podSecurityConfiguration.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "pod-security.admission.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "pod-security.admission.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the used Helm version is 3.3+. +A way to check the used Helm version was not introduced until version 3.3.0 with .Capabilities.HelmVersion, which contains an additional "{}}" structure. +This check is introduced as a regexMatch instead of {{ if .Capabilities.HelmVersion }} because checking for the key HelmVersion in <3.3 results in a "interface not found" error. +**To be removed when the catalog's minimun Helm version is 3.3** +*/}} +{{- define "common.capabilities.supportsHelmVersion" -}} +{{- if regexMatch "{(v[0-9])*[^}]*}}$" (.Capabilities | toString ) }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_compatibility.tpl b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_compatibility.tpl new file mode 100644 index 0000000..19c26db --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_compatibility.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return true if the detected platform is Openshift +Usage: +{{- include "common.compatibility.isOpenshift" . -}} +*/}} +{{- define "common.compatibility.isOpenshift" -}} +{{- if .Capabilities.APIVersions.Has "security.openshift.io/v1" -}} +{{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Render a compatible securityContext depending on the platform. By default it is maintained as it is. In other platforms like Openshift we remove default user/group values that do not work out of the box with the restricted-v1 SCC +Usage: +{{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) -}} +*/}} +{{- define "common.compatibility.renderSecurityContext" -}} +{{- $adaptedContext := .secContext -}} + +{{- if (((.context.Values.global).compatibility).openshift) -}} + {{- if or (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "force") (and (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "auto") (include "common.compatibility.isOpenshift" .context)) -}} + {{/* Remove incompatible user/group values that do not work in Openshift out of the box */}} + {{- $adaptedContext = omit $adaptedContext "fsGroup" "runAsUser" "runAsGroup" -}} + {{- if not .secContext.seLinuxOptions -}} + {{/* If it is an empty object, we remove it from the resulting context because it causes validation issues */}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{/* Remove empty seLinuxOptions object if global.compatibility.omitEmptySeLinuxOptions is set to true */}} +{{- if and (((.context.Values.global).compatibility).omitEmptySeLinuxOptions) (not .secContext.seLinuxOptions) -}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} +{{- end -}} +{{/* Remove fields that are disregarded when running the container in privileged mode */}} +{{- if $adaptedContext.privileged -}} + {{- $adaptedContext = omit $adaptedContext "capabilities" -}} +{{- end -}} +{{- omit $adaptedContext "enabled" | toYaml -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_errors.tpl b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_errors.tpl new file mode 100644 index 0000000..fb704c9 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_errors.tpl @@ -0,0 +1,92 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Throw error when upgrading using empty passwords values that must not be empty. + +Usage: +{{- $validationError00 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password00" "secret" "secretName" "field" "password-00") -}} +{{- $validationError01 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password01" "secret" "secretName" "field" "password-01") -}} +{{ include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $validationError00 $validationError01) "context" $) }} + +Required password params: + - validationErrors - String - Required. List of validation strings to be return, if it is empty it won't throw error. + - context - Context - Required. Parent context. +*/}} +{{- define "common.errors.upgrade.passwords.empty" -}} + {{- $validationErrors := join "" .validationErrors -}} + {{- if and $validationErrors .context.Release.IsUpgrade -}} + {{- $errorString := "\nPASSWORDS ERROR: You must provide your current passwords when upgrading the release." -}} + {{- $errorString = print $errorString "\n Note that even after reinstallation, old credentials may be needed as they may be kept in persistent volume claims." -}} + {{- $errorString = print $errorString "\n Further information can be obtained at https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues/#credential-errors-while-upgrading-chart-releases" -}} + {{- $errorString = print $errorString "\n%s" -}} + {{- printf $errorString $validationErrors | fail -}} + {{- end -}} +{{- end -}} + +{{/* +Throw error when original container images are replaced. +The error can be bypassed by setting the "global.security.allowInsecureImages" to true. In this case, +a warning message will be shown instead. + +Usage: +{{ include "common.errors.insecureImages" (dict "images" (list .Values.path.to.the.imageRoot) "context" $) }} +*/}} +{{- define "common.errors.insecureImages" -}} +{{- $relocatedImages := list -}} +{{- $replacedImages := list -}} +{{- $bitnamiLegacyImages := list -}} +{{- $retaggedImages := list -}} +{{- $globalRegistry := ((.context.Values.global).imageRegistry) -}} +{{- $originalImages := .context.Chart.Annotations.images -}} +{{- range .images -}} + {{- $registryName := default .registry $globalRegistry -}} + {{- $fullImageNameNoTag := printf "%s/%s" $registryName .repository -}} + {{- $fullImageName := printf "%s:%s" $fullImageNameNoTag .tag -}} + {{- if not (contains $fullImageNameNoTag $originalImages) -}} + {{- if not (contains $registryName $originalImages) -}} + {{- $relocatedImages = append $relocatedImages $fullImageName -}} + {{- else if not (contains .repository $originalImages) -}} + {{- $replacedImages = append $replacedImages $fullImageName -}} + {{- if contains "docker.io/bitnamilegacy/" $fullImageNameNoTag -}} + {{- $bitnamiLegacyImages = append $bitnamiLegacyImages $fullImageName -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- if not (contains (printf "%s:%s" .repository .tag) $originalImages) -}} + {{- $retaggedImages = append $retaggedImages $fullImageName -}} + {{- end -}} +{{- end -}} + +{{- if and (or (gt (len $relocatedImages) 0) (gt (len $replacedImages) 0)) (((.context.Values.global).security).allowInsecureImages) -}} + {{- print "\n\n⚠ SECURITY WARNING: Verifying original container images was skipped. Please note this Helm chart was designed, tested, and validated on multiple platforms using a specific set of Bitnami and Bitnami Secure Images containers. Substituting other containers is likely to cause degraded security and performance, broken chart features, and missing environment variables.\n" -}} +{{- else if (or (gt (len $relocatedImages) 0) (gt (len $replacedImages) 0)) -}} + {{- $errorString := "Original containers have been substituted for unrecognized ones. Deploying this chart with non-standard containers is likely to cause degraded security and performance, broken chart features, and missing environment variables." -}} + {{- $errorString = print $errorString "\n\nUnrecognized images:" -}} + {{- range (concat $relocatedImages $replacedImages) -}} + {{- $errorString = print $errorString "\n - " . -}} + {{- end -}} + {{- if and (eq (len $relocatedImages) 0) (eq (len $replacedImages) (len $bitnamiLegacyImages)) -}} + {{- $errorString = print "\n\n⚠ WARNING: " $errorString -}} + {{- print $errorString -}} + {{- else if or (contains "docker.io/bitnami/" $originalImages) (contains "docker.io/bitnamiprem/" $originalImages) (contains "docker.io/bitnamisecure/" $originalImages) -}} + {{- $errorString = print "\n\n⚠ ERROR: " $errorString -}} + {{- $errorString = print $errorString "\n\nIf you are sure you want to proceed with non-standard containers, you can skip container image verification by setting the global parameter 'global.security.allowInsecureImages' to true." -}} + {{- $errorString = print $errorString "\nFurther information can be obtained at https://github.com/bitnami/charts/issues/30850" -}} + {{- print $errorString | fail -}} + {{- else if gt (len $replacedImages) 0 -}} + {{- $errorString = print "\n\n⚠ WARNING: " $errorString -}} + {{- print $errorString -}} + {{- end -}} +{{- else if gt (len $retaggedImages) 0 -}} + {{- $warnString := "\n\n⚠ WARNING: Original containers have been retagged. Please note this Helm chart was tested, and validated on multiple platforms using a specific set of Bitnami and Bitnami Secure Images containers. Substituting original image tags could cause unexpected behavior." -}} + {{- $warnString = print $warnString "\n\nRetagged images:" -}} + {{- range $retaggedImages -}} + {{- $warnString = print $warnString "\n - " . -}} + {{- end -}} + {{- print $warnString -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_images.tpl b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_images.tpl new file mode 100644 index 0000000..76bb7ce --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_images.tpl @@ -0,0 +1,115 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Return the proper image name. +If image tag and digest are not defined, termination fallbacks to chart appVersion. +{{ include "common.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" .Values.global "chart" .Chart ) }} +*/}} +{{- define "common.images.image" -}} +{{- $registryName := default .imageRoot.registry ((.global).imageRegistry) -}} +{{- $repositoryName := .imageRoot.repository -}} +{{- $separator := ":" -}} +{{- $termination := .imageRoot.tag | toString -}} + +{{- if not .imageRoot.tag }} + {{- if .chart }} + {{- $termination = .chart.AppVersion | toString -}} + {{- end -}} +{{- end -}} +{{- if .imageRoot.digest }} + {{- $separator = "@" -}} + {{- $termination = .imageRoot.digest | toString -}} +{{- end -}} +{{- if $registryName }} + {{- printf "%s/%s%s%s" $registryName $repositoryName $separator $termination -}} +{{- else -}} + {{- printf "%s%s%s" $repositoryName $separator $termination -}} +{{- end -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead) +{{ include "common.images.pullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global) }} +*/}} +{{- define "common.images.pullSecrets" -}} + {{- $pullSecrets := list }} + + {{- range ((.global).imagePullSecrets) -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end }} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) -}} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names evaluating values as templates +{{ include "common.images.renderPullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $) }} +*/}} +{{- define "common.images.renderPullSecrets" -}} + {{- $pullSecrets := list }} + {{- $context := .context }} + + {{- range (($context.Values.global).imagePullSecrets) -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) -}} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper image version (ingores image revision/prerelease info & fallbacks to chart appVersion) +{{ include "common.images.version" ( dict "imageRoot" .Values.path.to.the.image "chart" .Chart ) }} +*/}} +{{- define "common.images.version" -}} +{{- $imageTag := .imageRoot.tag | toString -}} +{{/* regexp from https://github.com/Masterminds/semver/blob/23f51de38a0866c5ef0bfc42b3f735c73107b700/version.go#L41-L44 */}} +{{- if regexMatch `^([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?$` $imageTag -}} + {{- $version := semver $imageTag -}} + {{- printf "%d.%d.%d" $version.Major $version.Minor $version.Patch -}} +{{- else -}} + {{- print .chart.AppVersion -}} +{{- end -}} +{{- end -}} + diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_ingress.tpl b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_ingress.tpl new file mode 100644 index 0000000..2d0dbf1 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_ingress.tpl @@ -0,0 +1,41 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Generate backend entry that is compatible with all Kubernetes API versions. + +Usage: +{{ include "common.ingress.backend" (dict "serviceName" "backendName" "servicePort" "backendPort" "context" $) }} + +Params: + - serviceName - String. Name of an existing service backend + - servicePort - String/Int. Port name (or number) of the service. It will be translated to different yaml depending if it is a string or an integer. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.ingress.backend" -}} +service: + name: {{ .serviceName }} + port: + {{- if typeIs "string" .servicePort }} + name: {{ .servicePort }} + {{- else if or (typeIs "int" .servicePort) (typeIs "float64" .servicePort) }} + number: {{ .servicePort | int }} + {{- end }} +{{- end -}} + +{{/* +Return true if cert-manager required annotations for TLS signed +certificates are set in the Ingress annotations +Ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations +Usage: +{{ include "common.ingress.certManagerRequest" ( dict "annotations" .Values.path.to.the.ingress.annotations ) }} +*/}} +{{- define "common.ingress.certManagerRequest" -}} +{{ if or (hasKey .annotations "cert-manager.io/cluster-issuer") (hasKey .annotations "cert-manager.io/issuer") (hasKey .annotations "kubernetes.io/tls-acme") }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_labels.tpl b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_labels.tpl new file mode 100644 index 0000000..0a0cc54 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_labels.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Kubernetes standard labels +{{ include "common.labels.standard" (dict "customLabels" .Values.commonLabels "context" $) -}} +*/}} +{{- define "common.labels.standard" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{- $default := dict "app.kubernetes.io/name" (include "common.names.name" .context) "helm.sh/chart" (include "common.names.chart" .context) "app.kubernetes.io/instance" .context.Release.Name "app.kubernetes.io/managed-by" .context.Release.Service -}} +{{- with .context.Chart.AppVersion -}} +{{- $_ := set $default "app.kubernetes.io/version" . -}} +{{- end -}} +{{ template "common.tplvalues.merge" (dict "values" (list .customLabels $default) "context" .context) }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +helm.sh/chart: {{ include "common.names.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Chart.AppVersion }} +app.kubernetes.io/version: {{ . | quote }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Labels used on immutable fields such as deploy.spec.selector.matchLabels or svc.spec.selector +{{ include "common.labels.matchLabels" (dict "customLabels" .Values.podLabels "context" $) -}} + +We don't want to loop over custom labels appending them to the selector +since it's very likely that it will break deployments, services, etc. +However, it's important to overwrite the standard labels if the user +overwrote them on metadata.labels fields. +*/}} +{{- define "common.labels.matchLabels" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{ merge (pick (include "common.tplvalues.render" (dict "value" .customLabels "context" .context) | fromYaml) "app.kubernetes.io/name" "app.kubernetes.io/instance") (dict "app.kubernetes.io/name" (include "common.names.name" .context) "app.kubernetes.io/instance" .context.Release.Name ) | toYaml }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_names.tpl b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_names.tpl new file mode 100644 index 0000000..d5d0ae4 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_names.tpl @@ -0,0 +1,72 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "common.names.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "common.names.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "common.names.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- $releaseName := regexReplaceAll "(-?[^a-z\\d\\-])+-?" (lower .Release.Name) "-" -}} +{{- if contains $name $releaseName -}} +{{- $releaseName | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" $releaseName $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified dependency name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +Usage: +{{ include "common.names.dependency.fullname" (dict "chartName" "dependency-chart-name" "chartValues" .Values.dependency-chart "context" $) }} +*/}} +{{- define "common.names.dependency.fullname" -}} +{{- if .chartValues.fullnameOverride -}} +{{- .chartValues.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .chartName .chartValues.nameOverride -}} +{{- if contains $name .context.Release.Name -}} +{{- .context.Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .context.Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts. +*/}} +{{- define "common.names.namespace" -}} +{{- default .Release.Namespace .Values.namespaceOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a fully qualified app name adding the installation's namespace. +*/}} +{{- define "common.names.fullname.namespace" -}} +{{- printf "%s-%s" (include "common.names.fullname" .) (include "common.names.namespace" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_resources.tpl b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_resources.tpl new file mode 100644 index 0000000..d8a43e1 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_resources.tpl @@ -0,0 +1,50 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a resource request/limit object based on a given preset. +These presets are for basic testing and not meant to be used in production +{{ include "common.resources.preset" (dict "type" "nano") -}} +*/}} +{{- define "common.resources.preset" -}} +{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} +{{- $presets := dict + "nano" (dict + "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "2Gi") + ) + "micro" (dict + "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "2Gi") + ) + "small" (dict + "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "2Gi") + ) + "medium" (dict + "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "2Gi") + ) + "large" (dict + "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "2Gi") + ) + "xlarge" (dict + "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "2Gi") + ) + "2xlarge" (dict + "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "2Gi") + ) + }} +{{- if hasKey $presets .type -}} +{{- index $presets .type | toYaml -}} +{{- else -}} +{{- printf "ERROR: Preset key '%s' invalid. Allowed values are %s" .type (join "," (keys $presets)) | fail -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_secrets.tpl b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_secrets.tpl new file mode 100644 index 0000000..7868c00 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_secrets.tpl @@ -0,0 +1,192 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Generate secret name. + +Usage: +{{ include "common.secrets.name" (dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $) }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - defaultNameSuffix - String - Optional. It is used only if we have several secrets in the same deployment. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.secrets.name" -}} +{{- $name := (include "common.names.fullname" .context) -}} + +{{- if .defaultNameSuffix -}} +{{- $name = printf "%s-%s" $name .defaultNameSuffix | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- with .existingSecret -}} +{{- if not (typeIs "string" .) -}} +{{- with .name -}} +{{- $name = . -}} +{{- end -}} +{{- else -}} +{{- $name = . -}} +{{- end -}} +{{- end -}} + +{{- printf "%s" $name -}} +{{- end -}} + +{{/* +Generate secret key. + +Usage: +{{ include "common.secrets.key" (dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName") }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - key - String - Required. Name of the key in the secret. +*/}} +{{- define "common.secrets.key" -}} +{{- $key := .key -}} + +{{- if .existingSecret -}} + {{- if not (typeIs "string" .existingSecret) -}} + {{- if .existingSecret.keyMapping -}} + {{- $key = index .existingSecret.keyMapping $.key -}} + {{- end -}} + {{- end }} +{{- end -}} + +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Generate secret password or retrieve one if already created. + +Usage: +{{ include "common.secrets.passwords.manage" (dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "honorProvidedValues" false "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - providedValues - List - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - length - int - Optional - Length of the generated random password. + - strong - Boolean - Optional - Whether to add symbols to the generated random password. + - chartName - String - Optional - Name of the chart used when said chart is deployed as a subchart. + - context - Context - Required - Parent context. + - failOnNew - Boolean - Optional - Default to true. If set to false, skip errors adding new keys to existing secrets. + - skipB64enc - Boolean - Optional - Default to false. If set to true, no the secret will not be base64 encrypted. + - skipQuote - Boolean - Optional - Default to false. If set to true, no quotes will be added around the secret. + - honorProvidedValues - Boolean - Optional - Default to false. If set to true, the values in providedValues have higher priority than an existing secret +The order in which this function returns a secret password: + 1. Password provided via the values.yaml if honorProvidedValues = true + (If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned) + 2. Already existing 'Secret' resource + (If a 'Secret' resource is found under the name provided to the 'secret' parameter to this function and that 'Secret' resource contains a key with the name passed as the 'key' parameter to this function then the value of this existing secret password will be returned) + 3. Password provided via the values.yaml if honorProvidedValues = false + (If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned) + 4. Randomly generated secret password + (A new random secret password with the length specified in the 'length' parameter will be generated and returned) + +*/}} +{{- define "common.secrets.passwords.manage" -}} + +{{- $password := "" }} +{{- $subchart := "" }} +{{- $chartName := default "" .chartName }} +{{- $passwordLength := default 10 .length }} +{{- $providedPasswordKey := include "common.utils.getKeyFromList" (dict "keys" .providedValues "context" $.context) }} +{{- $providedPasswordValue := include "common.utils.getValueFromKey" (dict "key" $providedPasswordKey "context" $.context) }} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data }} +{{- if $secretData }} + {{- if hasKey $secretData .key }} + {{- $password = index $secretData .key | b64dec }} + {{- else if not (eq .failOnNew false) }} + {{- printf "\nPASSWORDS ERROR: The secret \"%s\" does not contain the key \"%s\"\n" .secret .key | fail -}} + {{- end -}} +{{- end }} + +{{- if and $providedPasswordValue .honorProvidedValues }} + {{- $password = tpl ($providedPasswordValue | toString) .context }} +{{- end }} + +{{- if not $password }} + {{- if $providedPasswordValue }} + {{- $password = tpl ($providedPasswordValue | toString) .context }} + {{- else }} + {{- if .context.Values.enabled }} + {{- $subchart = $chartName }} + {{- end -}} + + {{- if not (eq .failOnNew false) }} + {{- $requiredPassword := dict "valueKey" $providedPasswordKey "secret" .secret "field" .key "subchart" $subchart "context" $.context -}} + {{- $requiredPasswordError := include "common.validations.values.single.empty" $requiredPassword -}} + {{- $passwordValidationErrors := list $requiredPasswordError -}} + {{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" $passwordValidationErrors "context" $.context) -}} + {{- end }} + + {{- if .strong }} + {{- $subStr := list (lower (randAlpha 1)) (randNumeric 1) (upper (randAlpha 1)) | join "_" }} + {{- $password = randAscii $passwordLength }} + {{- $password = regexReplaceAllLiteral "\\W" $password "@" | substr 5 $passwordLength }} + {{- $password = printf "%s%s" $subStr $password | toString | shuffle }} + {{- else }} + {{- $password = randAlphaNum $passwordLength }} + {{- end }} + {{- end -}} +{{- end -}} +{{- if not .skipB64enc }} +{{- $password = $password | b64enc }} +{{- end -}} +{{- if .skipQuote -}} +{{- printf "%s" $password -}} +{{- else -}} +{{- printf "%s" $password | quote -}} +{{- end -}} +{{- end -}} + +{{/* +Reuses the value from an existing secret, otherwise sets its value to a default value. + +Usage: +{{ include "common.secrets.lookup" (dict "secret" "secret-name" "key" "keyName" "defaultValue" .Values.myValue "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - defaultValue - String - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - context - Context - Required - Parent context. + +*/}} +{{- define "common.secrets.lookup" -}} +{{- $value := "" -}} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data -}} +{{- if and $secretData (hasKey $secretData .key) -}} + {{- $value = index $secretData .key -}} +{{- else if .defaultValue -}} + {{- $value = .defaultValue | toString | b64enc -}} +{{- end -}} +{{- if $value -}} +{{- printf "%s" $value -}} +{{- end -}} +{{- end -}} + +{{/* +Returns whether a previous generated secret already exists + +Usage: +{{ include "common.secrets.exists" (dict "secret" "secret-name" "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - context - Context - Required - Parent context. +*/}} +{{- define "common.secrets.exists" -}} +{{- $secret := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret) }} +{{- if $secret }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_storage.tpl b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_storage.tpl new file mode 100644 index 0000000..aa75856 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_storage.tpl @@ -0,0 +1,21 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the proper Storage Class +{{ include "common.storage.class" ( dict "persistence" .Values.path.to.the.persistence "global" $) }} +*/}} +{{- define "common.storage.class" -}} +{{- $storageClass := (.global).storageClass | default .persistence.storageClass | default (.global).defaultStorageClass | default "" -}} +{{- if $storageClass -}} + {{- if (eq "-" $storageClass) -}} + {{- printf "storageClassName: \"\"" -}} + {{- else -}} + {{- printf "storageClassName: %s" $storageClass -}} + {{- end -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_tplvalues.tpl b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_tplvalues.tpl new file mode 100644 index 0000000..a04f4c1 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_tplvalues.tpl @@ -0,0 +1,52 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Renders a value that contains template perhaps with scope if the scope is present. +Usage: +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ ) }} +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ "scope" $app ) }} +*/}} +{{- define "common.tplvalues.render" -}} +{{- $value := typeIs "string" .value | ternary .value (.value | toYaml) }} +{{- if contains "{{" (toJson .value) }} + {{- if .scope }} + {{- tpl (cat "{{- with $.RelativeScope -}}" $value "{{- end }}") (merge (dict "RelativeScope" .scope) .context) }} + {{- else }} + {{- tpl $value .context }} + {{- end }} +{{- else }} + {{- $value }} +{{- end }} +{{- end -}} + +{{/* +Merge a list of values that contains template after rendering them. +Merge precedence is consistent with http://masterminds.github.io/sprig/dicts.html#merge-mustmerge +Usage: +{{ include "common.tplvalues.merge" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }} +*/}} +{{- define "common.tplvalues.merge" -}} +{{- $dst := dict -}} +{{- range .values -}} +{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | merge $dst -}} +{{- end -}} +{{ $dst | toYaml }} +{{- end -}} + +{{/* +Merge a list of values that contains template after rendering them. +Merge precedence is consistent with https://masterminds.github.io/sprig/dicts.html#mergeoverwrite-mustmergeoverwrite +Usage: +{{ include "common.tplvalues.merge-overwrite" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }} +*/}} +{{- define "common.tplvalues.merge-overwrite" -}} +{{- $dst := dict -}} +{{- range .values -}} +{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | mergeOverwrite $dst -}} +{{- end -}} +{{ $dst | toYaml }} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_utils.tpl b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_utils.tpl new file mode 100644 index 0000000..d53c74a --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_utils.tpl @@ -0,0 +1,77 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Print instructions to get a secret value. +Usage: +{{ include "common.utils.secret.getvalue" (dict "secret" "secret-name" "field" "secret-value-field" "context" $) }} +*/}} +{{- define "common.utils.secret.getvalue" -}} +{{- $varname := include "common.utils.fieldToEnvVar" . -}} +export {{ $varname }}=$(kubectl get secret --namespace {{ include "common.names.namespace" .context | quote }} {{ .secret }} -o jsonpath="{.data.{{ .field }}}" | base64 -d) +{{- end -}} + +{{/* +Build env var name given a field +Usage: +{{ include "common.utils.fieldToEnvVar" dict "field" "my-password" }} +*/}} +{{- define "common.utils.fieldToEnvVar" -}} + {{- $fieldNameSplit := splitList "-" .field -}} + {{- $upperCaseFieldNameSplit := list -}} + + {{- range $fieldNameSplit -}} + {{- $upperCaseFieldNameSplit = append $upperCaseFieldNameSplit ( upper . ) -}} + {{- end -}} + + {{ join "_" $upperCaseFieldNameSplit }} +{{- end -}} + +{{/* +Gets a value from .Values given +Usage: +{{ include "common.utils.getValueFromKey" (dict "key" "path.to.key" "context" $) }} +*/}} +{{- define "common.utils.getValueFromKey" -}} +{{- $splitKey := splitList "." .key -}} +{{- $value := "" -}} +{{- $latestObj := $.context.Values -}} +{{- range $splitKey -}} + {{- if not $latestObj -}} + {{- printf "please review the entire path of '%s' exists in values" $.key | fail -}} + {{- end -}} + {{- $value = ( index $latestObj . ) -}} + {{- $latestObj = $value -}} +{{- end -}} +{{- printf "%v" (default "" $value) -}} +{{- end -}} + +{{/* +Returns first .Values key with a defined value or first of the list if all non-defined +Usage: +{{ include "common.utils.getKeyFromList" (dict "keys" (list "path.to.key1" "path.to.key2") "context" $) }} +*/}} +{{- define "common.utils.getKeyFromList" -}} +{{- $key := first .keys -}} +{{- $reverseKeys := reverse .keys }} +{{- range $reverseKeys }} + {{- $value := include "common.utils.getValueFromKey" (dict "key" . "context" $.context ) }} + {{- if $value -}} + {{- $key = . }} + {{- end -}} +{{- end -}} +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Checksum a template at "path" containing a *single* resource (ConfigMap,Secret) for use in pod annotations, excluding the metadata (see #18376). +Usage: +{{ include "common.utils.checksumTemplate" (dict "path" "/configmap.yaml" "context" $) }} +*/}} +{{- define "common.utils.checksumTemplate" -}} +{{- $obj := include (print .context.Template.BasePath .path) .context | fromYaml -}} +{{ omit $obj "apiVersion" "kind" "metadata" | toYaml | sha256sum }} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_warnings.tpl b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_warnings.tpl new file mode 100644 index 0000000..62c44df --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/_warnings.tpl @@ -0,0 +1,109 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Warning about using rolling tag. +Usage: +{{ include "common.warnings.rollingTag" .Values.path.to.the.imageRoot }} +*/}} +{{- define "common.warnings.rollingTag" -}} + +{{- if and (contains "bitnami/" .repository) (not (.tag | toString | regexFind "-r\\d+$|sha256:")) }} +WARNING: Rolling tag detected ({{ .repository }}:{{ .tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. ++info https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-understand-rolling-tags-containers-index.html +{{- end }} +{{- end -}} + +{{/* +Warning about replaced images from the original. +Usage: +{{ include "common.warnings.modifiedImages" (dict "images" (list .Values.path.to.the.imageRoot) "context" $) }} +*/}} +{{- define "common.warnings.modifiedImages" -}} +{{- $affectedImages := list -}} +{{- $printMessage := false -}} +{{- $originalImages := .context.Chart.Annotations.images -}} +{{- range .images -}} + {{- $fullImageName := printf (printf "%s/%s:%s" .registry .repository .tag) -}} + {{- if not (contains $fullImageName $originalImages) }} + {{- $affectedImages = append $affectedImages (printf "%s/%s:%s" .registry .repository .tag) -}} + {{- $printMessage = true -}} + {{- end -}} +{{- end -}} +{{- if $printMessage }} + +⚠ SECURITY WARNING: Original containers have been substituted. This Helm chart was designed, tested, and validated on multiple platforms using a specific set of Bitnami and Tanzu Application Catalog containers. Substituting other containers is likely to cause degraded security and performance, broken chart features, and missing environment variables. + +Substituted images detected: +{{- range $affectedImages }} + - {{ . }} +{{- end }} +{{- end -}} +{{- end -}} + +{{/* +Warning about not setting the resource object in all deployments. +Usage: +{{ include "common.warnings.resources" (dict "sections" (list "path1" "path2") context $) }} +Example: +{{- include "common.warnings.resources" (dict "sections" (list "csiProvider.provider" "server" "volumePermissions" "") "context" $) }} +The list in the example assumes that the following values exist: + - csiProvider.provider.resources + - server.resources + - volumePermissions.resources + - resources +*/}} +{{- define "common.warnings.resources" -}} +{{- $values := .context.Values -}} +{{- $printMessage := false -}} +{{ $affectedSections := list -}} +{{- range .sections -}} + {{- if eq . "" -}} + {{/* Case where the resources section is at the root (one main deployment in the chart) */}} + {{- if not (index $values "resources") -}} + {{- $affectedSections = append $affectedSections "resources" -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Case where the are multiple resources sections (more than one main deployment in the chart) */}} + {{- $keys := split "." . -}} + {{/* We iterate through the different levels until arriving to the resource section. Example: a.b.c.resources */}} + {{- $section := $values -}} + {{- range $keys -}} + {{- $section = index $section . -}} + {{- end -}} + {{- if not (index $section "resources") -}} + {{/* If the section has enabled=false or replicaCount=0, do not include it */}} + {{- if and (hasKey $section "enabled") -}} + {{- if index $section "enabled" -}} + {{/* enabled=true */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else if and (hasKey $section "replicaCount") -}} + {{/* We need a casting to int because number 0 is not treated as an int by default */}} + {{- if (gt (index $section "replicaCount" | int) 0) -}} + {{/* replicaCount > 0 */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Default case, add it to the affected sections */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- if $printMessage }} + +WARNING: There are "resources" sections in the chart not set. Using "resourcesPreset" is not recommended for production. For production installations, please set the following values according to your workload needs: +{{- range $affectedSections }} + - {{ . }} +{{- end }} ++info https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/templates/validations/_cassandra.tpl b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/validations/_cassandra.tpl new file mode 100644 index 0000000..f8fd213 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/validations/_cassandra.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.cassandra.values.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.cassandra.dbUser.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.dbUser.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled cassandra. + +Usage: +{{ include "common.cassandra.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.cassandra.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.cassandra.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key dbUser + +Usage: +{{ include "common.cassandra.values.key.dbUser" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.key.dbUser" -}} + {{- if .subchart -}} + cassandra.dbUser + {{- else -}} + dbUser + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/templates/validations/_mariadb.tpl b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/validations/_mariadb.tpl new file mode 100644 index 0000000..6ea8c0f --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/validations/_mariadb.tpl @@ -0,0 +1,108 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MariaDB required passwords are not empty. + +Usage: +{{ include "common.validations.values.mariadb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MariaDB values are stored, e.g: "mysql-passwords-secret" + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mariadb.passwords" -}} + {{- $existingSecret := include "common.mariadb.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mariadb.values.enabled" . -}} + {{- $architecture := include "common.mariadb.values.architecture" . -}} + {{- $authPrefix := include "common.mariadb.values.key.auth" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mariadb-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- if not (empty $valueUsername) -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mariadb-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replication") -}} + {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mariadb-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mariadb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mariadb. + +Usage: +{{ include "common.mariadb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mariadb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mariadb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mariadb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mariadb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.key.auth" -}} + {{- if .subchart -}} + mariadb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/templates/validations/_mongodb.tpl b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/validations/_mongodb.tpl new file mode 100644 index 0000000..e678a6d --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/validations/_mongodb.tpl @@ -0,0 +1,67 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mongodb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDb is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mongodb. + +Usage: +{{ include "common.mongodb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mongodb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mongodb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mongodb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.key.auth" -}} + {{- if .subchart -}} + mongodb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mongodb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/templates/validations/_mysql.tpl b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/validations/_mysql.tpl new file mode 100644 index 0000000..fbb65c3 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/validations/_mysql.tpl @@ -0,0 +1,67 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mysql.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mysql. + +Usage: +{{ include "common.mysql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mysql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mysql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mysql.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mysql.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.key.auth" -}} + {{- if .subchart -}} + mysql.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/templates/validations/_postgresql.tpl b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/validations/_postgresql.tpl new file mode 100644 index 0000000..51d4716 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/validations/_postgresql.tpl @@ -0,0 +1,105 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to decide whether evaluate global values. + +Usage: +{{ include "common.postgresql.values.use.global" (dict "key" "key-of-global" "context" $) }} +Params: + - key - String - Required. Field to be evaluated within global, e.g: "existingSecret" +*/}} +{{- define "common.postgresql.values.use.global" -}} + {{- if .context.Values.global -}} + {{- if .context.Values.global.postgresql -}} + {{- index .context.Values.global.postgresql .key | quote -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.postgresql.values.existingSecret" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.existingSecret" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "existingSecret" "context" .context) -}} + + {{- if .subchart -}} + {{- default (.context.Values.postgresql.existingSecret | quote) $globalValue -}} + {{- else -}} + {{- default (.context.Values.existingSecret | quote) $globalValue -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled postgresql. + +Usage: +{{ include "common.postgresql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key postgressPassword. + +Usage: +{{ include "common.postgresql.values.key.postgressPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.postgressPassword" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "postgresqlUsername" "context" .context) -}} + + {{- if not $globalValue -}} + {{- if .subchart -}} + postgresql.postgresqlPassword + {{- else -}} + postgresqlPassword + {{- end -}} + {{- else -}} + global.postgresql.postgresqlPassword + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled.replication. + +Usage: +{{ include "common.postgresql.values.enabled.replication" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.enabled.replication" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.replication.enabled -}} + {{- else -}} + {{- printf "%v" .context.Values.replication.enabled -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key replication.password. + +Usage: +{{ include "common.postgresql.values.key.replicationPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.replicationPassword" -}} + {{- if .subchart -}} + postgresql.replication.password + {{- else -}} + replication.password + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/templates/validations/_redis.tpl b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/validations/_redis.tpl new file mode 100644 index 0000000..9fedfef --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/validations/_redis.tpl @@ -0,0 +1,48 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for enabled redis. + +Usage: +{{ include "common.redis.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.redis.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.redis.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right prefix path for the values + +Usage: +{{ include "common.redis.values.key.prefix" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false +*/}} +{{- define "common.redis.values.keys.prefix" -}} + {{- if .subchart -}}redis.{{- else -}}{{- end -}} +{{- end -}} + +{{/* +Checks whether the redis chart's includes the standarizations (version >= 14) + +Usage: +{{ include "common.redis.values.standarized.version" (dict "context" $) }} +*/}} +{{- define "common.redis.values.standarized.version" -}} + + {{- $standarizedAuth := printf "%s%s" (include "common.redis.values.keys.prefix" .) "auth" -}} + {{- $standarizedAuthValues := include "common.utils.getValueFromKey" (dict "key" $standarizedAuth "context" .context) }} + + {{- if $standarizedAuthValues -}} + {{- true -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/templates/validations/_validations.tpl b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/validations/_validations.tpl new file mode 100644 index 0000000..7cdee61 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/templates/validations/_validations.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate values must not be empty. + +Usage: +{{- $validateValueConf00 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-01") -}} +{{ include "common.validations.values.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" +*/}} +{{- define "common.validations.values.multiple.empty" -}} + {{- range .required -}} + {{- include "common.validations.values.single.empty" (dict "valueKey" .valueKey "secret" .secret "field" .field "context" $.context) -}} + {{- end -}} +{{- end -}} + +{{/* +Validate a value must not be empty. + +Usage: +{{ include "common.validations.value.empty" (dict "valueKey" "mariadb.password" "secret" "secretName" "field" "my-password" "subchart" "subchart" "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" + - subchart - String - Optional - Name of the subchart that the validated password is part of. +*/}} +{{- define "common.validations.values.single.empty" -}} + {{- $value := include "common.utils.getValueFromKey" (dict "key" .valueKey "context" .context) }} + {{- $subchart := ternary "" (printf "%s." .subchart) (empty .subchart) }} + + {{- if not $value -}} + {{- $varname := "my-value" -}} + {{- $getCurrentValue := "" -}} + {{- if and .secret .field -}} + {{- $varname = include "common.utils.fieldToEnvVar" . -}} + {{- $getCurrentValue = printf " To get the current value:\n\n %s\n" (include "common.utils.secret.getvalue" .) -}} + {{- end -}} + {{- printf "\n '%s' must not be empty, please add '--set %s%s=$%s' to the command.%s" .valueKey $subchart .valueKey $varname $getCurrentValue -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/charts/common/values.yaml b/backing-services/gitea/charts/valkey-cluster/charts/common/values.yaml new file mode 100644 index 0000000..de2cac5 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/charts/common/values.yaml @@ -0,0 +1,8 @@ +# Copyright Broadcom, Inc. All Rights Reserved. +# SPDX-License-Identifier: APACHE-2.0 + +## bitnami/common +## It is required by CI/CD tools and processes. +## @skip exampleValue +## +exampleValue: common-chart diff --git a/backing-services/gitea/charts/valkey-cluster/templates/NOTES.txt b/backing-services/gitea/charts/valkey-cluster/templates/NOTES.txt new file mode 100644 index 0000000..ef4a081 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/templates/NOTES.txt @@ -0,0 +1,124 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +⚠ WARNING: Since August 28th, 2025, only a limited subset of images/charts are available for free. + Subscribe to Bitnami Secure Images to receive continued support and security updates. + More info at https://bitnami.com and https://github.com/bitnami/containers/issues/83267 + +{{- $secretName := include "valkey-cluster.secretName" . -}} +{{- $secretPasswordKey := include "valkey-cluster.secretPasswordKey" . -}} + +** Please be patient while the chart is being deployed ** + +{{- if .Values.diagnosticMode.enabled }} +The chart has been deployed in diagnostic mode. All probes have been disabled and the command has been overwritten with: + + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 4 }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 4 }} + +Get the list of pods by executing: + + kubectl get pods --namespace {{ .Release.Namespace }} -l app.kubernetes.io/instance={{ .Release.Name }} + +Access the pod you want to debug by executing + + kubectl exec --namespace {{ .Release.Namespace }} -ti -- bash + +In order to replicate the container startup scripts execute this command: + + /opt/bitnami/scripts/valkey-cluster/entrypoint.sh /opt/bitnami/scripts/valkey-cluster/run.sh + +{{- else }} + +{{ if .Values.usePassword }} +To get your password run: + {{ include "common.utils.secret.getvalue" (dict "secret" $secretName "field" $secretPasswordKey "context" $) }} +{{- end }} + +{{- if .Values.cluster.externalAccess.enabled }} + +To connect to your Valkey server from outside the cluster check the following information: + + 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 "common.names.fullname" . }}' + + You will have a different external IP for each Valkey node. Get the external ip from `-external` suffixed services: `kubectl get svc`. + Valkey port: {{ .Values.cluster.externalAccess.service.port }} + + {{- if not .Values.cluster.externalAccess.service.loadBalancerIP }} + Once the LoadBalancerIPs are ready, you need to provide them and perform a Helm Upgrade: + + helm upgrade --namespace {{ .Release.Namespace }} {{ .Release.Name }} --set "cluster.externalAccess.enabled=true,cluster.externalAccess.service.type=LoadBalancer{{- $root := . }}{{ $count := .Values.cluster.nodes | int }}{{ range $i, $v := until $count }},cluster.externalAccess.service.loadBalancerIP[{{ $i }}]=load-balancerip-{{- $i }}{{- end }}" oci://registry-1.docker.io/bitnamicharts/valkey-cluster + Where loadbalancer-ip-i are the LoadBalancerIPs provided by the cluster. + {{- else -}} + {{- if .Values.cluster.init -}} + INFO: The Job to create the cluster will be created. + {{- end -}} + + To connect to your database from outside the cluster execute the following commands: + + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "common.names.fullname" . }}-0-svc --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") + valkey-cli -c -h $SERVICE_IP -p {{ .Values.service.ports.valkey }} {{- if .Values.usePassword }} -a $VALKEY_PASSWORD{{ end }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + {{- end }} + +{{- else }} + +You have deployed a Valkey Cluster accessible only from within you Kubernetes Cluster. + +{{- if .Values.cluster.init -}} +INFO: The Job to create the cluster will be created. +{{- end -}} + +To connect to your Valkey cluster: + +1. Run a Valkey pod that you can use as a client: +{{- $password_env := ternary (include "common.utils.fieldToEnvVar" (dict "field" $secretPasswordKey)) "VALKEYPASSWORD" (not (eq .Values.notEmptyString "")) -}} +{{- if .Values.tls.enabled }} + kubectl run --namespace {{ .Release.Namespace }} {{ template "common.names.fullname" . }}-client --restart='Never' --env VALKEY_PASSWORD=${{ $password_env }} --image {{ template "valkey-cluster.image" . }} --command -- sleep infinity + + Copy your TLS certificates to the pod: + + kubectl cp --namespace {{ .Release.Namespace }} /path/to/client.cert {{ template "common.names.fullname" . }}-client:/tmp/client.cert + kubectl cp --namespace {{ .Release.Namespace }} /path/to/client.key {{ template "common.names.fullname" . }}-client:/tmp/client.key + kubectl cp --namespace {{ .Release.Namespace }} /path/to/CA.cert {{ template "common.names.fullname" . }}-client:/tmp/CA.cert + + Use the following command to attach to the pod: + + kubectl exec --tty -i {{ template "common.names.fullname" . }}-client \ + {{- if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }}--labels="{{ template "common.names.fullname" . }}-client=true" \{{- end }} + --namespace {{ .Release.Namespace }} -- bash +{{- else }} +kubectl run --namespace {{ .Release.Namespace }} {{ template "common.names.fullname" . }}-client --rm --tty -i --restart='Never' \ +{{ if .Values.usePassword }} --env VALKEY_PASSWORD=${{ $password_env }} \{{ end }} +{{- if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }}--labels="{{ template "common.names.fullname" . }}-client=true" \{{- end }} +--image {{ template "valkey-cluster.image" . }} -- bash +{{- end }} + +2. Connect using the Valkey CLI: + +valkey-cli -c -h {{ template "common.names.fullname" . }}{{ if .Values.usePassword }} -a ${{ $password_env }}{{ end }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{ if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }} +Note: Since NetworkPolicy is enabled, only pods with label +{{ template "common.names.fullname" . }}-client=true" +will be able to connect to valkey. +{{- end -}} +{{- end -}} + +{{- include "valkey-cluster.validateValues" . }} +{{- include "valkey-cluster.checkRollingTags" . }} +{{- include "common.warnings.rollingTag" .Values.volumePermissions.image }} +{{- include "common.warnings.rollingTag" .Values.sysctlImage }} + +{{- if and .Values.usePassword (not .Values.existingSecret) -}} + + {{- $requiredPassword := dict "valueKey" "password" "secret" $secretName "field" $secretPasswordKey "context" $ -}} + {{- $requiredPasswordError := include "common.validations.values.single.empty" $requiredPassword -}} + + {{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $requiredPasswordError) "context" $) -}} +{{- end -}} +{{- end }} +{{- include "common.warnings.resources" (dict "sections" (list "metrics" "valkey" "sysctlImage" "updateJob" "volumePermissions") "context" $) }} +{{- include "common.warnings.modifiedImages" (dict "images" (list .Values.image .Values.volumePermissions.image .Values.metrics.image .Values.sysctlImage) "context" $) }} +{{- include "common.errors.insecureImages" (dict "images" (list .Values.image .Values.volumePermissions.image .Values.metrics.image .Values.sysctlImage) "context" $) }} diff --git a/backing-services/gitea/charts/valkey-cluster/templates/_helpers.tpl b/backing-services/gitea/charts/valkey-cluster/templates/_helpers.tpl new file mode 100644 index 0000000..ed56b59 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/templates/_helpers.tpl @@ -0,0 +1,237 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the proper Valkey image name +*/}} +{{- define "valkey-cluster.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper image name (for the metrics image) +*/}} +{{- define "valkey-cluster.metrics.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.metrics.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper image name (for the init container volume-permissions image) +*/}} +{{- define "valkey-cluster.volumePermissions.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.volumePermissions.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return sysctl image +*/}} +{{- define "valkey-cluster.sysctl.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.sysctlImage "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "valkey-cluster.imagePullSecrets" -}} +{{- include "common.images.pullSecrets" (dict "images" (list .Values.image .Values.metrics.image) "global" .Values.global) -}} +{{- end -}} + +{{/* +Return true if a TLS secret object should be created +*/}} +{{- define "valkey-cluster.createTlsSecret" -}} +{{- if and .Values.tls.enabled .Values.tls.autoGenerated (not .Values.tls.existingSecret) (not .Values.tls.certificatesSecret) }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the secret containing Valkey TLS certificates +*/}} +{{- define "valkey-cluster.tlsSecretName" -}} +{{- $secretName := coalesce .Values.tls.existingSecret .Values.tls.certificatesSecret -}} +{{- if $secretName -}} + {{- printf "%s" (tpl $secretName $) -}} +{{- else -}} + {{- printf "%s-crt" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the cert file. +*/}} +{{- define "valkey-cluster.tlsCert" -}} +{{- if (include "valkey-cluster.createTlsSecret" . ) -}} + {{- printf "/opt/bitnami/valkey/certs/%s" "tls.crt" -}} +{{- else -}} + {{- required "Certificate filename is required when TLS in enabled" .Values.tls.certFilename | printf "/opt/bitnami/valkey/certs/%s" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the cert key file. +*/}} +{{- define "valkey-cluster.tlsCertKey" -}} +{{- if (include "valkey-cluster.createTlsSecret" . ) -}} + {{- printf "/opt/bitnami/valkey/certs/%s" "tls.key" -}} +{{- else -}} + {{- required "Certificate Key filename is required when TLS in enabled" .Values.tls.certKeyFilename | printf "/opt/bitnami/valkey/certs/%s" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the CA cert file. +*/}} +{{- define "valkey-cluster.tlsCACert" -}} +{{- if (include "valkey-cluster.createTlsSecret" . ) -}} + {{- printf "/opt/bitnami/valkey/certs/%s" "ca.crt" -}} +{{- else -}} + {{- required "Certificate CA filename is required when TLS in enabled" .Values.tls.certCAFilename | printf "/opt/bitnami/valkey/certs/%s" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the DH params file. +*/}} +{{- define "valkey-cluster.tlsDHParams" -}} +{{- if .Values.tls.dhParamsFilename -}} +{{- printf "/opt/bitnami/valkey/certs/%s" .Values.tls.dhParamsFilename -}} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "valkey-cluster.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "common.names.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Get the password secret. +*/}} +{{- define "valkey-cluster.secretName" -}} +{{- if .Values.existingSecret -}} +{{- printf "%s" (tpl .Values.existingSecret $) -}} +{{- else -}} +{{- printf "%s" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Get the password key to be retrieved from Valkey secret. +*/}} +{{- define "valkey-cluster.secretPasswordKey" -}} +{{- if and .Values.existingSecret .Values.existingSecretPasswordKey -}} +{{- printf "%s" .Values.existingSecretPasswordKey -}} +{{- else -}} +{{- printf "valkey-password" -}} +{{- end -}} +{{- end -}} + +{{/* +Return Valkey password +*/}} +{{- define "valkey-cluster.password" -}} +{{- if not (empty .Values.global.valkey.password) }} + {{- .Values.global.valkey.password -}} +{{- else if not (empty .Values.password) -}} + {{- .Values.password -}} +{{- else -}} + {{- randAlphaNum 10 -}} +{{- end -}} +{{- end -}} + +{{/* +Determines whether or not to create the Statefulset +*/}} +{{- define "valkey-cluster.createStatefulSet" -}} + {{- if not .Values.cluster.externalAccess.enabled -}} + {{- true -}} + {{- end -}} + {{- if and .Values.cluster.externalAccess.enabled .Values.cluster.externalAccess.service.loadBalancerIP -}} + {{- true -}} + {{- end -}} +{{- end -}} + +{{/* Check if there are rolling tags in the images */}} +{{- define "valkey-cluster.checkRollingTags" -}} +{{- include "common.warnings.rollingTag" .Values.image -}} +{{- include "common.warnings.rollingTag" .Values.metrics.image -}} +{{- end -}} + +{{/* +Compile all warnings into a single message, and call fail. +*/}} +{{- define "valkey-cluster.validateValues" -}} +{{- $messages := list -}} +{{- $messages := append $messages (include "valkey-cluster.validateValues.updateParameters" .) -}} +{{- $messages := append $messages (include "valkey-cluster.validateValues.tlsParameters" .) -}} +{{- $messages := append $messages (include "valkey-cluster.validateValues.tls" .) -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}} +{{- end -}} +{{- end -}} + +{{/* Validate values of Valkey Cluster - check update parameters */}} +{{- define "valkey-cluster.validateValues.updateParameters" -}} +{{- if and .Values.cluster.update.addNodes ( or (and .Values.cluster.externalAccess.enabled .Values.cluster.externalAccess.service.loadBalancerIP) ( not .Values.cluster.externalAccess.enabled )) -}} + {{- if .Values.cluster.externalAccess.enabled }} + {{- if not .Values.cluster.update.newExternalIPs -}} +valkey-cluster: newExternalIPs + You must provide the newExternalIPs to perform the cluster upgrade when using external access. + {{- end -}} + {{- else }} + {{- if not .Values.cluster.update.currentNumberOfNodes -}} +valkey-cluster: currentNumberOfNodes + You must provide the currentNumberOfNodes to perform an upgrade when not using external access. + {{- end -}} + {{- if kindIs "invalid" .Values.cluster.update.currentNumberOfReplicas -}} +valkey-cluster: currentNumberOfReplicas + You must provide the currentNumberOfReplicas to perform an upgrade when not using external access. + {{- end -}} + {{- end -}} +{{- end -}} +{{- end -}} + +{{/* Validate values of Valkey Cluster - tls settings */}} +{{- define "valkey-cluster.validateValues.tlsParameters" -}} +{{- if and .Values.tls.enabled (not .Values.tls.autoGenerated) }} +{{- if and (not .Values.tls.existingSecret) (not .Values.tls.certificatesSecret) -}} +valkey-cluster: TLSSecretMissingSecret + A secret containing the certificates for the TLS traffic is required when TLS is enabled. Please set the tls.existingSecret value +{{- end -}} +{{- if not .Values.tls.certFilename -}} +valkey-cluster: TLSSecretMissingCert + A certificate filename is required when TLS is enabled. Please set the tls.certFilename value +{{- end -}} +{{- if not .Values.tls.certKeyFilename -}} +valkey-cluster: TLSSecretMissingCertKey + A certificate key filename is required when TLS is enabled. Please set the tls.certKeyFilename value +{{- end -}} +{{- if not .Values.tls.certCAFilename -}} +valkey-cluster: TLSSecretMissingCertCA + A certificate CA filename is required when TLS is enabled. Please set the tls.certCAFilename value +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* Validate values of Valkey - PodSecurityPolicy create */}} +{{- define "valkey-cluster.validateValues.tls" -}} +{{- if and .Values.tls.enabled (not .Values.tls.autoGenerated) (not .Values.tls.existingSecret) (not .Values.tls.certificatesSecret) }} +valkey-cluster: tls.enabled + In order to enable TLS, you also need to provide + an existing secret containing the TLS certificates or + enable auto-generated certificates. +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/templates/configmap.yaml b/backing-services/gitea/charts/valkey-cluster/templates/configmap.yaml new file mode 100644 index 0000000..20e4db7 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/templates/configmap.yaml @@ -0,0 +1,2284 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "common.names.fullname" . }}-default + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: +{{- if .Values.valkey.defaultConfigOverride }} + valkey-default.conf: |- + {{- include "common.tplvalues.render" (dict "value" .Values.valkey.defaultConfigOverride "context" $) | nindent 4 }} +{{- else }} + valkey-default.conf: |- + # Valkey configuration file example. + # + # Note that in order to read the configuration file, Valkey must be + # started with the file path as first argument: + # + # ./valkey-server /path/to/valkey.conf + + # Note on units: when memory size is needed, it is possible to specify + # it in the usual form of 1k 5GB 4M and so forth: + # + # 1k => 1000 bytes + # 1kb => 1024 bytes + # 1m => 1000000 bytes + # 1mb => 1024*1024 bytes + # 1g => 1000000000 bytes + # 1gb => 1024*1024*1024 bytes + # + # units are case insensitive so 1GB 1Gb 1gB are all the same. + + ################################## INCLUDES ################################### + + # Include one or more other config files here. This is useful if you + # have a standard template that goes to all Valkey servers but also need + # to customize a few per-server settings. Include files can include + # other files, so use this wisely. + # + # Note that option "include" won't be rewritten by command "CONFIG REWRITE" + # from admin or Valkey Sentinel. Since Valkey always uses the last processed + # line as value of a configuration directive, you'd better put includes + # at the beginning of this file to avoid overwriting config change at runtime. + # + # If instead you are interested in using includes to override configuration + # options, it is better to use include as the last line. + # + # Included paths may contain wildcards. All files matching the wildcards will + # be included in alphabetical order. + # Note that if an include path contains a wildcards but no files match it when + # the server is started, the include statement will be ignored and no error will + # be emitted. It is safe, therefore, to include wildcard files from empty + # directories. + # + # include /path/to/local.conf + # include /path/to/other.conf + # include /path/to/fragments/*.conf + # + + ################################## MODULES ##################################### + + # Load modules at startup. If the server is not able to load modules + # it will abort. It is possible to use multiple loadmodule directives. + # + # loadmodule /path/to/my_module.so + # loadmodule /path/to/other_module.so + + ################################## NETWORK ##################################### + + # By default, if no "bind" configuration directive is specified, Valkey listens + # for connections from all available network interfaces on the host machine. + # It is possible to listen to just one or multiple selected interfaces using + # the "bind" configuration directive, followed by one or more IP addresses. + # Each address can be prefixed by "-", which means that valkey will not fail to + # start if the address is not available. Being not available only refers to + # addresses that does not correspond to any network interface. Addresses that + # are already in use will always fail, and unsupported protocols will always BE + # silently skipped. + # + # Examples: + # + # bind 192.168.1.100 10.0.0.1 # listens on two specific IPv4 addresses + # bind 127.0.0.1 ::1 # listens on loopback IPv4 and IPv6 + # bind * -::* # like the default, all available interfaces + # + # ~~~ WARNING ~~~ If the computer running Valkey is directly exposed to the + # internet, binding to all the interfaces is dangerous and will expose the + # instance to everybody on the internet. So by default we uncomment the + # following bind directive, that will force Valkey to listen only on the + # IPv4 and IPv6 (if available) loopback interface addresses (this means Valkey + # will only be able to accept client connections from the same host that it is + # running on). + # + # IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES + # COMMENT OUT THE FOLLOWING LINE. + # + # You will also need to set a password unless you explicitly disable protected + # mode. + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + bind 127.0.0.1 -::1 + + # By default, outgoing connections (from replica to primary, from Sentinel to + # instances, cluster bus, etc.) are not bound to a specific local address. In + # most cases, this means the operating system will handle that based on routing + # and the interface through which the connection goes out. + # + # Using bind-source-addr it is possible to configure a specific address to bind + # to, which may also affect how the connection gets routed. + # + # Example: + # + # bind-source-addr 10.0.0.1 + + # Protected mode is a layer of security protection, in order to avoid that + # Valkey instances left open on the internet are accessed and exploited. + # + # When protected mode is on and the default user has no password, the server + # only accepts local connections from the IPv4 address (127.0.0.1), IPv6 address + # (::1) or Unix domain sockets. + # + # By default protected mode is enabled. You should disable it only if + # you are sure you want clients from other hosts to connect to Valkey + # even if no authentication is configured. + protected-mode yes + + # Valkey uses default hardened security configuration directives to reduce the + # attack surface on innocent users. Therefore, several sensitive configuration + # directives are immutable, and some potentially-dangerous commands are blocked. + # + # Configuration directives that control files that Valkey writes to (e.g., 'dir' + # and 'dbfilename') and that aren't usually modified during runtime + # are protected by making them immutable. + # + # Commands that can increase the attack surface of Valkey and that aren't usually + # called by users are blocked by default. + # + # These can be exposed to either all connections or just local ones by setting + # each of the configs listed below to either of these values: + # + # no - Block for any connection (remain immutable) + # yes - Allow for any connection (no protection) + # local - Allow only for local connections. Ones originating from the + # IPv4 address (127.0.0.1), IPv6 address (::1) or Unix domain sockets. + # + # enable-protected-configs no + # enable-debug-command no + # enable-module-command no + + # Accept connections on the specified port, default is 6379 (IANA #815344). + # If port 0 is specified Valkey will not listen on a TCP socket. + port 6379 + + # TCP listen() backlog. + # + # In high requests-per-second environments you need a high backlog in order + # to avoid slow clients connection issues. Note that the Linux kernel + # will silently truncate it to the value of /proc/sys/net/core/somaxconn so + # make sure to raise both the value of somaxconn and tcp_max_syn_backlog + # in order to get the desired effect. + tcp-backlog 511 + + # Unix socket. + # + # Specify the path for the Unix socket that will be used to listen for + # incoming connections. There is no default, so Valkey will not listen + # on a unix socket when not specified. + # + # unixsocket /run/valkey.sock + # unixsocketperm 700 + + # Close the connection after a client is idle for N seconds (0 to disable) + timeout 0 + + # TCP keepalive. + # + # If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence + # of communication. This is useful for two reasons: + # + # 1) Detect dead peers. + # 2) Force network equipment in the middle to consider the connection to be + # alive. + # + # On Linux, the specified value (in seconds) is the period used to send ACKs. + # Note that to close the connection the double of the time is needed. + # On other kernels the period depends on the kernel configuration. + # + # A reasonable value for this option is 300 seconds + tcp-keepalive 300 + + # Apply OS-specific mechanism to mark the listening socket with the specified + # ID, to support advanced routing and filtering capabilities. + # + # On Linux, the ID represents a connection mark. + # On FreeBSD, the ID represents a socket cookie ID. + # On OpenBSD, the ID represents a route table ID. + # + # The default value is 0, which implies no marking is required. + # socket-mark-id 0 + + ################################# TLS/SSL ##################################### + + # By default, TLS/SSL is disabled. To enable it, the "tls-port" configuration + # directive can be used to define TLS-listening ports. To enable TLS on the + # default port, use: + # + # port 0 + # tls-port 6379 + + # Configure a X.509 certificate and private key to use for authenticating the + # server to connected clients, primarys or cluster peers. These files should be + # PEM formatted. + # + # tls-cert-file valkey.crt + # tls-key-file valkey.key + # + # If the key file is encrypted using a passphrase, it can be included here + # as well. + # + # tls-key-file-pass secret + + # Normally Valkey uses the same certificate for both server functions (accepting + # connections) and client functions (replicating from a primary, establishing + # cluster bus connections, etc.). + # + # Sometimes certificates are issued with attributes that designate them as + # client-only or server-only certificates. In that case it may be desired to use + # different certificates for incoming (server) and outgoing (client) + # connections. To do that, use the following directives: + # + # tls-client-cert-file client.crt + # tls-client-key-file client.key + # + # If the key file is encrypted using a passphrase, it can be included here + # as well. + # + # tls-client-key-file-pass secret + + # Configure a DH parameters file to enable Diffie-Hellman (DH) key exchange, + # required by older versions of OpenSSL (<3.0). Newer versions do not require + # this configuration and recommend against it. + # + # tls-dh-params-file valkey.dh + + # Configure a CA certificate(s) bundle or directory to authenticate TLS/SSL + # clients and peers. Valkey requires an explicit configuration of at least one + # of these, and will not implicitly use the system wide configuration. + # + # tls-ca-cert-file ca.crt + # tls-ca-cert-dir /etc/ssl/certs + + # By default, clients (including replica servers) on a TLS port are required + # to authenticate using valid client side certificates. + # + # If "no" is specified, client certificates are not required and not accepted. + # If "optional" is specified, client certificates are accepted and must be + # valid if provided, but are not required. + # + # tls-auth-clients no + # tls-auth-clients optional + + # By default, a Valkey replica does not attempt to establish a TLS connection + # with its primary. + # + # Use the following directive to enable TLS on replication links. + # + # tls-replication yes + + # By default, the Valkey Cluster bus uses a plain TCP connection. To enable + # TLS for the bus protocol, use the following directive: + # + # tls-cluster yes + + # By default, only TLSv1.2 and TLSv1.3 are enabled and it is highly recommended + # that older formally deprecated versions are kept disabled to reduce the attack surface. + # You can explicitly specify TLS versions to support. + # Allowed values are case insensitive and include "TLSv1", "TLSv1.1", "TLSv1.2", + # "TLSv1.3" (OpenSSL >= 1.1.1) or any combination. + # To enable only TLSv1.2 and TLSv1.3, use: + # + # tls-protocols "TLSv1.2 TLSv1.3" + + # Configure allowed ciphers. See the ciphers(1ssl) manpage for more information + # about the syntax of this string. + # + # Note: this configuration applies only to <= TLSv1.2. + # + # tls-ciphers DEFAULT:!MEDIUM + + # Configure allowed TLSv1.3 ciphersuites. See the ciphers(1ssl) manpage for more + # information about the syntax of this string, and specifically for TLSv1.3 + # ciphersuites. + # + # tls-ciphersuites TLS_CHACHA20_POLY1305_SHA256 + + # When choosing a cipher, use the server's preference instead of the client + # preference. By default, the server follows the client's preference. + # + # tls-prefer-server-ciphers yes + + # By default, TLS session caching is enabled to allow faster and less expensive + # reconnections by clients that support it. Use the following directive to disable + # caching. + # + # tls-session-caching no + + # Change the default number of TLS sessions cached. A zero value sets the cache + # to unlimited size. The default size is 20480. + # + # tls-session-cache-size 5000 + + # Change the default timeout of cached TLS sessions. The default timeout is 300 + # seconds. + # + # tls-session-cache-timeout 60 + + ################################# GENERAL ##################################### + + # By default Valkey does not run as a daemon. Use 'yes' if you need it. + # Note that Valkey will write a pid file in /var/run/valkey.pid when daemonized. + # When Valkey is supervised by upstart or systemd, this parameter has no impact. + daemonize no + + # If you run Valkey from upstart or systemd, Valkey can interact with your + # supervision tree. Options: + # supervised no - no supervision interaction + # supervised upstart - signal upstart by putting Valkey into SIGSTOP mode + # requires "expect stop" in your upstart job config + # supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET + # on startup, and updating Valkey status on a regular + # basis. + # supervised auto - detect upstart or systemd method based on + # UPSTART_JOB or NOTIFY_SOCKET environment variables + # Note: these supervision methods only signal "process is ready." + # They do not enable continuous pings back to your supervisor. + # + # The default is "no". To run under upstart/systemd, you can simply uncomment + # the line below: + # + # supervised auto + + # If a pid file is specified, Valkey writes it where specified at startup + # and removes it at exit. + # + # When the server runs non daemonized, no pid file is created if none is + # specified in the configuration. When the server is daemonized, the pid file + # is used even if not specified, defaulting to "/var/run/valkey.pid". + # + # Creating a pid file is best effort: if Valkey is not able to create it + # nothing bad happens, the server will start and run normally. + # + # Note that on modern Linux systems "/run/valkey.pid" is more conforming + # and should be used instead. + pidfile /opt/bitnami/valkey/tmp/valkey_6379.pid + + # Specify the server verbosity level. + # This can be one of: + # debug (a lot of information, useful for development/testing) + # verbose (many rarely useful info, but not a mess like the debug level) + # notice (moderately verbose, what you want in production probably) + # warning (only very important / critical messages are logged) + loglevel notice + + # Specify the log file name. Also the empty string can be used to force + # Valkey to log on the standard output. Note that if you use standard + # output for logging but daemonize, logs will be sent to /dev/null + logfile "" + + # To enable logging to the system logger, just set 'syslog-enabled' to yes, + # and optionally update the other syslog parameters to suit your needs. + # syslog-enabled no + + # Specify the syslog identity. + # syslog-ident valkey + + # Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7. + # syslog-facility local0 + + # To disable the built in crash log, which will possibly produce cleaner core + # dumps when they are needed, uncomment the following: + # + # crash-log-enabled no + + # To disable the fast memory check that's run as part of the crash log, which + # will possibly let valkey terminate sooner, uncomment the following: + # + # crash-memcheck-enabled no + + # Set the number of databases. The default database is DB 0, you can select + # a different one on a per-connection basis using SELECT where + # dbid is a number between 0 and 'databases'-1 + databases 16 + + # By default Valkey shows an ASCII art logo only when started to log to the + # standard output and if the standard output is a TTY and syslog logging is + # disabled. Basically this means that normally a logo is displayed only in + # interactive sessions. + # + # However it is possible to force the pre-4.0 behavior and always show a + # ASCII art logo in startup logs by setting the following option to yes. + always-show-logo yes + + # By default, Valkey modifies the process title (as seen in 'top' and 'ps') to + # provide some runtime information. It is possible to disable this and leave + # the process name as executed by setting the following to no. + set-proc-title yes + + # When changing the process title, Valkey uses the following template to construct + # the modified title. + # + # Template variables are specified in curly brackets. The following variables are + # supported: + # + # {title} Name of process as executed if parent, or type of child process. + # {listen-addr} Bind address or '*' followed by TCP or TLS port listening on, or + # Unix socket if only that's available. + # {server-mode} Special mode, i.e. "[sentinel]" or "[cluster]". + # {port} TCP port listening on, or 0. + # {tls-port} TLS port listening on, or 0. + # {unixsocket} Unix domain socket listening on, or "". + # {config-file} Name of configuration file used. + # + proc-title-template "{title} {listen-addr} {server-mode}" + + ################################ SNAPSHOTTING ################################ + + # Save the DB to disk. + # + # save [ ...] + # + # Valkey will save the DB if the given number of seconds elapsed and it + # surpassed the given number of write operations against the DB. + # + # Snapshotting can be completely disabled with a single empty string argument + # as in following example: + # + # save "" + # + # Unless specified otherwise, by default Valkey will save the DB: + # * After 3600 seconds (an hour) if at least 1 change was performed + # * After 300 seconds (5 minutes) if at least 100 changes were performed + # * After 60 seconds if at least 10000 changes were performed + # + # You can set these explicitly by uncommenting the following line. + # + # save 3600 1 300 100 60 10000 + save 900 1 300 10 60 10000 + # By default Valkey will stop accepting writes if RDB snapshots are enabled + # (at least one save point) and the latest background save failed. + # This will make the user aware (in a hard way) that data is not persisting + # on disk properly, otherwise chances are that no one will notice and some + # disaster will happen. + # + # If the background saving process will start working again Valkey will + # automatically allow writes again. + # + # However if you have setup your proper monitoring of the Valkey server + # and persistence, you may want to disable this feature so that Valkey will + # continue to work as usual even if there are problems with disk, + # permissions, and so forth. + stop-writes-on-bgsave-error yes + + # Compress string objects using LZF when dump .rdb databases? + # By default compression is enabled as it's almost always a win. + # If you want to save some CPU in the saving child set it to 'no' but + # the dataset will likely be bigger if you have compressible values or keys. + rdbcompression yes + + # Since version 5 of RDB a CRC64 checksum is placed at the end of the file. + # This makes the format more resistant to corruption but there is a performance + # hit to pay (around 10%) when saving and loading RDB files, so you can disable it + # for maximum performances. + # + # RDB files created with checksum disabled have a checksum of zero that will + # tell the loading code to skip the check. + rdbchecksum yes + + # Enables or disables full sanitization checks for ziplist and listpack etc when + # loading an RDB or RESTORE payload. This reduces the chances of a assertion or + # crash later on while processing commands. + # Options: + # no - Never perform full sanitization + # yes - Always perform full sanitization + # clients - Perform full sanitization only for user connections. + # Excludes: RDB files, RESTORE commands received from the primary + # connection, and client connections which have the + # skip-sanitize-payload ACL flag. + # The default should be 'clients' but since it currently affects cluster + # resharding via MIGRATE, it is temporarily set to 'no' by default. + # + # sanitize-dump-payload no + + # The filename where to dump the DB + dbfilename dump.rdb + + # Remove RDB files used by replication in instances without persistence + # enabled. By default this option is disabled, however there are environments + # where for regulations or other security concerns, RDB files persisted on + # disk by primarys in order to feed replicas, or stored on disk by replicas + # in order to load them for the initial synchronization, should be deleted + # ASAP. Note that this option ONLY WORKS in instances that have both AOF + # and RDB persistence disabled, otherwise is completely ignored. + # + # An alternative (and sometimes better) way to obtain the same effect is + # to use diskless replication on both primary and replicas instances. However + # in the case of replicas, diskless is not always an option. + rdb-del-sync-files no + + # The working directory. + # + # The DB will be written inside this directory, with the filename specified + # above using the 'dbfilename' configuration directive. + # + # The Append Only File will also be created inside this directory. + # + # Note that you must specify a directory here, not a file name. + dir /bitnami/valkey/data + + ################################# REPLICATION ################################# + + # Primary-Replica replication. Use replicaof to make a Valkey instance a copy of + # another Valkey server. A few things to understand ASAP about Valkey replication. + # + # +------------------+ +---------------+ + # | Primary | ---> | Replica | + # | (receive writes) | | (exact copy) | + # +------------------+ +---------------+ + # + # 1) Valkey replication is asynchronous, but you can configure a primary to + # stop accepting writes if it appears to be not connected with at least + # a given number of replicas. + # 2) Valkey replicas are able to perform a partial resynchronization with the + # primary if the replication link is lost for a relatively small amount of + # time. You may want to configure the replication backlog size (see the next + # sections of this file) with a sensible value depending on your needs. + # 3) Replication is automatic and does not need user intervention. After a + # network partition replicas automatically try to reconnect to primarys + # and resynchronize with them. + # + # replicaof + + # If the primary is password protected (using the "requirepass" configuration + # directive below) it is possible to tell the replica to authenticate before + # starting the replication synchronization process, otherwise the primary will + # refuse the replica request. + # + # primaryauth + # + # However this is not enough if you are using Valkey ACLs (for Valkey version + # 6 or greater), and the default user is not capable of running the PSYNC + # command and/or other commands needed for replication. In this case it's + # better to configure a special user to use with replication, and specify the + # primaryuser configuration as such: + # + # primaryuser + # + # When primaryuser is specified, the replica will authenticate against its + # primary using the new AUTH form: AUTH . + + # When a replica loses its connection with the primary, or when the replication + # is still in progress, the replica can act in two different ways: + # + # 1) if replica-serve-stale-data is set to 'yes' (the default) the replica will + # still reply to client requests, possibly with out of date data, or the + # data set may just be empty if this is the first synchronization. + # + # 2) If replica-serve-stale-data is set to 'no' the replica will reply with error + # "MASTERDOWN Link with MASTER is down and replica-serve-stale-data is set to 'no'" + # to all data access commands, excluding commands such as: + # INFO, REPLICAOF, AUTH, SHUTDOWN, REPLCONF, ROLE, CONFIG, SUBSCRIBE, + # UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBLISH, PUBSUB, COMMAND, POST, + # HOST and LATENCY. + # + replica-serve-stale-data yes + + # You can configure a replica instance to accept writes or not. Writing against + # a replica instance may be useful to store some ephemeral data (because data + # written on a replica will be easily deleted after resync with the primary) but + # may also cause problems if clients are writing to it because of a + # misconfiguration. + # + # In Vakey by default replicas are read-only. + # + # Note: read only replicas are not designed to be exposed to untrusted clients + # on the internet. It's just a protection layer against misuse of the instance. + # Still a read only replica exports by default all the administrative commands + # such as CONFIG, DEBUG, and so forth. To a limited extent you can improve + # security of read only replicas using 'rename-command' to shadow all the + # administrative / dangerous commands. + replica-read-only yes + + # Replication SYNC strategy: disk or socket. + # + # New replicas and reconnecting replicas that are not able to continue the + # replication process just receiving differences, need to do what is called a + # "full synchronization". An RDB file is transmitted from the primary to the + # replicas. + # + # The transmission can happen in two different ways: + # + # 1) Disk-backed: The Valkey primary creates a new process that writes the RDB + # file on disk. Later the file is transferred by the parent + # process to the replicas incrementally. + # 2) Diskless: The Valkey primary creates a new process that directly writes the + # RDB file to replica sockets, without touching the disk at all. + # + # With disk-backed replication, while the RDB file is generated, more replicas + # can be queued and served with the RDB file as soon as the current child + # producing the RDB file finishes its work. With diskless replication instead + # once the transfer starts, new replicas arriving will be queued and a new + # transfer will start when the current one terminates. + # + # When diskless replication is used, the primary waits a configurable amount of + # time (in seconds) before starting the transfer in the hope that multiple + # replicas will arrive and the transfer can be parallelized. + # + # With slow disks and fast (large bandwidth) networks, diskless replication + # works better. + repl-diskless-sync no + + # When diskless replication is enabled, it is possible to configure the delay + # the server waits in order to spawn the child that transfers the RDB via socket + # to the replicas. + # + # This is important since once the transfer starts, it is not possible to serve + # new replicas arriving, that will be queued for the next RDB transfer, so the + # server waits a delay in order to let more replicas arrive. + # + # The delay is specified in seconds, and by default is 5 seconds. To disable + # it entirely just set it to 0 seconds and the transfer will start ASAP. + repl-diskless-sync-delay 5 + + # When diskless replication is enabled with a delay, it is possible to let + # the replication start before the maximum delay is reached if the maximum + # number of replicas expected have connected. Default of 0 means that the + # maximum is not defined and Valkey will wait the full delay. + repl-diskless-sync-max-replicas 0 + + # ----------------------------------------------------------------------------- + # WARNING: RDB diskless load is experimental. Since in this setup the replica + # does not immediately store an RDB on disk, it may cause data loss during + # failovers. RDB diskless load + Valkey modules not handling I/O reads may also + # cause Valkey to abort in case of I/O errors during the initial synchronization + # stage with the primary. Use only if you know what you are doing. + # ----------------------------------------------------------------------------- + # + # Replica can load the RDB it reads from the replication link directly from the + # socket, or store the RDB to a file and read that file after it was completely + # received from the primary. + # + # In many cases the disk is slower than the network, and storing and loading + # the RDB file may increase replication time (and even increase the primary's + # Copy on Write memory and replica buffers). + # However, parsing the RDB file directly from the socket may mean that we have + # to flush the contents of the current database before the full rdb was + # received. For this reason we have the following options: + # + # "disabled" - Don't use diskless load (store the rdb file to the disk first) + # "on-empty-db" - Use diskless load only when it is completely safe. + # "swapdb" - Keep current db contents in RAM while parsing the data directly + # from the socket. Replicas in this mode can keep serving current + # data set while replication is in progress, except for cases where + # they can't recognize primary as having a data set from same + # replication history. + # Note that this requires sufficient memory, if you don't have it, + # you risk an OOM kill. + repl-diskless-load disabled + + # Primary send PINGs to its replicas in a predefined interval. It's possible to + # change this interval with the repl_ping_replica_period option. The default + # value is 10 seconds. + # + # repl-ping-replica-period 10 + + # The following option sets the replication timeout for: + # + # 1) Bulk transfer I/O during SYNC, from the point of view of replica. + # 2) Primary timeout from the point of view of replicas (data, pings). + # 3) Replica timeout from the point of view of primary nodes (REPLCONF ACK pings). + # + # It is important to make sure that this value is greater than the value + # specified for repl-ping-replica-period otherwise a timeout will be detected + # every time there is low traffic between the primary and the replica. The default + # value is 60 seconds. + # + # repl-timeout 60 + + # Disable TCP_NODELAY on the replica socket after SYNC? + # + # If you select "yes" Valkey will use a smaller number of TCP packets and + # less bandwidth to send data to replicas. But this can add a delay for + # the data to appear on the replica side, up to 40 milliseconds with + # Linux kernels using a default configuration. + # + # If you select "no" the delay for data to appear on the replica side will + # be reduced but more bandwidth will be used for replication. + # + # By default we optimize for low latency, but in very high traffic conditions + # or when the primary and replicas are many hops away, turning this to "yes" may + # be a good idea. + repl-disable-tcp-nodelay no + + # Set the replication backlog size. The backlog is a buffer that accumulates + # replica data when replicas are disconnected for some time, so that when a + # replica wants to reconnect again, often a full resync is not needed, but a + # partial resync is enough, just passing the portion of data the replica + # missed while disconnected. + # + # The bigger the replication backlog, the longer the replica can endure the + # disconnect and later be able to perform a partial resynchronization. + # + # The backlog is only allocated if there is at least one replica connected. + # + # repl-backlog-size 1mb + + # After a primary has no connected replicas for some time, the backlog will be + # freed. The following option configures the amount of seconds that need to + # elapse, starting from the time the last replica disconnected, for the backlog + # buffer to be freed. + # + # Note that replicas never free the backlog for timeout, since they may be + # promoted to primarys later, and should be able to correctly "partially + # resynchronize" with other replicas: hence they should always accumulate backlog. + # + # A value of 0 means to never release the backlog. + # + # repl-backlog-ttl 3600 + + # The replica priority is an integer number published by Valkey in the INFO + # output. It is used by Valkey Sentinel in order to select a replica to promote + # into a primary if the primary is no longer working correctly. + # + # A replica with a low priority number is considered better for promotion, so + # for instance if there are three replicas with priority 10, 100, 25 Sentinel + # will pick the one with priority 10, that is the lowest. + # + # However a special priority of 0 marks the replica as not able to perform the + # role of primary, so a replica with priority of 0 will never be selected by + # Valkey Sentinel for promotion. + # + # By default the priority is 100. + replica-priority 100 + + # The propagation error behavior controls how Valkey will behave when it is + # unable to handle a command being processed in the replication stream from a primary + # or processed while reading from an AOF file. Errors that occur during propagation + # are unexpected, and can cause data inconsistency. However, there are edge cases + # in earlier versions of Valkey where it was possible for the server to replicate or persist + # commands that would fail on future versions. For this reason the default behavior + # is to ignore such errors and continue processing commands. + # + # If an application wants to ensure there is no data divergence, this configuration + # should be set to 'panic' instead. The value can also be set to 'panic-on-replicas' + # to only panic when a replica encounters an error on the replication stream. One of + # these two panic values will become the default value in the future once there are + # sufficient safety mechanisms in place to prevent false positive crashes. + # + # propagation-error-behavior ignore + + # Replica ignore disk write errors controls the behavior of a replica when it is + # unable to persist a write command received from its primary to disk. By default, + # this configuration is set to 'no' and will crash the replica in this condition. + # It is not recommended to change this default, however in order to be compatible + # with older versions of Valkey this config can be toggled to 'yes' which will just + # log a warning and execute the write command it got from the primary. + # + # replica-ignore-disk-write-errors no + + # ----------------------------------------------------------------------------- + # By default, Valkey Sentinel includes all replicas in its reports. A replica + # can be excluded from Valkey Sentinel's announcements. An unannounced replica + # will be ignored by the 'sentinel replicas ' command and won't be + # exposed to Valkey Sentinel's clients. + # + # This option does not change the behavior of replica-priority. Even with + # replica-announced set to 'no', the replica can be promoted to primary. To + # prevent this behavior, set replica-priority to 0. + # + # replica-announced yes + + # It is possible for a primary to stop accepting writes if there are less than + # N replicas connected, having a lag less or equal than M seconds. + # + # The N replicas need to be in "online" state. + # + # The lag in seconds, that must be <= the specified value, is calculated from + # the last ping received from the replica, that is usually sent every second. + # + # This option does not GUARANTEE that N replicas will accept the write, but + # will limit the window of exposure for lost writes in case not enough replicas + # are available, to the specified number of seconds. + # + # For example to require at least 3 replicas with a lag <= 10 seconds use: + # + # min-replicas-to-write 3 + # min-replicas-max-lag 10 + # + # Setting one or the other to 0 disables the feature. + # + # By default min-replicas-to-write is set to 0 (feature disabled) and + # min-replicas-max-lag is set to 10. + + # A Valkey primary is able to list the address and port of the attached + # replicas in different ways. For example the "INFO replication" section + # offers this information, which is used, among other tools, by + # Valkey Sentinel in order to discover replica instances. + # Another place where this info is available is in the output of the + # "ROLE" command of a primary. + # + # The listed IP address and port normally reported by a replica is + # obtained in the following way: + # + # IP: The address is auto detected by checking the peer address + # of the socket used by the replica to connect with the primary. + # + # Port: The port is communicated by the replica during the replication + # handshake, and is normally the port that the replica is using to + # listen for connections. + # + # However when port forwarding or Network Address Translation (NAT) is + # used, the replica may actually be reachable via different IP and port + # pairs. The following two options can be used by a replica in order to + # report to its primary a specific set of IP and port, so that both INFO + # and ROLE will report those values. + # + # There is no need to use both the options if you need to override just + # the port or the IP address. + # + # replica-announce-ip 5.5.5.5 + # replica-announce-port 1234 + + ############################### KEYS TRACKING ################################# + + # Valkey implements server assisted support for client side caching of values. + # This is implemented using an invalidation table that remembers, using + # a radix key indexed by key name, what clients have which keys. In turn + # this is used in order to send invalidation messages to clients. + # + # When tracking is enabled for a client, all the read only queries are assumed + # to be cached: this will force Valkey to store information in the invalidation + # table. When keys are modified, such information is flushed away, and + # invalidation messages are sent to the clients. However if the workload is + # heavily dominated by reads, Valkey could use more and more memory in order + # to track the keys fetched by many clients. + # + # For this reason it is possible to configure a maximum fill value for the + # invalidation table. By default it is set to 1M of keys, and once this limit + # is reached, Valkey will start to evict keys in the invalidation table + # even if they were not modified, just to reclaim memory: this will in turn + # force the clients to invalidate the cached values. Basically the table + # maximum size is a trade off between the memory you want to spend server + # side to track information about who cached what, and the ability of clients + # to retain cached objects in memory. + # + # If you set the value to 0, it means there are no limits, and Valkey will + # retain as many keys as needed in the invalidation table. + # In the "stats" INFO section, you can find information about the number of + # keys in the invalidation table at every given moment. + # + # Note: when key tracking is used in broadcasting mode, no memory is used + # in the server side so this setting is useless. + # + # tracking-table-max-keys 1000000 + + ################################## SECURITY ################################### + + # Warning: since Valkey is pretty fast, an outside user can try up to + # 1 million passwords per second against a modern box. This means that you + # should use very strong passwords, otherwise they will be very easy to break. + # Note that because the password is really a shared secret between the client + # and the server, and should not be memorized by any human, the password + # can be easily a long string from /dev/urandom or whatever, so by using a + # long and unguessable password no brute force attack will be possible. + + # Valkey ACL users are defined in the following format: + # + # user ... acl rules ... + # + # For example: + # + # user worker +@list +@connection ~jobs:* on >ffa9203c493aa99 + # + # The special username "default" is used for new connections. If this user + # has the "nopass" rule, then new connections will be immediately authenticated + # as the "default" user without the need of any password provided via the + # AUTH command. Otherwise if the "default" user is not flagged with "nopass" + # the connections will start in not authenticated state, and will require + # AUTH (or the HELLO command AUTH option) in order to be authenticated and + # start to work. + # + # The ACL rules that describe what a user can do are the following: + # + # on Enable the user: it is possible to authenticate as this user. + # off Disable the user: it's no longer possible to authenticate + # with this user, however the already authenticated connections + # will still work. + # skip-sanitize-payload RESTORE dump-payload sanitization is skipped. + # sanitize-payload RESTORE dump-payload is sanitized (default). + # + Allow the execution of that command. + # May be used with `|` for allowing subcommands (e.g "+config|get") + # - Disallow the execution of that command. + # May be used with `|` for blocking subcommands (e.g "-config|set") + # +@ Allow the execution of all the commands in such category + # with valid categories are like @admin, @set, @sortedset, ... + # and so forth, see the full list in the server.c file where + # the Valkey command table is described and defined. + # The special category @all means all the commands, but currently + # present in the server, and that will be loaded in the future + # via modules. + # +|first-arg Allow a specific first argument of an otherwise + # disabled command. It is only supported on commands with + # no sub-commands, and is not allowed as negative form + # like -SELECT|1, only additive starting with "+". This + # feature is deprecated and may be removed in the future. + # allcommands Alias for +@all. Note that it implies the ability to execute + # all the future commands loaded via the modules system. + # nocommands Alias for -@all. + # ~ Add a pattern of keys that can be mentioned as part of + # commands. For instance ~* allows all the keys. The pattern + # is a glob-style pattern like the one of KEYS. + # It is possible to specify multiple patterns. + # %R~ Add key read pattern that specifies which keys can be read + # from. + # %W~ Add key write pattern that specifies which keys can be + # written to. + # allkeys Alias for ~* + # resetkeys Flush the list of allowed keys patterns. + # & Add a glob-style pattern of Pub/Sub channels that can be + # accessed by the user. It is possible to specify multiple channel + # patterns. + # allchannels Alias for &* + # resetchannels Flush the list of allowed channel patterns. + # > Add this password to the list of valid password for the user. + # For example >mypass will add "mypass" to the list. + # This directive clears the "nopass" flag (see later). + # < Remove this password from the list of valid passwords. + # nopass All the set passwords of the user are removed, and the user + # is flagged as requiring no password: it means that every + # password will work against this user. If this directive is + # used for the default user, every new connection will be + # immediately authenticated with the default user without + # any explicit AUTH command required. Note that the "resetpass" + # directive will clear this condition. + # resetpass Flush the list of allowed passwords. Moreover removes the + # "nopass" status. After "resetpass" the user has no associated + # passwords and there is no way to authenticate without adding + # some password (or setting it as "nopass" later). + # reset Performs the following actions: resetpass, resetkeys, off, + # -@all. The user returns to the same state it has immediately + # after its creation. + # () Create a new selector with the options specified within the + # parentheses and attach it to the user. Each option should be + # space separated. The first character must be ( and the last + # character must be ). + # clearselectors Remove all of the currently attached selectors. + # Note this does not change the "root" user permissions, + # which are the permissions directly applied onto the + # user (outside the parentheses). + # + # ACL rules can be specified in any order: for instance you can start with + # passwords, then flags, or key patterns. However note that the additive + # and subtractive rules will CHANGE MEANING depending on the ordering. + # For instance see the following example: + # + # user alice on +@all -DEBUG ~* >somepassword + # + # This will allow "alice" to use all the commands with the exception of the + # DEBUG command, since +@all added all the commands to the set of the commands + # alice can use, and later DEBUG was removed. However if we invert the order + # of two ACL rules the result will be different: + # + # user alice on -DEBUG +@all ~* >somepassword + # + # Now DEBUG was removed when alice had yet no commands in the set of allowed + # commands, later all the commands are added, so the user will be able to + # execute everything. + # + # Basically ACL rules are processed left-to-right. + # + # The following is a list of command categories and their meanings: + # * keyspace - Writing or reading from keys, databases, or their metadata + # in a type agnostic way. Includes DEL, RESTORE, DUMP, RENAME, EXISTS, DBSIZE, + # KEYS, EXPIRE, TTL, FLUSHALL, etc. Commands that may modify the keyspace, + # key or metadata will also have `write` category. Commands that only read + # the keyspace, key or metadata will have the `read` category. + # * read - Reading from keys (values or metadata). Note that commands that don't + # interact with keys, will not have either `read` or `write`. + # * write - Writing to keys (values or metadata) + # * admin - Administrative commands. Normal applications will never need to use + # these. Includes REPLICAOF, CONFIG, DEBUG, SAVE, MONITOR, ACL, SHUTDOWN, etc. + # * dangerous - Potentially dangerous (each should be considered with care for + # various reasons). This includes FLUSHALL, MIGRATE, RESTORE, SORT, KEYS, + # CLIENT, DEBUG, INFO, CONFIG, SAVE, REPLICAOF, etc. + # * connection - Commands affecting the connection or other connections. + # This includes AUTH, SELECT, COMMAND, CLIENT, ECHO, PING, etc. + # * blocking - Potentially blocking the connection until released by another + # command. + # * fast - Fast O(1) commands. May loop on the number of arguments, but not the + # number of elements in the key. + # * slow - All commands that are not Fast. + # * pubsub - PUBLISH / SUBSCRIBE related + # * transaction - WATCH / MULTI / EXEC related commands. + # * scripting - Scripting related. + # * set - Data type: sets related. + # * sortedset - Data type: zsets related. + # * list - Data type: lists related. + # * hash - Data type: hashes related. + # * string - Data type: strings related. + # * bitmap - Data type: bitmaps related. + # * hyperloglog - Data type: hyperloglog related. + # * geo - Data type: geo related. + # * stream - Data type: streams related. + # + # For more information about ACL configuration please refer to + # the Valkey web site at https://valkey.io/docs/topics/acl/ + + # ACL LOG + # + # The ACL Log tracks failed commands and authentication events associated + # with ACLs. The ACL Log is useful to troubleshoot failed commands blocked + # by ACLs. The ACL Log is stored in memory. You can reclaim memory with + # ACL LOG RESET. Define the maximum entry length of the ACL Log below. + acllog-max-len 128 + + # Using an external ACL file + # + # Instead of configuring users here in this file, it is possible to use + # a stand-alone file just listing users. The two methods cannot be mixed: + # if you configure users here and at the same time you activate the external + # ACL file, the server will refuse to start. + # + # The format of the external ACL user file is exactly the same as the + # format that is used inside valkey.conf to describe users. + # + # aclfile /etc/valkey/users.acl + + # The option effect will be just setting the password for the default user. + # Clients will still authenticate using AUTH as usually, or more + # explicitly with AUTH default if they follow the new protocol: + # both will work. + # + # The requirepass is not compatible with aclfile option and the ACL LOAD + # command, these will cause requirepass to be ignored. + # + # requirepass foobared + + # New users are initialized with restrictive permissions by default, via the + # equivalent of this ACL rule 'off resetkeys -@all'. It + # is possible to manage access to Pub/Sub channels with ACL rules as well. The + # default Pub/Sub channels permission if new users is controlled by the + # acl-pubsub-default configuration directive, which accepts one of these values: + # + # allchannels: grants access to all Pub/Sub channels + # resetchannels: revokes access to all Pub/Sub channels + # + # acl-pubsub-default resetchannels + + # Command renaming (DEPRECATED). + # + # ------------------------------------------------------------------------ + # WARNING: avoid using this option if possible. Instead use ACLs to remove + # commands from the default user, and put them only in some admin user you + # create for administrative purposes. + # ------------------------------------------------------------------------ + # + # It is possible to change the name of dangerous commands in a shared + # environment. For instance the CONFIG command may be renamed into something + # hard to guess so that it will still be available for internal-use tools + # but not available for general clients. + # + # Example: + # + # rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52 + # + # It is also possible to completely kill a command by renaming it into + # an empty string: + # + # rename-command CONFIG "" + # + # Please note that changing the name of commands that are logged into the + # AOF file or transmitted to replicas may cause problems. + + ################################### CLIENTS #################################### + + # Set the max number of connected clients at the same time. By default + # this limit is set to 10000 clients, however if the Valkey server is not + # able to configure the process file limit to allow for the specified limit + # the max number of allowed clients is set to the current file limit + # minus 32 (as Valkey reserves a few file descriptors for internal uses). + # + # Once the limit is reached Valkey will close all the new connections sending + # an error 'max number of clients reached'. + # + # IMPORTANT: When Valkey Cluster is used, the max number of connections is also + # shared with the cluster bus: every node in the cluster will use two + # connections, one incoming and another outgoing. It is important to size the + # limit accordingly in case of very large clusters. + # + # maxclients 10000 + + ############################## MEMORY MANAGEMENT ################################ + + # Set a memory usage limit to the specified amount of bytes. + # When the memory limit is reached Valkey will try to remove keys + # according to the eviction policy selected (see maxmemory-policy). + # + # If Valkey can't remove keys according to the policy, or if the policy is + # set to 'noeviction', Valkey will start to reply with errors to commands + # that would use more memory, like SET, LPUSH, and so on, and will continue + # to reply to read-only commands like GET. + # + # This option is usually useful when using Valkey as an LRU or LFU cache, or to + # set a hard memory limit for an instance (using the 'noeviction' policy). + # + # WARNING: If you have replicas attached to an instance with maxmemory on, + # the size of the output buffers needed to feed the replicas are subtracted + # from the used memory count, so that network problems / resyncs will + # not trigger a loop where keys are evicted, and in turn the output + # buffer of replicas is full with DELs of keys evicted triggering the deletion + # of more keys, and so forth until the database is completely emptied. + # + # In short... if you have replicas attached it is suggested that you set a lower + # limit for maxmemory so that there is some free RAM on the system for replica + # output buffers (but this is not needed if the policy is 'noeviction'). + # + # maxmemory + + # MAXMEMORY POLICY: how Valkey will select what to remove when maxmemory + # is reached. You can select one from the following behaviors: + # + # volatile-lru -> Evict using approximated LRU, only keys with an expire set. + # allkeys-lru -> Evict any key using approximated LRU. + # volatile-lfu -> Evict using approximated LFU, only keys with an expire set. + # allkeys-lfu -> Evict any key using approximated LFU. + # volatile-random -> Remove a random key having an expire set. + # allkeys-random -> Remove a random key, any key. + # volatile-ttl -> Remove the key with the nearest expire time (minor TTL) + # noeviction -> Don't evict anything, just return an error on write operations. + # + # LRU means Least Recently Used + # LFU means Least Frequently Used + # + # Both LRU, LFU and volatile-ttl are implemented using approximated + # randomized algorithms. + # + # Note: with any of the above policies, when there are no suitable keys for + # eviction, Valkey will return an error on write operations that require + # more memory. These are usually commands that create new keys, add data or + # modify existing keys. A few examples are: SET, INCR, HSET, LPUSH, SUNIONSTORE, + # SORT (due to the STORE argument), and EXEC (if the transaction includes any + # command that requires memory). + # + # The default is: + # + # maxmemory-policy noeviction + + # LRU, LFU and minimal TTL algorithms are not precise algorithms but approximated + # algorithms (in order to save memory), so you can tune it for speed or + # accuracy. By default Valkey will check five keys and pick the one that was + # used least recently, you can change the sample size using the following + # configuration directive. + # + # The default of 5 produces good enough results. 10 Approximates very closely + # true LRU but costs more CPU. 3 is faster but not very accurate. + # + # maxmemory-samples 5 + + # Eviction processing is designed to function well with the default setting. + # If there is an unusually large amount of write traffic, this value may need to + # be increased. Decreasing this value may reduce latency at the risk of + # eviction processing effectiveness + # 0 = minimum latency, 10 = default, 100 = process without regard to latency + # + # maxmemory-eviction-tenacity 10 + + # By default a replica will ignore its maxmemory setting + # (unless it is promoted to primary after a failover or manually). It means + # that the eviction of keys will be just handled by the primary, sending the + # DEL commands to the replica as keys evict in the primary side. + # + # This behavior ensures that primarys and replicas stay consistent, and is usually + # what you want, however if your replica is writable, or you want the replica + # to have a different memory setting, and you are sure all the writes performed + # to the replica are idempotent, then you may change this default (but be sure + # to understand what you are doing). + # + # Note that since the replica by default does not evict, it may end using more + # memory than the one set via maxmemory (there are certain buffers that may + # be larger on the replica, or data structures may sometimes take more memory + # and so forth). So make sure you monitor your replicas and make sure they + # have enough memory to never hit a real out-of-memory condition before the + # primary hits the configured maxmemory setting. + # + # replica-ignore-maxmemory yes + + # Valkey reclaims expired keys in two ways: upon access when those keys are + # found to be expired, and also in background, in what is called the + # "active expire key". The key space is slowly and interactively scanned + # looking for expired keys to reclaim, so that it is possible to free memory + # of keys that are expired and will never be accessed again in a short time. + # + # The default effort of the expire cycle will try to avoid having more than + # ten percent of expired keys still in memory, and will try to avoid consuming + # more than 25% of total memory and to add latency to the system. However + # it is possible to increase the expire "effort" that is normally set to + # "1", to a greater value, up to the value "10". At its maximum value the + # system will use more CPU, longer cycles (and technically may introduce + # more latency), and will tolerate less already expired keys still present + # in the system. It's a tradeoff between memory, CPU and latency. + # + # active-expire-effort 1 + + ############################# LAZY FREEING #################################### + + # Valkey has two primitives to delete keys. One is called DEL and is a blocking + # deletion of the object. It means that the server stops processing new commands + # in order to reclaim all the memory associated with an object in a synchronous + # way. If the key deleted is associated with a small object, the time needed + # in order to execute the DEL command is very small and comparable to most other + # O(1) or O(log_N) commands in Valkey. However if the key is associated with an + # aggregated value containing millions of elements, the server can block for + # a long time (even seconds) in order to complete the operation. + # + # For the above reasons Valkey also offers non blocking deletion primitives + # such as UNLINK (non blocking DEL) and the ASYNC option of FLUSHALL and + # FLUSHDB commands, in order to reclaim memory in background. Those commands + # are executed in constant time. Another thread will incrementally free the + # object in the background as fast as possible. + # + # DEL, UNLINK and ASYNC option of FLUSHALL and FLUSHDB are user-controlled. + # It's up to the design of the application to understand when it is a good + # idea to use one or the other. However the Valkey server sometimes has to + # delete keys or flush the whole database as a side effect of other operations. + # Specifically Valkey deletes objects independently of a user call in the + # following scenarios: + # + # 1) On eviction, because of the maxmemory and maxmemory policy configurations, + # in order to make room for new data, without going over the specified + # memory limit. + # 2) Because of expire: when a key with an associated time to live (see the + # EXPIRE command) must be deleted from memory. + # 3) Because of a side effect of a command that stores data on a key that may + # already exist. For example the RENAME command may delete the old key + # content when it is replaced with another one. Similarly SUNIONSTORE + # or SORT with STORE option may delete existing keys. The SET command + # itself removes any old content of the specified key in order to replace + # it with the specified string. + # 4) During replication, when a replica performs a full resynchronization with + # its primary, the content of the whole database is removed in order to + # load the RDB file just transferred. + # + # In all the above cases the default is to delete objects in a blocking way, + # like if DEL was called. However you can configure each case specifically + # in order to instead release memory in a non-blocking way like if UNLINK + # was called, using the following configuration directives. + + lazyfree-lazy-eviction no + lazyfree-lazy-expire no + lazyfree-lazy-server-del no + replica-lazy-flush no + + # It is also possible, for the case when to replace the user code DEL calls + # with UNLINK calls is not easy, to modify the default behavior of the DEL + # command to act exactly like UNLINK, using the following configuration + # directive: + + lazyfree-lazy-user-del no + + # FLUSHDB, FLUSHALL, SCRIPT FLUSH and FUNCTION FLUSH support both asynchronous and synchronous + # deletion, which can be controlled by passing the [SYNC|ASYNC] flags into the + # commands. When neither flag is passed, this directive will be used to determine + # if the data should be deleted asynchronously. + + lazyfree-lazy-user-flush no + + ################################ THREADED I/O ################################# + + # Valkey is mostly single threaded, however there are certain threaded + # operations such as UNLINK, slow I/O accesses and other things that are + # performed on side threads. + # + # Now it is also possible to handle Valkey clients socket reads and writes + # in different I/O threads. Since especially writing is so slow, normally + # Valkey users use pipelining in order to speed up the Valkey performances per + # core, and spawn multiple instances in order to scale more. Using I/O + # threads it is possible to easily speedup two times Valkey without resorting + # to pipelining nor sharding of the instance. + # + # By default threading is disabled, we suggest enabling it only in machines + # that have at least 4 or more cores, leaving at least one spare core. + # Using more than 8 threads is unlikely to help much. We also recommend using + # threaded I/O only if you actually have performance problems, with Valkey + # instances being able to use a quite big percentage of CPU time, otherwise + # there is no point in using this feature. + # + # So for instance if you have a four cores boxes, try to use 2 or 3 I/O + # threads, if you have a 8 cores, try to use 6 threads. In order to + # enable I/O threads use the following configuration directive: + # + # io-threads 4 + # + # Setting io-threads to 1 will just use the main thread as usual. + # When I/O threads are enabled, we only use threads for writes, that is + # to thread the write(2) syscall and transfer the client buffers to the + # socket. However it is also possible to enable threading of reads and + # protocol parsing using the following configuration directive, by setting + # it to yes: + # + # io-threads-do-reads no + # + # Usually threading reads doesn't help much. + # + # NOTE 1: This configuration directive cannot be changed at runtime via + # CONFIG SET. Also, this feature currently does not work when SSL is + # enabled. + # + # NOTE 2: If you want to test the Valkey speedup using valkey-benchmark, make + # sure you also run the benchmark itself in threaded mode, using the + # --threads option to match the number of Valkey threads, otherwise you'll not + # be able to notice the improvements. + + ############################ KERNEL OOM CONTROL ############################## + + # On Linux, it is possible to hint the kernel OOM killer on what processes + # should be killed first when out of memory. + # + # Enabling this feature makes Valkey actively control the oom_score_adj value + # for all its processes, depending on their role. The default scores will + # attempt to have background child processes killed before all others, and + # replicas killed before primarys. + # + # Valkey supports these options: + # + # no: Don't make changes to oom-score-adj (default). + # yes: Alias to "relative" see below. + # absolute: Values in oom-score-adj-values are written as is to the kernel. + # relative: Values are used relative to the initial value of oom_score_adj when + # the server starts and are then clamped to a range of -1000 to 1000. + # Because typically the initial value is 0, they will often match the + # absolute values. + oom-score-adj no + + # When oom-score-adj is used, this directive controls the specific values used + # for primary, replica and background child processes. Values range -2000 to + # 2000 (higher means more likely to be killed). + # + # Unprivileged processes (not root, and without CAP_SYS_RESOURCE capabilities) + # can freely increase their value, but not decrease it below its initial + # settings. This means that setting oom-score-adj to "relative" and setting the + # oom-score-adj-values to positive values will always succeed. + oom-score-adj-values 0 200 800 + + + #################### KERNEL transparent hugepage CONTROL ###################### + + # Usually the kernel Transparent Huge Pages control is set to "madvise" or + # or "never" by default (/sys/kernel/mm/transparent_hugepage/enabled), in which + # case this config has no effect. On systems in which it is set to "always", + # valkey will attempt to disable it specifically for the valkey process in order + # to avoid latency problems specifically with fork(2) and CoW. + # If for some reason you prefer to keep it enabled, you can set this config to + # "no" and the kernel global to "always". + + disable-thp yes + + ############################## APPEND ONLY MODE ############################### + + # By default Valkey asynchronously dumps the dataset on disk. This mode is + # good enough in many applications, but an issue with the Valkey process or + # a power outage may result into a few minutes of writes lost (depending on + # the configured save points). + # + # The Append Only File is an alternative persistence mode that provides + # much better durability. For instance using the default data fsync policy + # (see later in the config file) Valkey can lose just one second of writes in a + # dramatic event like a server power outage, or a single write if something + # wrong with the Valkey process itself happens, but the operating system is + # still running correctly. + # + # AOF and RDB persistence can be enabled at the same time without problems. + # If the AOF is enabled on startup Valkey will load the AOF, that is the file + # with the better durability guarantees. + # + # Please check https://valkey.io/docs/topics/persistence/ for more information. + + appendonly no + + # The base name of the append only file. + # + # Valkey 7 and newer use a set of append-only files to persist the dataset + # and changes applied to it. There are two basic types of files in use: + # + # - Base files, which are a snapshot representing the complete state of the + # dataset at the time the file was created. Base files can be either in + # the form of RDB (binary serialized) or AOF (textual commands). + # - Incremental files, which contain additional commands that were applied + # to the dataset following the previous file. + # + # In addition, manifest files are used to track the files and the order in + # which they were created and should be applied. + # + # Append-only file names are created by Valkey following a specific pattern. + # The file name's prefix is based on the 'appendfilename' configuration + # parameter, followed by additional information about the sequence and type. + # + # For example, if appendfilename is set to appendonly.aof, the following file + # names could be derived: + # + # - appendonly.aof.1.base.rdb as a base file. + # - appendonly.aof.1.incr.aof, appendonly.aof.2.incr.aof as incremental files. + # - appendonly.aof.manifest as a manifest file. + + appendfilename "appendonly.aof" + + # For convenience, Valkey stores all persistent append-only files in a dedicated + # directory. The name of the directory is determined by the appenddirname + # configuration parameter. + + appenddirname "appendonlydir" + + # The fsync() call tells the Operating System to actually write data on disk + # instead of waiting for more data in the output buffer. Some OS will really flush + # data on disk, some other OS will just try to do it ASAP. + # + # Valkey supports three different modes: + # + # no: don't fsync, just let the OS flush the data when it wants. Faster. + # always: fsync after every write to the append only log. Slow, Safest. + # everysec: fsync only one time every second. Compromise. + # + # The default is "everysec", as that's usually the right compromise between + # speed and data safety. It's up to you to understand if you can relax this to + # "no" that will let the operating system flush the output buffer when + # it wants, for better performances (but if you can live with the idea of + # some data loss consider the default persistence mode that's snapshotting), + # or on the contrary, use "always" that's very slow but a bit safer than + # everysec. + # + # If unsure, use "everysec". + + # appendfsync always + appendfsync everysec + # appendfsync no + + # When the AOF fsync policy is set to always or everysec, and a background + # saving process (a background save or AOF log background rewriting) is + # performing a lot of I/O against the disk, in some Linux configurations + # Valkey may block too long on the fsync() call. Note that there is no fix for + # this currently, as even performing fsync in a different thread will block + # our synchronous write(2) call. + # + # In order to mitigate this problem it's possible to use the following option + # that will prevent fsync() from being called in the main process while a + # BGSAVE or BGREWRITEAOF is in progress. + # + # This means that while another child is saving, the durability of Valkey is + # the same as "appendfsync no". In practical terms, this means that it is + # possible to lose up to 30 seconds of log in the worst scenario (with the + # default Linux settings). + # + # If you have latency problems turn this to "yes". Otherwise leave it as + # "no" that is the safest pick from the point of view of durability. + + no-appendfsync-on-rewrite no + + # Automatic rewrite of the append only file. + # Valkey is able to automatically rewrite the log file implicitly calling + # BGREWRITEAOF when the AOF log size grows by the specified percentage. + # + # This is how it works: Valkey remembers the size of the AOF file after the + # latest rewrite (if no rewrite has happened since the restart, the size of + # the AOF at startup is used). + # + # This base size is compared to the current size. If the current size is + # bigger than the specified percentage, the rewrite is triggered. Also + # you need to specify a minimal size for the AOF file to be rewritten, this + # is useful to avoid rewriting the AOF file even if the percentage increase + # is reached but it is still pretty small. + # + # Specify a percentage of zero in order to disable the automatic AOF + # rewrite feature. + + auto-aof-rewrite-percentage 100 + auto-aof-rewrite-min-size 64mb + + # An AOF file may be found to be truncated at the end during the Valkey + # startup process, when the AOF data gets loaded back into memory. + # This may happen when the system where Valkey is running + # crashes, especially when an ext4 filesystem is mounted without the + # data=ordered option (however this can't happen when Valkey itself + # crashes or aborts but the operating system still works correctly). + # + # Valkey can either exit with an error when this happens, or load as much + # data as possible (the default now) and start if the AOF file is found + # to be truncated at the end. The following option controls this behavior. + # + # If aof-load-truncated is set to yes, a truncated AOF file is loaded and + # the Valkey server starts emitting a log to inform the user of the event. + # Otherwise if the option is set to no, the server aborts with an error + # and refuses to start. When the option is set to no, the user requires + # to fix the AOF file using the "valkey-check-aof" utility before to restart + # the server. + # + # Note that if the AOF file will be found to be corrupted in the middle + # the server will still exit with an error. This option only applies when + # Valkey will try to read more data from the AOF file but not enough bytes + # will be found. + aof-load-truncated yes + + # Valkey can create append-only base files in either RDB or AOF formats. Using + # the RDB format is always faster and more efficient, and disabling it is only + # supported for backward compatibility purposes. + aof-use-rdb-preamble yes + + # Valkey supports recording timestamp annotations in the AOF to support restoring + # the data from a specific point-in-time. However, using this capability changes + # the AOF format in a way that may not be compatible with existing AOF parsers. + aof-timestamp-enabled no + + ################################ SHUTDOWN ##################################### + + # Maximum time to wait for replicas when shutting down, in seconds. + # + # During shut down, a grace period allows any lagging replicas to catch up with + # the latest replication offset before the primary exists. This period can + # prevent data loss, especially for deployments without configured disk backups. + # + # The 'shutdown-timeout' value is the grace period's duration in seconds. It is + # only applicable when the instance has replicas. To disable the feature, set + # the value to 0. + # + # shutdown-timeout 10 + + # When Valkey receives a SIGINT or SIGTERM, shutdown is initiated and by default + # an RDB snapshot is written to disk in a blocking operation if save points are configured. + # The options used on signaled shutdown can include the following values: + # default: Saves RDB snapshot only if save points are configured. + # Waits for lagging replicas to catch up. + # save: Forces a DB saving operation even if no save points are configured. + # nosave: Prevents DB saving operation even if one or more save points are configured. + # now: Skips waiting for lagging replicas. + # force: Ignores any errors that would normally prevent the server from exiting. + # + # Any combination of values is allowed as long as "save" and "nosave" are not set simultaneously. + # Example: "nosave force now" + # + # shutdown-on-sigint default + # shutdown-on-sigterm default + + ################ NON-DETERMINISTIC LONG BLOCKING COMMANDS ##################### + + # Maximum time in milliseconds for EVAL scripts, functions and in some cases + # modules' commands before Valkey can start processing or rejecting other clients. + # + # If the maximum execution time is reached Valkey will start to reply to most + # commands with a BUSY error. + # + # In this state Valkey will only allow a handful of commands to be executed. + # For instance, SCRIPT KILL, FUNCTION KILL, SHUTDOWN NOSAVE and possibly some + # module specific 'allow-busy' commands. + # + # SCRIPT KILL and FUNCTION KILL will only be able to stop a script that did not + # yet call any write commands, so SHUTDOWN NOSAVE may be the only way to stop + # the server in the case a write command was already issued by the script when + # the user doesn't want to wait for the natural termination of the script. + # + # The default is 5 seconds. It is possible to set it to 0 or a negative value + # to disable this mechanism (uninterrupted execution). Note that in the past + # this config had a different name, which is now an alias, so both of these do + # the same: + lua-time-limit 5000 + # busy-reply-threshold 5000 + + ################################ VALKEY CLUSTER ############################### + + # Normal Valkey instances can't be part of a Valkey Cluster; only nodes that are + # started as cluster nodes can. In order to start a Valkey instance as a + # cluster node enable the cluster support uncommenting the following: + # + cluster-enabled yes + + # Every cluster node has a cluster configuration file. This file is not + # intended to be edited by hand. It is created and updated by Valkey nodes. + # Every Valkey Cluster node requires a different cluster configuration file. + # Make sure that instances running in the same system do not have + # overlapping cluster configuration file names. + # + cluster-config-file /bitnami/valkey/data/nodes.conf + + # Cluster node timeout is the amount of milliseconds a node must be unreachable + # for it to be considered in failure state. + # Most other internal time limits are a multiple of the node timeout. + # + # cluster-node-timeout 15000 + + # The cluster port is the port that the cluster bus will listen for inbound connections on. When set + # to the default value, 0, it will be bound to the command port + 10000. Setting this value requires + # you to specify the cluster bus port when executing cluster meet. + # cluster-port 0 + + # A replica of a failing primary will avoid to start a failover if its data + # looks too old. + # + # There is no simple way for a replica to actually have an exact measure of + # its "data age", so the following two checks are performed: + # + # 1) If there are multiple replicas able to failover, they exchange messages + # in order to try to give an advantage to the replica with the best + # replication offset (more data from the primary processed). + # Replicas will try to get their rank by offset, and apply to the start + # of the failover a delay proportional to their rank. + # + # 2) Every single replica computes the time of the last interaction with + # its primary. This can be the last ping or command received (if the primary + # is still in the "connected" state), or the time that elapsed since the + # disconnection with the primary (if the replication link is currently down). + # If the last interaction is too old, the replica will not try to failover + # at all. + # + # The point "2" can be tuned by user. Specifically a replica will not perform + # the failover if, since the last interaction with the primary, the time + # elapsed is greater than: + # + # (node-timeout * cluster-replica-validity-factor) + repl-ping-replica-period + # + # So for example if node-timeout is 30 seconds, and the cluster-replica-validity-factor + # is 10, and assuming a default repl-ping-replica-period of 10 seconds, the + # replica will not try to failover if it was not able to talk with the primary + # for longer than 310 seconds. + # + # A large cluster-replica-validity-factor may allow replicas with too old data to failover + # a primary, while a too small value may prevent the cluster from being able to + # elect a replica at all. + # + # For maximum availability, it is possible to set the cluster-replica-validity-factor + # to a value of 0, which means, that replicas will always try to failover the + # primary regardless of the last time they interacted with the primary. + # (However they'll always try to apply a delay proportional to their + # offset rank). + # + # Zero is the only value able to guarantee that when all the partitions heal + # the cluster will always be able to continue. + # + # cluster-replica-validity-factor 10 + + # Cluster replicas are able to migrate to orphaned primarys, that are primarys + # that are left without working replicas. This improves the cluster ability + # to resist to failures as otherwise an orphaned primary can't be failed over + # in case of failure if it has no working replicas. + # + # Replicas migrate to orphaned primarys only if there are still at least a + # given number of other working replicas for their old primary. This number + # is the "migration barrier". A migration barrier of 1 means that a replica + # will migrate only if there is at least 1 other working replica for its primary + # and so forth. It usually reflects the number of replicas you want for every + # primary in your cluster. + # + # Default is 1 (replicas migrate only if their primarys remain with at least + # one replica). To disable migration just set it to a very large value or + # set cluster-allow-replica-migration to 'no'. + # A value of 0 can be set but is useful only for debugging and dangerous + # in production. + # + # cluster-migration-barrier 1 + + # Turning off this option allows to use less automatic cluster configuration. + # It both disables migration to orphaned primarys and migration from primarys + # that became empty. + # + # Default is 'yes' (allow automatic migrations). + # + # cluster-allow-replica-migration yes + + # By default Valkey Cluster nodes stop accepting queries if they detect there + # is at least a hash slot uncovered (no available node is serving it). + # This way if the cluster is partially down (for example a range of hash slots + # are no longer covered) all the cluster becomes, eventually, unavailable. + # It automatically returns available as soon as all the slots are covered again. + # + # However sometimes you want the subset of the cluster which is working, + # to continue to accept queries for the part of the key space that is still + # covered. In order to do so, just set the cluster-require-full-coverage + # option to no. + # + # cluster-require-full-coverage yes + + # This option, when set to yes, prevents replicas from trying to failover its + # primary during primary failures. However the replica can still perform a + # manual failover, if forced to do so. + # + # This is useful in different scenarios, especially in the case of multiple + # data center operations, where we want one side to never be promoted if not + # in the case of a total DC failure. + # + # cluster-replica-no-failover no + + # This option, when set to yes, allows nodes to serve read traffic while the + # cluster is in a down state, as long as it believes it owns the slots. + # + # This is useful for two cases. The first case is for when an application + # doesn't require consistency of data during node failures or network partitions. + # One example of this is a cache, where as long as the node has the data it + # should be able to serve it. + # + # The second use case is for configurations that don't meet the recommended + # three shards but want to enable cluster mode and scale later. A + # primary outage in a 1 or 2 shard configuration causes a read/write outage to the + # entire cluster without this option set, with it set there is only a write outage. + # Without a quorum of primarys, slot ownership will not change automatically. + # + # cluster-allow-reads-when-down no + + # This option, when set to yes, allows nodes to serve pubsub shard traffic while + # the cluster is in a down state, as long as it believes it owns the slots. + # + # This is useful if the application would like to use the pubsub feature even when + # the cluster global stable state is not OK. If the application wants to make sure only + # one shard is serving a given channel, this feature should be kept as yes. + # + # cluster-allow-pubsubshard-when-down yes + + # Cluster link send buffer limit is the limit on the memory usage of an individual + # cluster bus link's send buffer in bytes. Cluster links would be freed if they exceed + # this limit. This is to primarily prevent send buffers from growing unbounded on links + # toward slow peers (E.g. PubSub messages being piled up). + # This limit is disabled by default. Enable this limit when 'mem_cluster_links' INFO field + # and/or 'send-buffer-allocated' entries in the 'CLUSTER LINKS` command output continuously increase. + # Minimum limit of 1gb is recommended so that cluster link buffer can fit in at least a single + # PubSub message by default. (client-query-buffer-limit default value is 1gb) + # + # cluster-link-sendbuf-limit 0 + + # Clusters can configure their announced hostname using this config. This is a common use case for + # applications that need to use TLS Server Name Indication (SNI) or dealing with DNS based + # routing. By default this value is only shown as additional metadata in the CLUSTER SLOTS + # command, but can be changed using 'cluster-preferred-endpoint-type' config. This value is + # communicated along the clusterbus to all nodes, setting it to an empty string will remove + # the hostname and also propagate the removal. + # + # cluster-announce-hostname "" + + # Clusters can advertise how clients should connect to them using either their IP address, + # a user defined hostname, or by declaring they have no endpoint. Which endpoint is + # shown as the preferred endpoint is set by using the cluster-preferred-endpoint-type + # config with values 'ip', 'hostname', or 'unknown-endpoint'. This value controls how + # the endpoint returned for MOVED/ASKING requests as well as the first field of CLUSTER SLOTS. + # If the preferred endpoint type is set to hostname, but no announced hostname is set, a '?' + # will be returned instead. + # + # When a cluster advertises itself as having an unknown endpoint, it's indicating that + # the server doesn't know how clients can reach the cluster. This can happen in certain + # networking situations where there are multiple possible routes to the node, and the + # server doesn't know which one the client took. In this case, the server is expecting + # the client to reach out on the same endpoint it used for making the last request, but use + # the port provided in the response. + # + # cluster-preferred-endpoint-type ip + + ########################## CLUSTER DOCKER/NAT support ######################## + + # In certain deployments, Valkey Cluster nodes address discovery fails, because + # addresses are NAT-ted or because ports are forwarded (the typical case is + # Docker and other containers). + # + # In order to make Valkey Cluster working in such environments, a static + # configuration where each node knows its public address is needed. The + # following four options are used for this scope, and are: + # + # * cluster-announce-ip + # * cluster-announce-port + # * cluster-announce-tls-port + # * cluster-announce-bus-port + # + # Each instructs the node about its address, client ports (for connections + # without and with TLS) and cluster message bus port. The information is then + # published in the header of the bus packets so that other nodes will be able to + # correctly map the address of the node publishing the information. + # + # If cluster-tls is set to yes and cluster-announce-tls-port is omitted or set + # to zero, then cluster-announce-port refers to the TLS port. Note also that + # cluster-announce-tls-port has no effect if cluster-tls is set to no. + # + # If the above options are not used, the normal Valkey Cluster auto-detection + # will be used instead. + # + # Note that when remapped, the bus port may not be at the fixed offset of + # clients port + 10000, so you can specify any port and bus-port depending + # on how they get remapped. If the bus-port is not set, a fixed offset of + # 10000 will be used as usual. + # + # Example: + # + # cluster-announce-ip 10.1.1.5 + # cluster-announce-tls-port 6379 + # cluster-announce-port 0 + # cluster-announce-bus-port 6380 + + ################################## SLOW LOG ################################### + + # The Valkey Slow Log is a system to log queries that exceeded a specified + # execution time. The execution time does not include the I/O operations + # like talking with the client, sending the reply and so forth, + # but just the time needed to actually execute the command (this is the only + # stage of command execution where the thread is blocked and can not serve + # other requests in the meantime). + # + # You can configure the slow log with two parameters: one tells Valkey + # what is the execution time, in microseconds, to exceed in order for the + # command to get logged, and the other parameter is the length of the + # slow log. When a new command is logged the oldest one is removed from the + # queue of logged commands. + + # The following time is expressed in microseconds, so 1000000 is equivalent + # to one second. Note that a negative number disables the slow log, while + # a value of zero forces the logging of every command. + slowlog-log-slower-than 10000 + + # There is no limit to this length. Just be aware that it will consume memory. + # You can reclaim memory used by the slow log with SLOWLOG RESET. + slowlog-max-len 128 + + ################################ LATENCY MONITOR ############################## + + # The Valkey latency monitoring subsystem samples different operations + # at runtime in order to collect data related to possible sources of + # latency of a Valkey instance. + # + # Via the LATENCY command this information is available to the user that can + # print graphs and obtain reports. + # + # The system only logs operations that were performed in a time equal or + # greater than the amount of milliseconds specified via the + # latency-monitor-threshold configuration directive. When its value is set + # to zero, the latency monitor is turned off. + # + # By default latency monitoring is disabled since it is mostly not needed + # if you don't have latency issues, and collecting data has a performance + # impact, that while very small, can be measured under big load. Latency + # monitoring can easily be enabled at runtime using the command + # "CONFIG SET latency-monitor-threshold " if needed. + latency-monitor-threshold 0 + + ################################ LATENCY TRACKING ############################## + + # The Valkey extended latency monitoring tracks the per command latencies and enables + # exporting the percentile distribution via the INFO latencystats command, + # and cumulative latency distributions (histograms) via the LATENCY command. + # + # By default, the extended latency monitoring is enabled since the overhead + # of keeping track of the command latency is very small. + # latency-tracking yes + + # By default the exported latency percentiles via the INFO latencystats command + # are the p50, p99, and p999. + # latency-tracking-info-percentiles 50 99 99.9 + + ############################# EVENT NOTIFICATION ############################## + + # Valkey can notify Pub/Sub clients about events happening in the key space. + # + # For instance if keyspace events notification is enabled, and a client + # performs a DEL operation on key "foo" stored in the Database 0, two + # messages will be published via Pub/Sub: + # + # PUBLISH __keyspace@0__:foo del + # PUBLISH __keyevent@0__:del foo + # + # It is possible to select the events that Valkey will notify among a set + # of classes. Every class is identified by a single character: + # + # K Keyspace events, published with __keyspace@__ prefix. + # E Keyevent events, published with __keyevent@__ prefix. + # g Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ... + # $ String commands + # l List commands + # s Set commands + # h Hash commands + # z Sorted set commands + # x Expired events (events generated every time a key expires) + # e Evicted events (events generated when a key is evicted for maxmemory) + # n New key events (Note: not included in the 'A' class) + # t Stream commands + # d Module key type events + # m Key-miss events (Note: It is not included in the 'A' class) + # A Alias for g$lshzxetd, so that the "AKE" string means all the events + # (Except key-miss events which are excluded from 'A' due to their + # unique nature). + # + # The "notify-keyspace-events" takes as argument a string that is composed + # of zero or multiple characters. The empty string means that notifications + # are disabled. + # + # Example: to enable list and generic events, from the point of view of the + # event name, use: + # + # notify-keyspace-events Elg + # + # Example 2: to get the stream of the expired keys subscribing to channel + # name __keyevent@0__:expired use: + # + # notify-keyspace-events Ex + # + # By default all notifications are disabled because most users don't need + # this feature and the feature has some overhead. Note that if you don't + # specify at least one of K or E, no events will be delivered. + notify-keyspace-events "" + + ############################### ADVANCED CONFIG ############################### + + # Hashes are encoded using a memory efficient data structure when they have a + # small number of entries, and the biggest entry does not exceed a given + # threshold. These thresholds can be configured using the following directives. + hash-max-listpack-entries 512 + hash-max-listpack-value 64 + + # Lists are also encoded in a special way to save a lot of space. + # The number of entries allowed per internal list node can be specified + # as a fixed maximum size or a maximum number of elements. + # For a fixed maximum size, use -5 through -1, meaning: + # -5: max size: 64 Kb <-- not recommended for normal workloads + # -4: max size: 32 Kb <-- not recommended + # -3: max size: 16 Kb <-- probably not recommended + # -2: max size: 8 Kb <-- good + # -1: max size: 4 Kb <-- good + # Positive numbers mean store up to _exactly_ that number of elements + # per list node. + # The highest performing option is usually -2 (8 Kb size) or -1 (4 Kb size), + # but if your use case is unique, adjust the settings as necessary. + list-max-listpack-size -2 + + # Lists may also be compressed. + # Compress depth is the number of quicklist ziplist nodes from *each* side of + # the list to *exclude* from compression. The head and tail of the list + # are always uncompressed for fast push/pop operations. Settings are: + # 0: disable all list compression + # 1: depth 1 means "don't start compressing until after 1 node into the list, + # going from either the head or tail" + # So: [head]->node->node->...->node->[tail] + # [head], [tail] will always be uncompressed; inner nodes will compress. + # 2: [head]->[next]->node->node->...->node->[prev]->[tail] + # 2 here means: don't compress head or head->next or tail->prev or tail, + # but compress all nodes between them. + # 3: [head]->[next]->[next]->node->node->...->node->[prev]->[prev]->[tail] + # etc. + list-compress-depth 0 + + # Sets have a special encoding in just one case: when a set is composed + # of just strings that happen to be integers in radix 10 in the range + # of 64 bit signed integers. + # The following configuration setting sets the limit in the size of the + # set in order to use this special memory saving encoding. + set-max-intset-entries 512 + + # Similarly to hashes and lists, sorted sets are also specially encoded in + # order to save a lot of space. This encoding is only used when the length and + # elements of a sorted set are below the following limits: + zset-max-listpack-entries 128 + zset-max-listpack-value 64 + + # HyperLogLog sparse representation bytes limit. The limit includes the + # 16 bytes header. When an HyperLogLog using the sparse representation crosses + # this limit, it is converted into the dense representation. + # + # A value greater than 16000 is totally useless, since at that point the + # dense representation is more memory efficient. + # + # The suggested value is ~ 3000 in order to have the benefits of + # the space efficient encoding without slowing down too much PFADD, + # which is O(N) with the sparse encoding. The value can be raised to + # ~ 10000 when CPU is not a concern, but space is, and the data set is + # composed of many HyperLogLogs with cardinality in the 0 - 15000 range. + hll-sparse-max-bytes 3000 + + # Streams macro node max size / items. The stream data structure is a radix + # tree of big nodes that encode multiple items inside. Using this configuration + # it is possible to configure how big a single node can be in bytes, and the + # maximum number of items it may contain before switching to a new node when + # appending new stream entries. If any of the following settings are set to + # zero, the limit is ignored, so for instance it is possible to set just a + # max entries limit by setting max-bytes to 0 and max-entries to the desired + # value. + stream-node-max-bytes 4096 + stream-node-max-entries 100 + + # Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in + # order to help rehashing the main Valkey hash table (the one mapping top-level + # keys to values). The hash table implementation Valkey uses (see dict.c) + # performs a lazy rehashing: the more operation you run into a hash table + # that is rehashing, the more rehashing "steps" are performed, so if the + # server is idle the rehashing is never complete and some more memory is used + # by the hash table. + # + # The default is to use this millisecond 10 times every second in order to + # actively rehash the main dictionaries, freeing memory when possible. + # + # If unsure: + # use "activerehashing no" if you have hard latency requirements and it is + # not a good thing in your environment that Valkey can reply from time to time + # to queries with 2 milliseconds delay. + # + # use "activerehashing yes" if you don't have such hard requirements but + # want to free memory asap when possible. + activerehashing yes + + # The client output buffer limits can be used to force disconnection of clients + # that are not reading data from the server fast enough for some reason (a + # common reason is that a Pub/Sub client can't consume messages as fast as the + # publisher can produce them). + # + # The limit can be set differently for the three different classes of clients: + # + # normal -> normal clients including MONITOR clients + # replica -> replica clients + # pubsub -> clients subscribed to at least one pubsub channel or pattern + # + # The syntax of every client-output-buffer-limit directive is the following: + # + # client-output-buffer-limit + # + # A client is immediately disconnected once the hard limit is reached, or if + # the soft limit is reached and remains reached for the specified number of + # seconds (continuously). + # So for instance if the hard limit is 32 megabytes and the soft limit is + # 16 megabytes / 10 seconds, the client will get disconnected immediately + # if the size of the output buffers reach 32 megabytes, but will also get + # disconnected if the client reaches 16 megabytes and continuously overcomes + # the limit for 10 seconds. + # + # By default normal clients are not limited because they don't receive data + # without asking (in a push way), but just after a request, so only + # asynchronous clients may create a scenario where data is requested faster + # than it can read. + # + # Instead there is a default limit for pubsub and replica clients, since + # subscribers and replicas receive data in a push fashion. + # + # Note that it doesn't make sense to set the replica clients output buffer + # limit lower than the repl-backlog-size config (partial sync will succeed + # and then replica will get disconnected). + # Such a configuration is ignored (the size of repl-backlog-size will be used). + # This doesn't have memory consumption implications since the replica client + # will share the backlog buffers memory. + # + # Both the hard or the soft limit can be disabled by setting them to zero. + client-output-buffer-limit normal 0 0 0 + client-output-buffer-limit replica 256mb 64mb 60 + client-output-buffer-limit pubsub 32mb 8mb 60 + + # Client query buffers accumulate new commands. They are limited to a fixed + # amount by default in order to avoid that a protocol desynchronization (for + # instance due to a bug in the client) will lead to unbound memory usage in + # the query buffer. However you can configure it here if you have very special + # needs, such us huge multi/exec requests or alike. + # + # client-query-buffer-limit 1gb + + # In some scenarios client connections can hog up memory leading to OOM + # errors or data eviction. To avoid this we can cap the accumulated memory + # used by all client connections (all pubsub and normal clients). Once we + # reach that limit connections will be dropped by the server freeing up + # memory. The server will attempt to drop the connections using the most + # memory first. We call this mechanism "client eviction". + # + # Client eviction is configured using the maxmemory-clients setting as follows: + # 0 - client eviction is disabled (default) + # + # A memory value can be used for the client eviction threshold, + # for example: + # maxmemory-clients 1g + # + # A percentage value (between 1% and 100%) means the client eviction threshold + # is based on a percentage of the maxmemory setting. For example to set client + # eviction at 5% of maxmemory: + # maxmemory-clients 5% + + # In the Valkey protocol, bulk requests, that are, elements representing single + # strings, are normally limited to 512 mb. However you can change this limit + # here, but must be 1mb or greater + # + # proto-max-bulk-len 512mb + + # Valkey calls an internal function to perform many background tasks, like + # closing connections of clients in timeout, purging expired keys that are + # never requested, and so forth. + # + # Not all tasks are performed with the same frequency, but Valkey checks for + # tasks to perform according to the specified "hz" value. + # + # By default "hz" is set to 10. Raising the value will use more CPU when + # Valkey is idle, but at the same time will make Valkey more responsive when + # there are many keys expiring at the same time, and timeouts may be + # handled with more precision. + # + # The range is between 1 and 500, however a value over 100 is usually not + # a good idea. Most users should use the default of 10 and raise this up to + # 100 only in environments where very low latency is required. + hz 10 + + # Normally it is useful to have an HZ value which is proportional to the + # number of clients connected. This is useful in order, for instance, to + # avoid too many clients are processed for each background task invocation + # in order to avoid latency spikes. + # + # Since the default HZ value by default is conservatively set to 10, Valkey + # offers, and enables by default, the ability to use an adaptive HZ value + # which will temporarily raise when there are many connected clients. + # + # When dynamic HZ is enabled, the actual configured HZ will be used + # as a baseline, but multiples of the configured HZ value will be actually + # used as needed once more clients are connected. In this way an idle + # instance will use very little CPU time while a busy instance will be + # more responsive. + dynamic-hz yes + + # When a child rewrites the AOF file, if the following option is enabled + # the file will be fsync-ed every 4 MB of data generated. This is useful + # in order to commit the file to the disk more incrementally and avoid + # big latency spikes. + aof-rewrite-incremental-fsync yes + + # When valkey saves RDB file, if the following option is enabled + # the file will be fsync-ed every 4 MB of data generated. This is useful + # in order to commit the file to the disk more incrementally and avoid + # big latency spikes. + rdb-save-incremental-fsync yes + + # Valkey LFU eviction (see maxmemory setting) can be tuned. However it is a good + # idea to start with the default settings and only change them after investigating + # how to improve the performances and how the keys LFU change over time, which + # is possible to inspect via the OBJECT FREQ command. + # + # There are two tunable parameters in the Valkey LFU implementation: the + # counter logarithm factor and the counter decay time. It is important to + # understand what the two parameters mean before changing them. + # + # The LFU counter is just 8 bits per key, it's maximum value is 255, so Valkey + # uses a probabilistic increment with logarithmic behavior. Given the value + # of the old counter, when a key is accessed, the counter is incremented in + # this way: + # + # 1. A random number R between 0 and 1 is extracted. + # 2. A probability P is calculated as 1/(old_value*lfu_log_factor+1). + # 3. The counter is incremented only if R < P. + # + # The default lfu-log-factor is 10. This is a table of how the frequency + # counter changes with a different number of accesses with different + # logarithmic factors: + # + # +--------+------------+------------+------------+------------+------------+ + # | factor | 100 hits | 1000 hits | 100K hits | 1M hits | 10M hits | + # +--------+------------+------------+------------+------------+------------+ + # | 0 | 104 | 255 | 255 | 255 | 255 | + # +--------+------------+------------+------------+------------+------------+ + # | 1 | 18 | 49 | 255 | 255 | 255 | + # +--------+------------+------------+------------+------------+------------+ + # | 10 | 10 | 18 | 142 | 255 | 255 | + # +--------+------------+------------+------------+------------+------------+ + # | 100 | 8 | 11 | 49 | 143 | 255 | + # +--------+------------+------------+------------+------------+------------+ + # + # NOTE: The above table was obtained by running the following commands: + # + # valkey-benchmark -n 1000000 incr foo + # valkey-cli object freq foo + # + # NOTE 2: The counter initial value is 5 in order to give new objects a chance + # to accumulate hits. + # + # The counter decay time is the time, in minutes, that must elapse in order + # for the key counter to be divided by two (or decremented if it has a value + # less <= 10). + # + # The default value for the lfu-decay-time is 1. A special value of 0 means to + # decay the counter every time it happens to be scanned. + # + # lfu-log-factor 10 + # lfu-decay-time 1 + + ########################### ACTIVE DEFRAGMENTATION ####################### + # + # What is active defragmentation? + # ------------------------------- + # + # Active (online) defragmentation allows a Valkey server to compact the + # spaces left between small allocations and deallocations of data in memory, + # thus allowing to reclaim back memory. + # + # Fragmentation is a natural process that happens with every allocator (but + # less so with Jemalloc, fortunately) and certain workloads. Normally a server + # restart is needed in order to lower the fragmentation, or at least to flush + # away all the data and create it again. + # + # Basically when the fragmentation is over a certain level (see the + # configuration options below) Valkey will start to create new copies of the + # values in contiguous memory regions by exploiting certain specific Jemalloc + # features (in order to understand if an allocation is causing fragmentation + # and to allocate it in a better place), and at the same time, will release the + # old copies of the data. This process, repeated incrementally for all the keys + # will cause the fragmentation to drop back to normal values. + # + # Important things to understand: + # + # 1. This feature is disabled by default, and only works if you compiled Valkey + # to use the copy of Jemalloc we ship with the source code of Valkey. + # This is the default with Linux builds. + # + # 2. You never need to enable this feature if you don't have fragmentation + # issues. + # + # 3. Once you experience fragmentation, you can enable this feature when + # needed with the command "CONFIG SET activedefrag yes". + # + # The configuration parameters are able to fine tune the behavior of the + # defragmentation process. If you are not sure about what they mean it is + # a good idea to leave the defaults untouched. + + # Active defragmentation is disabled by default + # activedefrag no + + # Minimum amount of fragmentation waste to start active defrag + # active-defrag-ignore-bytes 100mb + + # Minimum percentage of fragmentation to start active defrag + # active-defrag-threshold-lower 10 + + # Maximum percentage of fragmentation at which we use maximum effort + # active-defrag-threshold-upper 100 + + # Minimal effort for defrag in CPU percentage, to be used when the lower + # threshold is reached + # active-defrag-cycle-min 1 + + # Maximal effort for defrag in CPU percentage, to be used when the upper + # threshold is reached + # active-defrag-cycle-max 25 + + # Maximum number of set/hash/zset/list fields that will be processed from + # the main dictionary scan + # active-defrag-max-scan-fields 1000 + + # Jemalloc background thread for purging will be enabled by default + jemalloc-bg-thread yes + + # It is possible to pin different threads and processes of Valkey to specific + # CPUs in your system, in order to maximize the performances of the server. + # This is useful both in order to pin different Valkey threads in different + # CPUs, but also in order to make sure that multiple Valkey instances running + # in the same host will be pinned to different CPUs. + # + # Normally you can do this using the "taskset" command, however it is also + # possible to this via Valkey configuration directly, both in Linux and FreeBSD. + # + # You can pin the server/IO threads, bio threads, aof rewrite child process, and + # the bgsave child process. The syntax to specify the cpu list is the same as + # the taskset command: + # + # Set valkey server/io threads to cpu affinity 0,2,4,6: + # server_cpulist 0-7:2 + # + # Set bio threads to cpu affinity 1,3: + # bio_cpulist 1,3 + # + # Set aof rewrite child process to cpu affinity 8,9,10,11: + # aof_rewrite_cpulist 8-11 + # + # Set bgsave child process to cpu affinity 1,10,11 + # bgsave_cpulist 1,10-11 + + # In some cases valkey will emit warnings and even refuse to start if it detects + # that the system is in bad state, it is possible to suppress these warnings + # by setting the following config which takes a space delimited list of warnings + # to suppress + # + # ignore-warnings ARM64-COW-BUG +{{- end }} +{{- if .Values.valkey.configmap }} +{{- include "common.tplvalues.render" (dict "value" .Values.valkey.configmap "context" $) | nindent 4 }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey-cluster/templates/extra-list.yaml b/backing-services/gitea/charts/valkey-cluster/templates/extra-list.yaml new file mode 100644 index 0000000..329f5c6 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/templates/extra-list.yaml @@ -0,0 +1,9 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey-cluster/templates/headless-svc.yaml b/backing-services/gitea/charts/valkey-cluster/templates/headless-svc.yaml new file mode 100644 index 0000000..d572988 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/templates/headless-svc.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-headless" (include "common.names.fullname" . ) | replace "+" "_" | trunc 63 | trimSuffix "-" }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.service.headless.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.service.headless.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + publishNotReadyAddresses: true + ports: + - name: tcp-redis + port: {{ .Values.valkey.containerPorts.valkey }} + targetPort: tcp-redis + - name: tcp-redis-bus + port: {{ .Values.valkey.containerPorts.bus }} + targetPort: tcp-redis-bus + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.valkey.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} diff --git a/backing-services/gitea/charts/valkey-cluster/templates/metrics-prometheus.yaml b/backing-services/gitea/charts/valkey-cluster/templates/metrics-prometheus.yaml new file mode 100644 index 0000000..09e6763 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/templates/metrics-prometheus.yaml @@ -0,0 +1,45 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (.Values.metrics.enabled) (.Values.metrics.serviceMonitor.enabled) }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ default .Release.Namespace .Values.metrics.serviceMonitor.namespace | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.serviceMonitor.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + {{- if or .Values.commonAnnotations .Values.metrics.serviceMonitor.annotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.serviceMonitor.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.metrics.serviceMonitor.jobLabel }} + jobLabel: {{ .Values.metrics.serviceMonitor.jobLabel }} + {{- end }} + endpoints: + - port: metrics + {{- if .Values.metrics.serviceMonitor.interval }} + interval: {{ .Values.metrics.serviceMonitor.interval }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.relabelings }} + relabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.relabelings "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.metricRelabelings "context" $) | nindent 8 }} + {{- end }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + {{- if .Values.metrics.serviceMonitor.selector }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.serviceMonitor.selector "context" $) | nindent 6 }} + {{- end }} + app.kubernetes.io/component: "metrics" + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/templates/metrics-svc.yaml b/backing-services/gitea/charts/valkey-cluster/templates/metrics-svc.yaml new file mode 100644 index 0000000..e665396 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/templates/metrics-svc.yaml @@ -0,0 +1,33 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.metrics.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-metrics" (include "common.names.fullname" . ) | replace "+" "_" | trunc 63 | trimSuffix "-" }} + namespace: {{ .Release.Namespace | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.service.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: "metrics" + {{- if or .Values.metrics.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.metrics.service.type }} + {{- if and .Values.metrics.service.clusterIP (eq .Values.metrics.service.type "ClusterIP") }} + clusterIP: {{ .Values.metrics.service.clusterIP }} + {{- end }} + {{- if and (eq .Values.metrics.service.type "LoadBalancer") .Values.metrics.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.metrics.service.loadBalancerIP }} + {{- end }} + ports: + - name: metrics + port: {{ .Values.metrics.service.ports.http }} + targetPort: http-metrics + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.valkey.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey-cluster/templates/networkpolicy.yaml b/backing-services/gitea/charts/valkey-cluster/templates/networkpolicy.yaml new file mode 100644 index 0000000..5db4465 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/templates/networkpolicy.yaml @@ -0,0 +1,81 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ template "common.capabilities.networkPolicy.apiVersion" . }} +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.valkey.podLabels .Values.commonLabels ) "context" . ) }} + podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + policyTypes: + - Ingress + - Egress + {{- if .Values.networkPolicy.allowExternalEgress }} + egress: + - {} + {{- else }} + egress: + # Allow dns resolution + - ports: + - port: 53 + protocol: TCP + - port: 53 + protocol: UDP + # Allow outbound connections to other cluster pods + - ports: + - port: {{ .Values.valkey.containerPorts.valkey }} + - port: {{ .Values.valkey.containerPorts.bus }} + to: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 14 }} + {{- if .Values.networkPolicy.extraEgress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.networkPolicy.extraEgress "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} + ingress: + # Allow inbound connections + - ports: + - port: {{ .Values.valkey.containerPorts.valkey }} + - port: {{ .Values.valkey.containerPorts.bus }} + {{- if .Values.metrics.enabled }} + # Allow prometheus scrapes for metrics + - port: {{ .Values.metrics.containerPorts.http }} + {{- end }} + {{- if not .Values.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 14 }} + - podSelector: + matchLabels: + {{ template "common.names.fullname" . }}-client: "true" + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 14 }} + {{- end }} + {{- if .Values.networkPolicy.ingressNSMatchLabels }} + - namespaceSelector: + matchLabels: + {{- range $key, $value := .Values.networkPolicy.ingressNSMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{- end }} + {{- if .Values.networkPolicy.ingressNSPodMatchLabels }} + - podSelector: + matchLabels: + {{- range $key, $value := .Values.networkPolicy.ingressNSPodMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{- end }} + {{- if .Values.networkPolicy.extraIngress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.networkPolicy.extraIngress "context" $ ) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey-cluster/templates/poddisruptionbudget.yaml b/backing-services/gitea/charts/valkey-cluster/templates/poddisruptionbudget.yaml new file mode 100644 index 0000000..4f975cf --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/templates/poddisruptionbudget.yaml @@ -0,0 +1,32 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if or .Values.podDisruptionBudget .Values.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.podDisruptionBudget }} + {{- include "common.tplvalues.render" (dict "value" .Values.podDisruptionBudget "context" $) | nindent 2 }} + {{- else }} + {{- if .Values.pdb.minAvailable }} + minAvailable: {{ .Values.pdb.minAvailable }} + {{- end }} + {{- if or .Values.pdb.maxUnavailable (not .Values.pdb.minAvailable) }} + maxUnavailable: {{ .Values.pdb.maxUnavailable | default 1 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.valkey.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + matchExpressions: + - {key: job-name, operator: NotIn, values: [{{ template "common.names.fullname" . }}-cluster-update]} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey-cluster/templates/prometheusrule.yaml b/backing-services/gitea/charts/valkey-cluster/templates/prometheusrule.yaml new file mode 100644 index 0000000..75ad4b5 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/templates/prometheusrule.yaml @@ -0,0 +1,25 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ default .Release.Namespace .Values.metrics.prometheusRule.namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.metrics.prometheusRule.additionalLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.prometheusRule.additionalLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- with .Values.metrics.prometheusRule.rules }} + groups: + - name: {{ template "common.names.name" $ }} + rules: {{- include "common.tplvalues.render" ( dict "value" . "context" $ ) | nindent 8 }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey-cluster/templates/scripts-configmap.yaml b/backing-services/gitea/charts/valkey-cluster/templates/scripts-configmap.yaml new file mode 100644 index 0000000..14f83f8 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/templates/scripts-configmap.yaml @@ -0,0 +1,113 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-scripts" (include "common.names.fullname" . ) | replace "+" "_" | trunc 63 | trimSuffix "-" }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + ping_readiness_local.sh: |- + #!/bin/sh + set -e + + VALKEY_STATUS_FILE=/tmp/.valkey_cluster_check + + {{- if and .Values.usePassword .Values.usePasswordFiles }} + password_aux=`cat ${VALKEY_PASSWORD_FILE}` + export REDISCLI_AUTH=$password_aux + {{- else }} + if [ ! -z "$VALKEY_PASSWORD" ]; then export REDISCLI_AUTH=$VALKEY_PASSWORD; fi; + {{- end }} + response=$( + timeout -s 15 $1 \ + valkey-cli \ + -h localhost \ +{{- if .Values.tls.enabled }} + -p $VALKEY_TLS_PORT_NUMBER \ + --tls \ + --cert {{ template "valkey-cluster.tlsCert" . }} \ + --key {{ template "valkey-cluster.tlsCertKey" . }} \ + --cacert {{ template "valkey-cluster.tlsCACert" . }} \ +{{- else }} + -p $VALKEY_PORT_NUMBER \ +{{- end }} + ping + ) + if [ "$?" -eq "124" ]; then + echo "Timed out" + exit 1 + fi + if [ "$response" != "PONG" ]; then + echo "$response" + exit 1 + fi +{{- if not .Values.cluster.externalAccess.enabled }} + if [ ! -f "$VALKEY_STATUS_FILE" ]; then + response=$( + timeout -s 15 $1 \ + valkey-cli \ + -h localhost \ + {{- if .Values.tls.enabled }} + -p $VALKEY_TLS_PORT_NUMBER \ + --tls \ + --cert {{ template "valkey-cluster.tlsCert" . }} \ + --key {{ template "valkey-cluster.tlsCertKey" . }} \ + --cacert {{ template "valkey-cluster.tlsCACert" . }} \ + {{- else }} + -p $VALKEY_PORT_NUMBER \ + {{- end }} + CLUSTER INFO | grep cluster_state | tr -d '[:space:]' + ) + if [ "$?" -eq "124" ]; then + echo "Timed out" + exit 1 + fi + if [ "$response" != "cluster_state:ok" ]; then + echo "$response" + exit 1 + else + touch "$VALKEY_STATUS_FILE" + fi + fi +{{- end }} + ping_liveness_local.sh: |- + #!/bin/sh + set -e + + {{- if and .Values.usePassword .Values.usePasswordFiles }} + password_aux=`cat ${VALKEY_PASSWORD_FILE}` + export REDISCLI_AUTH=$password_aux + {{- else }} + if [ ! -z "$VALKEY_PASSWORD" ]; then export REDISCLI_AUTH=$VALKEY_PASSWORD; fi; + {{- end }} + response=$( + timeout -s 15 $1 \ + valkey-cli \ + -h localhost \ +{{- if .Values.tls.enabled }} + -p $VALKEY_TLS_PORT_NUMBER \ + --tls \ + --cert {{ template "valkey-cluster.tlsCert" . }} \ + --key {{ template "valkey-cluster.tlsCertKey" . }} \ + --cacert {{ template "valkey-cluster.tlsCACert" . }} \ +{{- else }} + -p $VALKEY_PORT_NUMBER \ +{{- end }} + ping + ) + if [ "$?" -eq "124" ]; then + echo "Timed out" + exit 1 + fi + responseFirstWord=$(echo $response | head -n1 | awk '{print $1;}') + if [ "$response" != "PONG" ] && [ "$responseFirstWord" != "LOADING" ] && [ "$responseFirstWord" != "MASTERDOWN" ]; then + echo "$response" + exit 1 + fi diff --git a/backing-services/gitea/charts/valkey-cluster/templates/secret.yaml b/backing-services/gitea/charts/valkey-cluster/templates/secret.yaml new file mode 100644 index 0000000..301cdf3 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/templates/secret.yaml @@ -0,0 +1,19 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.usePassword (not .Values.existingSecret) -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + valkey-password: {{ include "valkey-cluster.password" . | b64enc | quote }} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/templates/svc-cluster-external-access.yaml b/backing-services/gitea/charts/valkey-cluster/templates/svc-cluster-external-access.yaml new file mode 100644 index 0000000..ef7c4c2 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/templates/svc-cluster-external-access.yaml @@ -0,0 +1,64 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.cluster.externalAccess.enabled }} +{{- $fullName := include "common.names.fullname" . }} +{{- $nodesCount := .Values.cluster.nodes | int }} +{{- $root := . }} + +{{- range $i, $e := until $nodesCount }} +{{- $targetPod := printf "%s-%d" (printf "%s" $fullName) $i }} +{{- $_ := set $ "targetPod" $targetPod }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "common.names.fullname" $ }}-{{ $i }}-svc + namespace: {{ $.Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $root.Values.commonLabels "context" $ ) | nindent 4 }} + pod: {{ $targetPod }} + {{- if or + ($root.Values.cluster.externalAccess.service.annotations) + ($root.Values.commonAnnotations) + (ne $root.Values.cluster.externalAccess.service.loadBalancerIPAnnotaion "") }} + {{- $loadBalancerIPAnnotaion := "" }} + {{- if ne $root.Values.cluster.externalAccess.service.loadBalancerIPAnnotaion ""}} + {{- $loadBalancerIPAnnotaion = printf + "%s: %s" + $root.Values.cluster.externalAccess.service.loadBalancerIPAnnotaion + (index $root.Values.cluster.externalAccess.service.loadBalancerIP $i) }} + {{- end }} + {{- $annotations := include "common.tplvalues.merge" + ( dict "values" + ( list + $root.Values.cluster.externalAccess.service.annotations + $root.Values.commonAnnotations + $loadBalancerIPAnnotaion + ) "context" $ ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ $root.Values.cluster.externalAccess.service.type }} + {{- if and + ($root.Values.cluster.externalAccess.service.loadBalancerIP) + (eq $root.Values.cluster.externalAccess.service.loadBalancerIPAnnotaion "") + (not $root.Values.cluster.externalAccess.service.disableLoadBalancerIP) }} + loadBalancerIP: {{ index $root.Values.cluster.externalAccess.service.loadBalancerIP $i }} + {{- end }} + {{- if and (eq $root.Values.cluster.externalAccess.service.type "LoadBalancer") $root.Values.cluster.externalAccess.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{- toYaml $root.Values.cluster.externalAccess.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + ports: + - name: tcp-redis + port: {{ $root.Values.cluster.externalAccess.service.port }} + targetPort: tcp-redis + - name: tcp-redis-bus + targetPort: tcp-redis-bus + port: {{ $root.Values.valkey.containerPorts.bus }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list $root.Values.valkey.podLabels $root.Values.commonLabels ) "context" $ ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + statefulset.kubernetes.io/pod-name: {{ $targetPod }} +--- +{{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey-cluster/templates/tls-secret.yaml b/backing-services/gitea/charts/valkey-cluster/templates/tls-secret.yaml new file mode 100644 index 0000000..c03c05e --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/templates/tls-secret.yaml @@ -0,0 +1,30 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "valkey-cluster.createTlsSecret" .) }} + {{- $secretName := printf "%s-crt" (include "common.names.fullname" .) }} +{{- $ca := genCA "valkey-cluster-ca" 365 }} +{{- $releaseNamespace := .Release.Namespace }} +{{- $clusterDomain := .Values.clusterDomain }} +{{- $fullname := include "common.names.fullname" . }} +{{- $serviceName := include "common.names.fullname" . }} +{{- $headlessServiceName := printf "%s-headless" (include "common.names.fullname" .) }} +{{- $altNames := list (printf "*.%s.%s.svc.%s" $serviceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $serviceName $releaseNamespace $clusterDomain) (printf "*.%s.%s.svc.%s" $headlessServiceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $headlessServiceName $releaseNamespace $clusterDomain) "127.0.0.1" "localhost" $fullname }} +{{- $cert := genSignedCert $fullname nil $altNames 365 $ca }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.crt" "defaultValue" $cert.Cert "context" $) }} + tls.key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.key" "defaultValue" $cert.Key "context" $) }} + ca.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey-cluster/templates/update-cluster.yaml b/backing-services/gitea/charts/valkey-cluster/templates/update-cluster.yaml new file mode 100644 index 0000000..379da54 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/templates/update-cluster.yaml @@ -0,0 +1,266 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.cluster.update.addNodes ( or (and .Values.cluster.externalAccess.enabled .Values.cluster.externalAccess.service.loadBalancerIP) ( not .Values.cluster.externalAccess.enabled )) }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ template "common.names.fullname" . }}-cluster-update + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + annotations: + "helm.sh/hook": {{ .Values.updateJob.helmHook }} + {{- if or .Values.updateJob.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.updateJob.annotations .Values.commonAnnotations ) "context" . ) }} + {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + activeDeadlineSeconds: {{ .Values.updateJob.activeDeadlineSeconds }} + template: + metadata: + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.updateJob.podLabels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 8 }} + {{- if or .Values.updateJob.podAnnotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.updateJob.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 8 }} + {{- end }} + spec: + {{- include "valkey-cluster.imagePullSecrets" . | nindent 6 }} + automountServiceAccountToken: {{ .Values.updateJob.automountServiceAccountToken }} + {{- if .Values.updateJob.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.updateJob.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.updateJob.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.updateJob.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.updateJob.podAffinityPreset "customLabels" $labels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.updateJob.podAntiAffinityPreset "customLabels" $labels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.updateJob.nodeAffinityPreset.type "key" .Values.updateJob.nodeAffinityPreset.key "values" .Values.updateJob.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.updateJob.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.updateJob.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.updateJob.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.updateJob.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.updateJob.priorityClassName }} + priorityClassName: {{ .Values.updateJob.priorityClassName }} + {{- end }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "valkey-cluster.serviceAccountName" . }} + {{- if .Values.updateJob.initContainers }} + initContainers: {{- include "common.tplvalues.render" (dict "value" .Values.updateJob.initContainers "context" $) | nindent 8 }} + {{- end }} + containers: + - name: trigger + image: {{ include "valkey-cluster.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.updateJob.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.updateJob.command "context" $) | nindent 12 }} + {{- else }} + command: ['/bin/bash', '-c'] + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.updateJob.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.updateJob.args "context" $) | nindent 12 }} + {{- else }} + args: + - | + . /opt/bitnami/scripts/libnet.sh + . /opt/bitnami/scripts/libos.sh + # Backwards compatibility change + if ! [[ -f /opt/bitnami/valkey/etc/valkey.conf ]]; then + cp /opt/bitnami/valkey/etc/valkey-default.conf /opt/bitnami/valkey/etc/valkey.conf + fi + firstNodeIP=$(wait_for_dns_lookup {{ template "common.names.fullname" . }}-0.{{ template "common.names.fullname" . }}-headless 120 5) + {{- if .Values.cluster.externalAccess.enabled }} + newNodeCounter=0 + for nodeIP in $(echo "{{ .Values.cluster.update.newExternalIPs }}" | cut -d [ -f2 | cut -d ] -f 1 ); do + {{- if .Values.tls.enabled }} + while [[ $(valkey-cli -h "$nodeIP" -p "$VALKEY_TLS_PORT_NUMBER" --tls --cert ${VALKEY_TLS_CERT_FILE} --key ${VALKEY_TLS_KEY_FILE} --cacert ${VALKEY_TLS_CA_FILE} ping) != 'PONG' ]]; do + {{- else }} + while [[ $(valkey-cli -h "$nodeIP" -p "$VALKEY_PORT_NUMBER" ping) != 'PONG' ]]; do + {{- end }} + echo "Node $nodeIP not ready, waiting for all the nodes to be ready..." + sleep 5 + done + replica=() + if (( $VALKEY_CLUSTER_REPLICAS >= 1 )) && (( newNodeCounter % (( $VALKEY_CLUSTER_REPLICAS + 1 )) )); then + replica+=("--cluster-slave") + fi + {{- if .Values.tls.enabled }} + while ! valkey-cli --cluster --tls --cert ${VALKEY_TLS_CERT_FILE} --key ${VALKEY_TLS_KEY_FILE} --cacert ${VALKEY_TLS_CA_FILE} add-node "${nodeIP}:${VALKEY_TLS_PORT_NUMBER}" "{{ index .Values.cluster.externalAccess.service.loadBalancerIP 0 }}:${VALKEY_TLS_PORT_NUMBER}" ${replica[@]}; do + {{- else }} + while ! valkey-cli --cluster add-node "${nodeIP}:${VALKEY_PORT_NUMBER}" "{{ index .Values.cluster.externalAccess.service.loadBalancerIP 0 }}:${VALKEY_PORT_NUMBER}" ${replica[@]}; do + {{- end }} + echo "Add-node ${newNodeIndex} ${newNodeIP} failed, retrying" + sleep 5 + done + ((newNodeCounter += 1)) + done + + {{- if .Values.tls.enabled }} + while ! valkey-cli --cluster rebalance --tls --cert ${VALKEY_TLS_CERT_FILE} --key ${VALKEY_TLS_KEY_FILE} --cacert ${VALKEY_TLS_CA_FILE} "{{ index .Values.cluster.externalAccess.service.loadBalancerIP 0 }}:${VALKEY_TLS_PORT_NUMBER}" --cluster-use-empty-masters; do + {{- else }} + while ! valkey-cli --cluster rebalance "{{ index .Values.cluster.externalAccess.service.loadBalancerIP 0 }}:${VALKEY_PORT_NUMBER}" --cluster-use-empty-masters; do + {{- end }} + echo "Rebalance failed, retrying" + sleep 5 + {{- if .Values.tls.enabled }} + valkey-cli --cluster fix --tls --cert ${VALKEY_TLS_CERT_FILE} --key ${VALKEY_TLS_KEY_FILE} --cacert ${VALKEY_TLS_CA_FILE} "{{ index .Values.cluster.externalAccess.service.loadBalancerIP 0 }}:${VALKEY_TLS_PORT_NUMBER}" + {{- else }} + valkey-cli --cluster fix "{{ index .Values.cluster.externalAccess.service.loadBalancerIP 0 }}:${VALKEY_PORT_NUMBER}" + {{- end }} + done + + {{- else }} + # number of currently deployed valkey primary nodes + currentPrimaryNodesNum="$(( {{ .Values.cluster.update.currentNumberOfNodes }} / (( {{ .Values.cluster.update.currentNumberOfReplicas }} + 1 )) ))" + # end postion of new replicas that should be assigned to original valkey primary nodes + replicaNodesEndPos="$(( {{ .Values.cluster.update.currentNumberOfNodes }} + (($VALKEY_CLUSTER_REPLICAS - {{ .Values.cluster.update.currentNumberOfReplicas }})) * $currentPrimaryNodesNum ))" + for node in $(seq $((1+{{ .Values.cluster.update.currentNumberOfNodes }})) {{ .Values.cluster.nodes }}); do + newNodeIndex="$(($node - 1))" + newNodeIP=$(wait_for_dns_lookup "{{ template "common.names.fullname" . }}-${newNodeIndex}.{{ template "common.names.fullname" . }}-headless" 120 5) + {{- if .Values.tls.enabled }} + while [[ $(valkey-cli -h "$newNodeIP" -p "$VALKEY_TLS_PORT_NUMBER" --tls --cert ${VALKEY_TLS_CERT_FILE} --key ${VALKEY_TLS_KEY_FILE} --cacert ${VALKEY_TLS_CA_FILE} ping) != 'PONG' ]]; do + {{- else }} + while [[ $(valkey-cli -h "$newNodeIP" -p "$VALKEY_PORT_NUMBER" ping) != 'PONG' ]]; do + {{- end }} + echo "Node $newNodeIP not ready, waiting for all the nodes to be ready..." + newNodeIP=$(wait_for_dns_lookup "{{ template "common.names.fullname" . }}-${newNodeIndex}.{{ template "common.names.fullname" . }}-headless" 120 5) + sleep 5 + done + replica=() + # when the index of the new node is less than `replicaNodesEndPos`,the added node is a replica that assigned to original valkey primary node + # when the index of the new node is greater than or equal to `replicaNodesEndPos`,and it is not a multiple of `$VALKEY_CLUSTER_REPLICAS + 1`, the added node is a replica that assigned to newly added primary node + if (( $VALKEY_CLUSTER_REPLICAS >= 1 )) && (( (( $newNodeIndex < $replicaNodesEndPos )) || (( (( $newNodeIndex >= $replicaNodesEndPos )) && (( $newNodeIndex % (( $VALKEY_CLUSTER_REPLICAS + 1 )) )) )) )); then + replica+=("--cluster-slave") + fi + {{- if .Values.tls.enabled }} + while ! valkey-cli --cluster add-node --tls --cert ${VALKEY_TLS_CERT_FILE} --key ${VALKEY_TLS_KEY_FILE} --cacert ${VALKEY_TLS_CA_FILE} "${newNodeIP}:${VALKEY_TLS_PORT_NUMBER}" "${firstNodeIP}:${VALKEY_TLS_PORT_NUMBER}" ${replica[@]}; do + {{- else }} + while ! valkey-cli --cluster add-node "${newNodeIP}:${VALKEY_PORT_NUMBER}" "${firstNodeIP}:${VALKEY_PORT_NUMBER}" ${replica[@]}; do + {{- end }} + echo "Add-node ${newNodeIndex} ${newNodeIP} failed, retrying" + sleep 5 + firstNodeIP=$(wait_for_dns_lookup "{{ template "common.names.fullname" . }}-0.{{ template "common.names.fullname" . }}-headless" 120 5) + newNodeIP=$(wait_for_dns_lookup "{{ template "common.names.fullname" . }}-${newNodeIndex}.{{ template "common.names.fullname" . }}-headless" 120 5) + done + done + + {{- if .Values.tls.enabled }} + while ! valkey-cli --cluster rebalance --tls --cert ${VALKEY_TLS_CERT_FILE} --key ${VALKEY_TLS_KEY_FILE} --cacert ${VALKEY_TLS_CA_FILE} "${firstNodeIP}:${VALKEY_TLS_PORT_NUMBER}" --cluster-use-empty-masters; do + {{- else }} + while ! valkey-cli --cluster rebalance "${firstNodeIP}:${VALKEY_PORT_NUMBER}" --cluster-use-empty-masters; do + {{- end }} + echo "Rebalance failed, retrying" + sleep 5 + firstNodeIP=$(wait_for_dns_lookup "{{ template "common.names.fullname" . }}-0.{{ template "common.names.fullname" . }}-headless" 120 5) + {{- if .Values.tls.enabled }} + valkey-cli --cluster fix --tls --cert ${VALKEY_TLS_CERT_FILE} --key ${VALKEY_TLS_KEY_FILE} --cacert ${VALKEY_TLS_CA_FILE} "${firstNodeIP}:${VALKEY_TLS_PORT_NUMBER}" + {{- else }} + valkey-cli --cluster fix "${firstNodeIP}:${VALKEY_PORT_NUMBER}" + {{- end }} + done + + {{- end }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + {{- if .Values.cluster.externalAccess.enabled }} + {{- if .Values.tls.enabled }} + - name: VALKEY_TLS_CERT_FILE + value: {{ template "valkey-cluster.tlsCert" . }} + - name: VALKEY_TLS_KEY_FILE + value: {{ template "valkey-cluster.tlsCertKey" . }} + - name: VALKEY_TLS_CA_FILE + value: {{ template "valkey-cluster.tlsCACert" . }} + - name: VALKEY_TLS_PORT_NUMBER + {{- else }} + - name: VALKEY_PORT_NUMBER + {{- end }} + value: {{ .Values.cluster.externalAccess.service.port | quote }} + {{- else }} + {{- if .Values.tls.enabled }} + - name: VALKEY_TLS_CERT_FILE + value: {{ template "valkey-cluster.tlsCert" . }} + - name: VALKEY_TLS_KEY_FILE + value: {{ template "valkey-cluster.tlsCertKey" . }} + - name: VALKEY_TLS_CA_FILE + value: {{ template "valkey-cluster.tlsCACert" . }} + - name: VALKEY_TLS_PORT_NUMBER + {{- else }} + - name: VALKEY_PORT_NUMBER + {{- end }} + value: {{ .Values.valkey.containerPorts.valkey | quote }} + {{- end }} + - name: VALKEY_CLUSTER_REPLICAS + value: {{ .Values.cluster.replicas | quote }} + {{- if .Values.usePassword }} + - name: REDISCLI_AUTH + valueFrom: + secretKeyRef: + name: {{ template "valkey-cluster.secretName" . }} + key: {{ template "valkey-cluster.secretPasswordKey" . }} + {{- end }} + {{- if .Values.updateJob.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.updateJob.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.updateJob.extraEnvVarsCM .Values.updateJob.extraEnvVarsSecret }} + envFrom: + {{- if .Values.updateJob.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.updateJob.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.updateJob.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.updateJob.extraEnvVarsSecret "context" $) }} + {{- end }} + {{- end }} + {{- if .Values.updateJob.resources }} + resources: {{- toYaml .Values.updateJob.resources | nindent 12 }} + {{- else if ne .Values.updateJob.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.updateJob.resourcesPreset) | nindent 12 }} + {{- end }} + {{- if or .Values.tls.enabled .Values.updateJob.extraVolumeMounts }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if .Values.tls.enabled }} + - name: valkey-certificates + mountPath: /opt/bitnami/valkey/certs + readOnly: true + {{- end }} + {{- if .Values.updateJob.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.updateJob.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- end }} + restartPolicy: OnFailure + {{- if or .Values.tls.enabled .Values.updateJob.extraVolumes }} + volumes: + - name: empty-dir + emptyDir: {} + {{- if .Values.tls.enabled }} + - name: valkey-certificates + secret: + secretName: {{ include "common.tplvalues.render" (dict "value" .Values.tls.certificatesSecret "context" $) }} + {{- end }} + {{- if .Values.updateJob.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.updateJob.extraVolumes "context" $) | nindent 6 }} + {{- end }} + {{- end }} +{{- end }} + diff --git a/backing-services/gitea/charts/valkey-cluster/templates/valkey-role.yaml b/backing-services/gitea/charts/valkey-cluster/templates/valkey-role.yaml new file mode 100644 index 0000000..03ca0a3 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/templates/valkey-role.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.rbac.create -}} +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: Role +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: +{{- if .Values.rbac.role.rules }} +{{- toYaml .Values.rbac.role.rules | nindent 2 }} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/templates/valkey-rolebinding.yaml b/backing-services/gitea/charts/valkey-cluster/templates/valkey-rolebinding.yaml new file mode 100644 index 0000000..f9b2e8f --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/templates/valkey-rolebinding.yaml @@ -0,0 +1,23 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.rbac.create -}} +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: RoleBinding +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "common.names.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "valkey-cluster.serviceAccountName" . }} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/templates/valkey-serviceaccount.yaml b/backing-services/gitea/charts/valkey-cluster/templates/valkey-serviceaccount.yaml new file mode 100644 index 0000000..e542f1c --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/templates/valkey-serviceaccount.yaml @@ -0,0 +1,18 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "valkey-cluster.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey-cluster/templates/valkey-statefulset.yaml b/backing-services/gitea/charts/valkey-cluster/templates/valkey-statefulset.yaml new file mode 100644 index 0000000..d2421b2 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/templates/valkey-statefulset.yaml @@ -0,0 +1,509 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "valkey-cluster.createStatefulSet" .) }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.valkey.updateStrategy }} + updateStrategy: {{- toYaml .Values.valkey.updateStrategy | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.valkey.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + replicas: {{ .Values.cluster.nodes }} + serviceName: {{ include "common.names.fullname" . }}-headless + podManagementPolicy: {{ .Values.valkey.podManagementPolicy }} + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + {{- if and .Values.metrics.enabled .Values.metrics.podLabels }} + {{- toYaml .Values.metrics.podLabels | nindent 8 }} + {{- end }} + annotations: + checksum/scripts: {{ include (print $.Template.BasePath "/scripts-configmap.yaml") . | sha256sum }} + {{- if not .Values.existingSecret }} + checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} + {{- end }} + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + {{- if .Values.valkey.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.valkey.podAnnotations "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.podAnnotations "context" $) | nindent 8 }} + {{- end }} + spec: + hostNetwork: {{ .Values.valkey.hostNetwork }} + enableServiceLinks: false + {{- include "valkey-cluster.imagePullSecrets" . | nindent 6 }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "valkey-cluster.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.valkey.automountServiceAccountToken }} + {{- if .Values.valkey.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.valkey.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.valkey.priorityClassName }} + priorityClassName: {{ .Values.valkey.priorityClassName }} + {{- end }} + {{- if .Values.valkey.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.valkey.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.valkey.podAffinityPreset "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.valkey.podAntiAffinityPreset "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.valkey.nodeAffinityPreset.type "key" .Values.valkey.nodeAffinityPreset.key "values" .Values.valkey.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.valkey.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.valkey.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.valkey.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.valkey.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.valkey.shareProcessNamespace }} + shareProcessNamespace: {{ .Values.valkey.shareProcessNamespace }} + {{- end }} + {{- if .Values.valkey.schedulerName }} + schedulerName: {{ .Values.valkey.schedulerName | quote }} + {{- end }} + {{- if .Values.valkey.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" ( dict "value" .Values.valkey.topologySpreadConstraints "context" $ ) | nindent 8 }} + {{- end }} + containers: + - name: {{ include "common.names.fullname" . }} + image: {{ include "valkey-cluster.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.valkey.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.valkey.command "context" $) | nindent 12 }} + {{- else }} + command: ['/bin/bash', '-c'] + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.valkey.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.valkey.args "context" $) | nindent 12 }} + {{- else if .Values.cluster.externalAccess.enabled }} + args: + - | + # Backwards compatibility change + if ! [[ -f /opt/bitnami/valkey/etc/valkey.conf ]]; then + cp /opt/bitnami/valkey/etc/valkey-default.conf /opt/bitnami/valkey/etc/valkey.conf + fi + pod_index=($(echo "$POD_NAME" | tr "-" "\n")) + pod_index="${pod_index[-1]}" + ips=($(echo "{{ .Values.cluster.externalAccess.service.loadBalancerIP }}" | cut -d [ -f2 | cut -d ] -f 1)) + {{- if .Values.cluster.externalAccess.hostMode }} + export VALKEY_CLUSTER_ANNOUNCE_HOSTNAME="${ips[$pod_index]}" + {{- else }} + export VALKEY_CLUSTER_ANNOUNCE_IP="${ips[$pod_index]}" + {{- end }} + export VALKEY_NODES="${ips[@]}" + {{- if .Values.cluster.init }} + if [[ "$pod_index" == "0" ]]; then + export VALKEY_CLUSTER_CREATOR="yes" + export VALKEY_CLUSTER_REPLICAS="{{ .Values.cluster.replicas }}" + fi + {{- end }} + /opt/bitnami/scripts/valkey-cluster/entrypoint.sh /opt/bitnami/scripts/valkey-cluster/run.sh + {{- else }} + args: + - | + # Backwards compatibility change + if ! [[ -f /opt/bitnami/valkey/etc/valkey.conf ]]; then + echo COPYING FILE + cp /opt/bitnami/valkey/etc/valkey-default.conf /opt/bitnami/valkey/etc/valkey.conf + fi + {{- if .Values.cluster.init }} + pod_index=($(echo "$POD_NAME" | tr "-" "\n")) + pod_index="${pod_index[-1]}" + if [[ "$pod_index" == "0" ]]; then + export VALKEY_CLUSTER_CREATOR="yes" + export VALKEY_CLUSTER_REPLICAS="{{ .Values.cluster.replicas }}" + fi + {{- end }} + /opt/bitnami/scripts/valkey-cluster/entrypoint.sh /opt/bitnami/scripts/valkey-cluster/run.sh + {{- end }} + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + {{- if and .Values.cluster.externalAccess.enabled .Values.cluster.externalAccess.hostMode }} + - name: VALKEY_CLUSTER_DYNAMIC_IPS + value: "yes" + - name: VALKEY_CLUSTER_PREFERRED_ENDPOINT_TYPE + value: "hostname" + {{- else if .Values.cluster.externalAccess.enabled }} + - name: VALKEY_CLUSTER_DYNAMIC_IPS + value: "no" + {{- else }} + - name: VALKEY_NODES + value: "{{ $count := .Values.cluster.nodes | int }}{{ range $i, $v := until $count }}{{ include "common.names.fullname" $ }}-{{ $i }}.{{ template "common.names.fullname" $ }}-headless {{ end }}" + {{- end }} + {{- if .Values.usePassword }} + - name: REDISCLI_AUTH + valueFrom: + secretKeyRef: + name: {{ template "valkey-cluster.secretName" . }} + key: {{ template "valkey-cluster.secretPasswordKey" . }} + {{- if .Values.usePasswordFiles }} + - name: VALKEY_PASSWORD_FILE + value: "/opt/bitnami/valkey/secrets/valkey-password" + {{- else }} + - name: VALKEY_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "valkey-cluster.secretName" . }} + key: {{ template "valkey-cluster.secretPasswordKey" . }} + {{- end }} + {{- else }} + - name: ALLOW_EMPTY_PASSWORD + value: "yes" + {{- end }} + - name: VALKEY_AOF_ENABLED + value: {{ .Values.valkey.useAOFPersistence | quote }} + - name: VALKEY_TLS_ENABLED + value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} + {{- if .Values.tls.enabled }} + - name: VALKEY_TLS_PORT_NUMBER + value: {{ .Values.valkey.containerPorts.valkey | quote }} + - name: VALKEY_TLS_AUTH_CLIENTS + value: {{ ternary "yes" "no" .Values.tls.authClients | quote }} + - name: VALKEY_TLS_CERT_FILE + value: {{ template "valkey-cluster.tlsCert" . }} + - name: VALKEY_TLS_KEY_FILE + value: {{ template "valkey-cluster.tlsCertKey" . }} + - name: VALKEY_TLS_CA_FILE + value: {{ template "valkey-cluster.tlsCACert" . }} + {{- if .Values.tls.dhParamsFilename }} + - name: VALKEY_TLS_DH_PARAMS_FILE + value: {{ template "valkey-cluster.tlsDHParams" . }} + {{- end }} + {{- else }} + - name: VALKEY_PORT_NUMBER + value: {{ .Values.valkey.containerPorts.valkey | quote }} + {{- end }} + {{- if .Values.valkey.extraEnvVars }} + {{- include "common.tplvalues.render" ( dict "value" .Values.valkey.extraEnvVars "context" $ ) | nindent 12 }} + {{- end }} + {{- if or .Values.valkey.extraEnvVarsCM .Values.valkey.extraEnvVarsSecret }} + envFrom: + {{- if .Values.valkey.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" ( dict "value" .Values.valkey.extraEnvVarsCM "context" $ ) }} + {{- end }} + {{- if .Values.valkey.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" ( dict "value" .Values.valkey.extraEnvVarsSecret "context" $ ) }} + {{- end }} + {{- end }} + ports: + - name: tcp-redis + containerPort: {{ .Values.valkey.containerPorts.valkey }} + - name: tcp-redis-bus + containerPort: {{ .Values.valkey.containerPorts.bus }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.valkey.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.valkey.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.valkey.livenessProbe.enabled }} + livenessProbe: + initialDelaySeconds: {{ .Values.valkey.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.valkey.livenessProbe.periodSeconds }} + # One second longer than command timeout should prevent generation of zombie processes. + timeoutSeconds: {{ add1 .Values.valkey.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.valkey.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.valkey.livenessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /scripts/ping_liveness_local.sh {{ .Values.valkey.livenessProbe.timeoutSeconds }} + {{- end }} + {{- if .Values.valkey.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.valkey.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.valkey.readinessProbe.enabled }} + readinessProbe: + initialDelaySeconds: {{ .Values.valkey.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.valkey.readinessProbe.periodSeconds }} + # One second longer than command timeout should prevent generation of zombie processes. + timeoutSeconds: {{ add1 .Values.valkey.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.valkey.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.valkey.readinessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /scripts/ping_readiness_local.sh {{ .Values.valkey.readinessProbe.timeoutSeconds }} + {{- end }} + {{- if .Values.valkey.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.valkey.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.valkey.startupProbe.enabled }} + startupProbe: + tcpSocket: + port: tcp-redis + initialDelaySeconds: {{ .Values.valkey.startupProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.valkey.startupProbe.periodSeconds }} + timeoutSeconds: {{ .Values.valkey.startupProbe.timeoutSeconds }} + successThreshold: {{ .Values.valkey.startupProbe.successThreshold }} + failureThreshold: {{ .Values.valkey.startupProbe.failureThreshold }} + {{- end }} + {{- if .Values.valkey.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.valkey.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.valkey.resources }} + resources: {{- toYaml .Values.valkey.resources | nindent 12 }} + {{- else if ne .Values.valkey.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.valkey.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: scripts + mountPath: /scripts + {{- if and .Values.usePassword .Values.usePasswordFiles }} + - name: valkey-password + mountPath: /opt/bitnami/valkey/secrets/ + {{- end }} + - name: valkey-data + mountPath: {{ .Values.persistence.path }} + subPath: {{ .Values.persistence.subPath }} + - name: default-config + mountPath: /opt/bitnami/valkey/etc/valkey-default.conf + subPath: valkey-default.conf + - name: empty-dir + mountPath: /opt/bitnami/valkey/etc/ + subPath: app-conf-dir + - name: empty-dir + mountPath: /opt/bitnami/valkey/tmp + subPath: app-tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/valkey/logs + subPath: app-logs-dir + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if .Values.tls.enabled }} + - name: valkey-certificates + mountPath: /opt/bitnami/valkey/certs + readOnly: true + {{- end }} + {{- if .Values.valkey.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.valkey.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ template "valkey-cluster.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.metrics.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.metrics.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -c + - | + {{- if and .Values.usePassword .Values.usePasswordFiles }} + export REDIS_PASSWORD="$(< "${REDIS_PASSWORD_FILE}")" + {{- end }} + redis_exporter{{- range $key, $value := .Values.metrics.extraArgs }} --{{ $key }}={{ $value }}{{- end }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + - name: REDIS_ALIAS + value: {{ template "common.names.fullname" . }} + - name: REDIS_ADDR + value: {{ printf "%s://127.0.0.1:%g" (ternary "rediss" "redis" .Values.tls.enabled) .Values.valkey.containerPorts.valkey | quote }} + {{- if .Values.usePassword }} + {{- if .Values.usePasswordFiles }} + - name: REDIS_PASSWORD_FILE + value: "/opt/bitnami/valkey/secrets/valkey-password" + {{- else }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "valkey-cluster.secretName" . }} + key: {{ template "valkey-cluster.secretPasswordKey" . }} + {{- end }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: REDIS_EXPORTER_TLS_CLIENT_KEY_FILE + value: {{ template "valkey-cluster.tlsCertKey" . }} + - name: REDIS_EXPORTER_TLS_CLIENT_CERT_FILE + value: {{ template "valkey-cluster.tlsCert" . }} + - name: REDIS_EXPORTER_TLS_CA_CERT_FILE + value: {{ template "valkey-cluster.tlsCACert" . }} + {{- end }} + - name: REDIS_EXPORTER_WEB_LISTEN_ADDRESS + value: {{ printf ":%v" .Values.metrics.containerPorts.http }} + {{- if .Values.metrics.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or (and .Values.usePassword .Values.usePasswordFiles) .Values.tls.enabled }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if and .Values.usePassword .Values.usePasswordFiles }} + - name: valkey-password + mountPath: /opt/bitnami/valkey/secrets/ + {{- end }} + {{- if .Values.tls.enabled }} + - name: valkey-certificates + mountPath: /opt/bitnami/valkey/certs + readOnly: true + {{- end }} + {{- end }} + ports: + - name: http-metrics + containerPort: {{ .Values.metrics.containerPorts.http }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- else if ne .Values.metrics.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.metrics.resourcesPreset) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.valkey.sidecars }} + {{- include "common.tplvalues.render" ( dict "value" .Values.valkey.sidecars "context" $ ) | nindent 8 }} + {{- end }} + {{- $needsVolumePermissions := and .Values.volumePermissions.enabled .Values.containerSecurityContext.enabled }} + {{- if or $needsVolumePermissions .Values.sysctlImage.enabled .Values.valkey.initContainers }} + initContainers: + {{- if $needsVolumePermissions }} + - name: volume-permissions + image: {{ include "valkey-cluster.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: ["/bin/chown", "-R", "{{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }}", "{{ .Values.persistence.path }}"] + securityContext: + runAsUser: 0 + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- else if ne .Values.volumePermissions.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.volumePermissions.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: valkey-data + mountPath: {{ .Values.persistence.path }} + subPath: {{ .Values.persistence.subPath }} + {{- end }} + {{- if .Values.sysctlImage.enabled }} + - name: init-sysctl + image: {{ template "valkey-cluster.sysctl.image" . }} + imagePullPolicy: {{ default "" .Values.sysctlImage.pullPolicy | quote }} + {{- if .Values.sysctlImage.resources }} + resources: {{- toYaml .Values.sysctlImage.resources | nindent 12 }} + {{- else if ne .Values.sysctlImage.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.sysctlImage.resourcesPreset) | nindent 12 }} + {{- end }} + {{- if .Values.sysctlImage.mountHostSys }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: host-sys + mountPath: /host-sys + {{- end }} + command: + {{- toYaml .Values.sysctlImage.command | nindent 12 }} + {{- if .Values.sysctlImage.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.sysctlImage.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.valkey.initContainers }} + {{- toYaml .Values.valkey.initContainers | nindent 8 }} + {{- end }} + {{- end }} + volumes: + - name: scripts + configMap: + name: {{ include "common.names.fullname" . }}-scripts + defaultMode: 0755 + {{- if and .Values.usePassword .Values.usePasswordFiles }} + - name: valkey-password + secret: + secretName: {{ include "valkey-cluster.secretName" . }} + items: + - key: {{ include "valkey-cluster.secretPasswordKey" . }} + path: valkey-password + {{- end }} + - name: default-config + configMap: + name: {{ include "common.names.fullname" . }}-default + {{- if .Values.sysctlImage.mountHostSys }} + - name: host-sys + hostPath: + path: /sys + {{- end }} + - name: empty-dir + emptyDir: {} + {{- if .Values.valkey.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.valkey.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: valkey-certificates + secret: + secretName: {{ include "valkey-cluster.tlsSecretName" . }} + defaultMode: 256 + {{- end }} + {{- if not .Values.persistence.enabled }} + - name: valkey-data + emptyDir: {} + {{- end }} + {{- if .Values.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + {{- if .Values.persistence.enabled }} + volumeClaimTemplates: + - metadata: + name: valkey-data + labels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 10 }} + {{- if .Values.persistence.labels }} + {{- include "common.tplvalues.render" (dict "value" .Values.persistence.labels "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.persistence.annotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.annotations "context" $) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) | nindent 8 }} + {{- if or .Values.persistence.matchLabels .Values.persistence.matchExpressions }} + selector: + {{- if .Values.persistence.matchLabels }} + matchLabels: + {{- toYaml .Values.persistence.matchLabels | nindent 12 }} + {{- end -}} + {{- if .Values.persistence.matchExpressions }} + matchExpressions: + {{- toYaml .Values.persistence.matchExpressions | nindent 12 }} + {{- end -}} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey-cluster/templates/valkey-svc.yaml b/backing-services/gitea/charts/valkey-cluster/templates/valkey-svc.yaml new file mode 100644 index 0000000..11288a9 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/templates/valkey-svc.yaml @@ -0,0 +1,51 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.service.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + {{- if or .Values.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + {{- if and .Values.service.clusterIP (eq .Values.service.type "ClusterIP") }} + clusterIP: {{ .Values.service.clusterIP }} + {{- end }} + {{- if or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ .Values.service.loadBalancerSourceRanges }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + {{- if .Values.service.sessionAffinity }} + sessionAffinity: {{ .Values.service.sessionAffinity }} + {{- end }} + {{- if .Values.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + ports: + - name: tcp-redis + port: {{ .Values.service.ports.valkey }} + targetPort: tcp-redis + protocol: TCP + {{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.valkey)) }} + nodePort: {{ .Values.service.nodePorts.valkey }} + {{- else if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.valkey.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} diff --git a/backing-services/gitea/charts/valkey-cluster/values.yaml b/backing-services/gitea/charts/valkey-cluster/values.yaml new file mode 100644 index 0000000..f13ea71 --- /dev/null +++ b/backing-services/gitea/charts/valkey-cluster/values.yaml @@ -0,0 +1,1167 @@ +# Copyright Broadcom, Inc. All Rights Reserved. +# SPDX-License-Identifier: APACHE-2.0 + +## @section Global parameters +## 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, imagePullSecrets and storageClass +## + +## @param global.imageRegistry Global Docker image registry +## @param global.imagePullSecrets Global Docker registry secret names as an array +## @param global.defaultStorageClass Global default StorageClass for Persistent Volume(s) +## @param global.storageClass DEPRECATED: use global.defaultStorageClass instead +## @param global.valkey.password Valkey password (overrides `password`) +## +global: + imageRegistry: "" + ## E.g. + ## imagePullSecrets: + ## - myRegistryKeySecretName + ## + imagePullSecrets: [] + defaultStorageClass: "" + storageClass: "" + ## Security parameters + ## + security: + ## @param global.security.allowInsecureImages Allows skipping image verification + allowInsecureImages: false + valkey: + password: "" + ## Compatibility adaptations for Kubernetes platforms + ## + compatibility: + ## Compatibility adaptations for Openshift + ## + openshift: + ## @param global.compatibility.openshift.adaptSecurityContext Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) + ## + adaptSecurityContext: auto +## @section Valkey Cluster Common parameters +## + +## @param nameOverride String to partially override common.names.fullname template (will maintain the release name) +## +nameOverride: "" +## @param fullnameOverride String to fully override common.names.fullname template +## +fullnameOverride: "" +## @param clusterDomain Kubernetes Cluster Domain +## +clusterDomain: cluster.local +## @param commonAnnotations Annotations to add to all deployed objects +## +commonAnnotations: {} +## @param commonLabels Labels to add to all deployed objects +## +commonLabels: {} +## @param extraDeploy Array of extra objects to deploy with the release (evaluated as a template) +## +extraDeploy: [] +## Enable diagnostic mode in the deployment +## +diagnosticMode: + ## @param diagnosticMode.enabled Enable diagnostic mode (all probes will be disabled and the command will be overridden) + ## + enabled: false + ## @param diagnosticMode.command Command to override all containers in the deployment + ## + command: + - sleep + ## @param diagnosticMode.args Args to override all containers in the deployment + ## + args: + - infinity +## Bitnami Valkey image version +## ref: https://hub.docker.com/r/bitnami/valkey/tags/ +## @param image.registry [default: REGISTRY_NAME] Valkey cluster image registry +## @param image.repository [default: REPOSITORY_NAME/valkey-cluster] Valkey cluster image repository +## @skip image.tag Valkey cluster image tag (immutable tags are recommended) +## @param image.digest Valkey cluster image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag +## @param image.pullPolicy Valkey cluster image pull policy +## @param image.pullSecrets Specify docker-registry secret names as an array +## @param image.debug Enable image debug mode +## +image: + registry: docker.io + repository: bitnami/valkey-cluster + tag: 8.1.3-debian-12-r3 + digest: "" + ## Specify a imagePullPolicy + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Enable debug mode + ## + debug: false +## Network Policy configuration +## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ +## +networkPolicy: + ## @param networkPolicy.enabled Enable creation of NetworkPolicy resources + ## + enabled: true + ## @param networkPolicy.allowExternal The Policy model to apply + ## When set to false, only pods with the correct client label will have network access to the ports Valkey Cluster is + ## listening on. When true, Valkey Cluster will accept connections from any source (with the correct destination port). + ## + allowExternal: true + ## @param networkPolicy.allowExternalEgress Allow the pod to access any range of port and all destinations. + ## + allowExternalEgress: true + ## @param networkPolicy.extraIngress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraIngress: + ## - ports: + ## - port: 1234 + ## from: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraIngress: [] + ## @param networkPolicy.extraEgress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraEgress: + ## - ports: + ## - port: 1234 + ## to: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraEgress: [] + ## @param networkPolicy.ingressNSMatchLabels [object] Labels to match to allow traffic from other namespaces + ## @param networkPolicy.ingressNSPodMatchLabels [object] Pod labels to match to allow traffic from other namespaces + ## + ingressNSMatchLabels: {} + ingressNSPodMatchLabels: {} +serviceAccount: + ## @param serviceAccount.create Specifies whether a ServiceAccount should be created + ## + create: true + ## @param serviceAccount.name The name of the ServiceAccount to create + ## If not set and create is true, a name is generated using the fullname template + ## + name: "" + ## @param serviceAccount.annotations Annotations for Cassandra Service Account + ## + annotations: {} + ## @param serviceAccount.automountServiceAccountToken Automount API credentials for a service account. + ## + automountServiceAccountToken: false +rbac: + ## @param rbac.create Specifies whether RBAC resources should be created + ## + create: false + role: + ## @param rbac.role.rules Rules to create. It follows the role specification + ## rules: + ## - apiGroups: + ## - extensions + ## resources: + ## - podsecuritypolicies + ## verbs: + ## - use + ## resourceNames: + ## - gce.unprivileged + ## + rules: [] +## Valkey pod Security Context +## @param podSecurityContext.enabled Enable Valkey pod Security Context +## @param podSecurityContext.fsGroupChangePolicy Set filesystem group change policy +## @param podSecurityContext.supplementalGroups Set filesystem extra groups +## @param podSecurityContext.fsGroup Group ID for the pods +## @param podSecurityContext.sysctls Set namespaced sysctls for the pods +## +podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + supplementalGroups: [] + fsGroup: 1001 + ## Uncomment the setting below to increase the net.core.somaxconn value + ## e.g: + ## sysctls: + ## - name: net.core.somaxconn + ## value: "10000" + ## + sysctls: [] +## @param podDisruptionBudget DEPRECATED please use pdb instead +## ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions +## +podDisruptionBudget: {} +## Pod Disruption Budget configuration +## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ +## +pdb: + ## @param pdb.create Created a PodDisruptionBudget + ## + create: true + ## @param pdb.minAvailable Min number of pods that must still be available after the eviction. + ## You can specify an integer or a percentage by setting the value to a string representation of a percentage (eg. "50%"). It will be disabled if set to 0 + ## + minAvailable: "" + ## @param pdb.maxUnavailable Max number of pods that can be unavailable after the eviction. + ## You can specify an integer or a percentage by setting the value to a string representation of a percentage (eg. "50%"). It will be disabled if set to 0 + ## + maxUnavailable: "" +## Containers Security Context +## @param containerSecurityContext.enabled Enabled containers' Security Context +## @param containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container +## @param containerSecurityContext.runAsUser Set containers' Security Context runAsUser +## @param containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup +## @param containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot +## @param containerSecurityContext.privileged Set container's Security Context privileged +## @param containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem +## @param containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation +## @param containerSecurityContext.capabilities.drop List of capabilities to be dropped +## @param containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile +## +containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" +## @param usePassword Use password authentication +## +usePassword: true +## @param password Valkey password (ignored if existingSecret set) +## Defaults to a random 10-character alphanumeric string if not set and usePassword is true +## ref: https://github.com/bitnami/containers/tree/main/bitnami/valkey#setting-the-server-password-on-first-run +## +password: "" +## @param existingSecret Name of existing secret object (for password authentication) +## +existingSecret: "" +## @param existingSecretPasswordKey Name of key containing password to be retrieved from the existing secret +## +existingSecretPasswordKey: "" +## @param usePasswordFiles Mount passwords as files instead of environment variables +## +usePasswordFiles: true +## +## TLS configuration +## +tls: + ## @param tls.enabled Enable TLS support for replication traffic + ## + enabled: false + ## @param tls.authClients Require clients to authenticate or not + ## + authClients: true + ## @param tls.autoGenerated Generate automatically self-signed TLS certificates + ## + autoGenerated: false + ## @param tls.existingSecret The name of the existing secret that contains the TLS certificates + ## + existingSecret: "" + ## @param tls.certificatesSecret DEPRECATED. Use tls.existingSecret instead + ## + certificatesSecret: "" + ## @param tls.certFilename Certificate filename + ## + certFilename: "" + ## @param tls.certKeyFilename Certificate key filename + ## + certKeyFilename: "" + ## @param tls.certCAFilename CA Certificate filename + ## + certCAFilename: "" + ## @param tls.dhParamsFilename File containing DH params (in order to support DH based ciphers) + ## + dhParamsFilename: "" +## Valkey Service properties for standalone mode. +## +service: + ## @param service.ports.valkey Kubernetes Valkey service port + ## + ports: + valkey: 6379 + ## Node ports to expose + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## @param service.nodePorts.valkey Node port for Valkey + ## + nodePorts: + valkey: "" + ## @param service.extraPorts Extra ports to expose in the service (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param service.annotations Provide any additional annotations which may be required. + ## This can be used to set the LoadBalancer service type to internal only. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + annotations: {} + ## @param service.labels Additional labels for valkey service + ## + labels: {} + ## @param service.type Service type for default valkey service + ## Setting this to LoadBalancer may require corresponding service annotations for loadbalancer creation to succeed. + ## Currently supported types are ClusterIP (default) and LoadBalancer + ## + type: ClusterIP + ## @param service.clusterIP Service Cluster IP + ## e.g.: + ## clusterIP: None + ## + clusterIP: "" + ## @param service.loadBalancerIP Load balancer IP if `service.type` is `LoadBalancer` + ## If service.type is LoadBalancer, request a specific static IP address if supported by the cloud provider, otherwise leave blank + ## + loadBalancerIP: "" + ## @param service.loadBalancerSourceRanges Service Load Balancer sources + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param service.externalTrafficPolicy Service external traffic policy + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## Headless service properties + ## + headless: + ## @param service.headless.annotations Annotations for the headless service. + ## + annotations: {} +## Enable persistence using Persistent Volume Claims +## ref: https://kubernetes.io/docs/concepts/storage/persistent-volumes/ +## +persistence: + ## @param persistence.enabled Enable persistence on Valkey + ## If enabled, nodes are using Persistent Volume Claims + ## If disabled, an emptyDir volume is used. This is not recommended. + ## ref: https://github.com/bitnami/charts/tree/main/bitnami/valkey-cluster#persistence + ## + enabled: true + ## @param persistence.path Path to mount the volume at, to use other images Valkey images. + ## + path: /bitnami/valkey/data + ## @param persistence.subPath The subdirectory of the volume to mount to, useful in dev environments and one PV for multiple services + ## + subPath: "" + ## @param persistence.storageClass Storage class of backing PVC + ## 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: "" + ## @param persistence.annotations Persistent Volume Claim annotations + ## + annotations: {} + ## @param persistence.labels Persistent Volume Claim labels + ## + labels: {} + ## @param persistence.accessModes Persistent Volume Access Modes + ## + accessModes: + - ReadWriteOnce + ## @param persistence.size Size of data volume + ## + size: 8Gi + ## @param persistence.matchLabels Persistent Volume selectors + ## https://kubernetes.io/docs/concepts/storage/persistent-volumes/#selector + ## + matchLabels: {} + ## @param persistence.matchExpressions matchExpressions Persistent Volume selectors + ## + matchExpressions: {} +## persistentVolumeClaimRetentionPolicy +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention +## @param persistentVolumeClaimRetentionPolicy.enabled Controls if and how PVCs are deleted during the lifecycle of a StatefulSet +## @param persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced +## @param persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted +persistentVolumeClaimRetentionPolicy: + enabled: false + whenScaled: Retain + whenDeleted: Retain +## Init containers parameters: +## volumePermissions: Change the owner of the persist volume mountpoint to RunAsUser:fsGroup +## +volumePermissions: + ## @param volumePermissions.enabled Enable init container that changes volume permissions in the registry (for cases where the default k8s `runAsUser` and `fsUser` values do not work) + ## + enabled: false + ## @param volumePermissions.image.registry [default: REGISTRY_NAME] Init container volume-permissions image registry + ## @param volumePermissions.image.repository [default: REPOSITORY_NAME/os-shell] Init container volume-permissions image repository + ## @skip volumePermissions.image.tag Init container volume-permissions image tag + ## @param volumePermissions.image.digest Init container volume-permissions image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param volumePermissions.image.pullPolicy Init container volume-permissions image pull policy + ## @param volumePermissions.image.pullSecrets Specify docker-registry secret names as an array + ## + image: + registry: docker.io + repository: bitnami/os-shell + tag: 12-debian-12-r51 + digest: "" + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Containers Security Context + ## @param volumePermissions.containerSecurityContext.enabled Enable Containers' Security Context + ## @param volumePermissions.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param volumePermissions.containerSecurityContext.runAsUser User ID for the containers. + ## @param volumePermissions.containerSecurityContext.privileged Run container as privileged + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 0 + privileged: false + ## Container resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param volumePermissions.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if volumePermissions.resources is set (volumePermissions.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param volumePermissions.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} +## @section Valkey statefulset parameters +## +valkey: + ## @param valkey.command Valkey entrypoint string. The command `valkey-server` is executed if this is not provided + ## + command: [] + ## @param valkey.args Arguments for the provided command if needed + ## + args: [] + ## @param valkey.updateStrategy.type Argo Workflows statefulset strategy type + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## + updateStrategy: + ## StrategyType + ## Can be set to RollingUpdate or OnDelete + ## + type: RollingUpdate + ## @param valkey.updateStrategy.rollingUpdate.partition Partition update strategy + ## https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#partitions + ## + rollingUpdate: + partition: 0 + ## @param valkey.podManagementPolicy Statefulset Pod management policy, it needs to be Parallel to be able to complete the cluster join + ## Ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#pod-management-policies + ## + podManagementPolicy: Parallel + ## @param valkey.automountServiceAccountToken Mount Service Account token in pod + ## + automountServiceAccountToken: false + ## @param valkey.hostAliases Deployment pod host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param valkey.hostNetwork Host networking requested for this pod. Use the host's network namespace. + ## https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#podspec-v1-core + ## + hostNetwork: false + ## @param valkey.useAOFPersistence Whether to use AOF Persistence mode or not + ## It is strongly recommended to use this type when dealing with clusters + ## ref: https://valkey.io/topics/persistence#append-only-file + ## ref: https://valkey.io/topics/cluster-tutorial#creating-and-using-a-valkey-cluster + ## + useAOFPersistence: "yes" + ## @param valkey.containerPorts.valkey Valkey port + ## @param valkey.containerPorts.bus The busPort should be obtained adding 10000 to the valkeyPort. By default: 10000 + 6379 = 16379 + ## + containerPorts: + valkey: 6379 + bus: 16379 + ## @param valkey.lifecycleHooks LifecycleHook to set additional configuration before or after startup. Evaluated as a template + ## + lifecycleHooks: {} + ## @param valkey.extraVolumes Extra volumes to add to the deployment + ## + extraVolumes: [] + ## @param valkey.extraVolumeMounts Extra volume mounts to add to the container + ## + extraVolumeMounts: [] + ## @param valkey.customLivenessProbe Override default liveness probe + ## + customLivenessProbe: {} + ## @param valkey.customReadinessProbe Override default readiness probe + ## + customReadinessProbe: {} + ## @param valkey.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param valkey.initContainers Extra init containers to add to the deployment + ## + initContainers: [] + ## @param valkey.sidecars Extra sidecar containers to add to the deployment + ## + sidecars: [] + ## @param valkey.podLabels Additional labels for Valkey pod + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param valkey.priorityClassName Valkey Primary pod priorityClassName + ## + priorityClassName: "" + ## @param valkey.defaultConfigOverride Optional default Valkey configuration for the nodes + ## If not set, the default Valkey configuration from the chart is used + ## ref: https://valkey.io/topics/config + ## + defaultConfigOverride: "" + ## @param valkey.configmap Additional Valkey configuration for the nodes + ## ref: https://valkey.io/topics/config + ## + configmap: "" + ## @param valkey.extraEnvVars An array to add extra environment variables + ## For example: + ## - name: BEARER_AUTH + ## value: true + ## + extraEnvVars: [] + ## @param valkey.extraEnvVarsCM ConfigMap with extra environment variables + ## + extraEnvVarsCM: "" + ## @param valkey.extraEnvVarsSecret Secret with extra environment variables + ## + extraEnvVarsSecret: "" + ## @param valkey.podAnnotations Valkey additional annotations + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podAnnotations: {} + ## Valkey resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param valkey.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if valkey.resources is set (valkey.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param valkey.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## @param valkey.schedulerName Use an alternate scheduler, e.g. "stork". + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param valkey.shareProcessNamespace Enable shared process namespace in a pod. + ## If set to false (default), each container will run in separate namespace, valkey will have PID=1. + ## If set to true, the /pause will run as init process and will reap any zombie PIDs, + ## for example, generated by a custom exec probe running longer than a probe timeoutSeconds. + ## Enable this only if customLivenessProbe or customReadinessProbe is used and zombie PIDs are accumulating. + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/share-process-namespace/ + ## + shareProcessNamespace: false + ## Configure extra options for Valkey liveness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) + ## @param valkey.livenessProbe.enabled Enable livenessProbe + ## @param valkey.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param valkey.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param valkey.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param valkey.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param valkey.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## Configure extra options for Valkey readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) + ## @param valkey.readinessProbe.enabled Enable readinessProbe + ## @param valkey.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param valkey.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param valkey.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param valkey.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param valkey.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 5 + ## @param valkey.startupProbe.enabled Enable startupProbe + ## @param valkey.startupProbe.path Path to check for startupProbe + ## @param valkey.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param valkey.startupProbe.periodSeconds Period seconds for startupProbe + ## @param valkey.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param valkey.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param valkey.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + path: / + initialDelaySeconds: 300 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param valkey.podAffinityPreset Valkey pod affinity preset. Ignored if `valkey.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param valkey.podAntiAffinityPreset Valkey pod anti-affinity preset. Ignored if `valkey.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Valkey node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param valkey.nodeAffinityPreset.type Valkey node affinity preset type. Ignored if `valkey.affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param valkey.nodeAffinityPreset.key Valkey node label key to match Ignored if `valkey.affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param valkey.nodeAffinityPreset.values Valkey node label values to match. Ignored if `valkey.affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param valkey.affinity Affinity settings for Valkey pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## Note: valkey.podAffinityPreset, valkey.podAntiAffinityPreset, and valkey.nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## @param valkey.nodeSelector Node labels for Valkey pods assignment + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: {} + ## @param valkey.tolerations Tolerations for Valkey pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param valkey.topologySpreadConstraints Pod topology spread constraints for Valkey pod + ## https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## The value is evaluated as a template + ## + topologySpreadConstraints: [] +## @section Cluster update job parameters +## + +## Cluster update job settings +## +updateJob: + ## @param updateJob.activeDeadlineSeconds Number of seconds the Job to create the cluster will be waiting for the Nodes to be ready. + ## + activeDeadlineSeconds: 600 + ## @param updateJob.command Container command (using container default if not set) + ## + command: [] + ## @param updateJob.args Container args (using container default if not set) + ## + args: [] + ## @param updateJob.automountServiceAccountToken Mount Service Account token in pod + ## + automountServiceAccountToken: false + ## @param updateJob.hostAliases Deployment pod host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param updateJob.helmHook Job Helm hook + ## https://helm.sh/docs/topics/charts_hooks/#the-available-hooks + ## + helmHook: post-upgrade + ## @param updateJob.annotations Job annotations + ## + annotations: {} + ## @param updateJob.podAnnotations Job pod annotations + ## + podAnnotations: {} + ## @param updateJob.podLabels Pod extra labels + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param updateJob.extraEnvVars An array to add extra environment variables + ## For example: + ## - name: BEARER_AUTH + ## value: true + ## + extraEnvVars: [] + ## @param updateJob.extraEnvVarsCM ConfigMap containing extra environment variables + ## + extraEnvVarsCM: "" + ## @param updateJob.extraEnvVarsSecret Secret containing extra environment variables + ## + extraEnvVarsSecret: "" + ## @param updateJob.extraVolumes Extra volumes to add to the deployment + ## + extraVolumes: [] + ## @param updateJob.extraVolumeMounts Extra volume mounts to add to the container + ## + extraVolumeMounts: [] + ## @param updateJob.initContainers Extra init containers to add to the deployment + ## + initContainers: [] + ## @param updateJob.podAffinityPreset Update job pod affinity preset. Ignored if `updateJob.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param updateJob.podAntiAffinityPreset Update job pod anti-affinity preset. Ignored if `updateJob.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Update job node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param updateJob.nodeAffinityPreset.type Update job node affinity preset type. Ignored if `updateJob.affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param updateJob.nodeAffinityPreset.key Update job node label key to match Ignored if `updateJob.affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param updateJob.nodeAffinityPreset.values Update job node label values to match. Ignored if `updateJob.affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param updateJob.affinity Affinity for update job pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## Note: updateJob.podAffinityPreset, updateJob.podAntiAffinityPreset, and updateJob.nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## @param updateJob.nodeSelector Node labels for update job pods assignment + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: {} + ## @param updateJob.tolerations Tolerations for update job pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param updateJob.priorityClassName Priority class name + ## + priorityClassName: "" + ## Container resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## 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:'. + ## @param updateJob.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if updateJob.resources is set (updateJob.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param updateJob.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} +## @section Cluster management parameters +## + +## Valkey Cluster settings +## +cluster: + ## @param cluster.init Enable the initialization of the Valkey Cluster + ## + init: true + ## Number of Valkey nodes to be deployed + ## + ## Note: + ## This is total number of nodes including the replicas. Meaning there will be 3 primary and 3 replica + ## nodes (as replica count is set to 1 by default, there will be 1 replica per primary node). + ## Hence, nodes = numberOfPrimaryNodes + numberOfPrimaryNodes * replicas + ## + ## @param cluster.nodes The number of primary nodes should always be >= 3, otherwise cluster creation will fail + ## + nodes: 6 + ## @param cluster.replicas Number of replicas for every primary in the cluster + ## Parameter to be passed as --cluster-replicas to the valkey-cli --cluster create + ## 1 means that we want a replica for every primary created + ## + replicas: 1 + ## Configuration to access the Valkey Cluster from outside the Kubernetes cluster + ## + externalAccess: + ## @param cluster.externalAccess.enabled Enable access to the Valkey + ## + enabled: false + ## @param cluster.externalAccess.hostMode Set cluster preferred endpoint type as hostname + ## + hostMode: false + service: + ## @param cluster.externalAccess.service.disableLoadBalancerIP Disable use of `Service.spec.loadBalancerIP` + ## + disableLoadBalancerIP: false + ## @param cluster.externalAccess.service.loadBalancerIPAnnotaion Name of annotation to specify fixed IP for service in. Disables `Service.spec.loadBalancerIP` if not empty + ## + loadBalancerIPAnnotaion: "" + ## @param cluster.externalAccess.service.type Type for the services used to expose every Pod + ## At this moment only LoadBalancer is supported + ## + type: LoadBalancer + ## @param cluster.externalAccess.service.port Port for the services used to expose every Pod + ## + port: 6379 + ## @param cluster.externalAccess.service.loadBalancerIP Array of load balancer IPs for each Valkey node. Length must be the same as cluster.nodes + ## + loadBalancerIP: [] + ## @param cluster.externalAccess.service.loadBalancerSourceRanges Service Load Balancer sources + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param cluster.externalAccess.service.annotations Annotations to add to the services used to expose every Pod of the Valkey Cluster + ## + annotations: {} + ## This section allows to update the Valkey cluster nodes. + ## + update: + ## @param cluster.update.addNodes Boolean to specify if you want to add nodes after the upgrade + ## Setting this to true a hook will add nodes to the Valkey cluster after the upgrade. currentNumberOfNodes and currentNumberOfReplicas is required + ## + addNodes: false + ## @param cluster.update.currentNumberOfNodes Number of currently deployed Valkey nodes + ## + currentNumberOfNodes: 6 + ## @param cluster.update.currentNumberOfReplicas Number of currently deployed Valkey replicas + ## + currentNumberOfReplicas: 1 + ## @param cluster.update.newExternalIPs External IPs obtained from the services for the new nodes to add to the cluster + ## + newExternalIPs: [] +## @section Metrics sidecar parameters +## + +## Prometheus Exporter / Metrics +## +metrics: + ## @param metrics.enabled Start a side-car prometheus exporter + ## + enabled: false + ## @param metrics.image.registry [default: REGISTRY_NAME] Valkey exporter image registry + ## @param metrics.image.repository [default: REPOSITORY_NAME/redis-exporter] Valkey exporter image name + ## @skip metrics.image.tag Valkey exporter image tag + ## @param metrics.image.digest Valkey exporter image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param metrics.image.pullPolicy Valkey exporter image pull policy + ## @param metrics.image.pullSecrets Specify docker-registry secret names as an array + ## + image: + registry: docker.io + repository: bitnami/redis-exporter + tag: 1.76.0-debian-12-r0 + digest: "" + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## @param metrics.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if metrics.resources is set (metrics.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param metrics.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## + resources: {} + ## @param metrics.extraArgs Extra arguments for the binary; possible values [here](https://github.com/oliver006/redis_exporter) + ## extraArgs: + ## check-keys: myKey,myOtherKey + ## + extraArgs: {} + ## @param metrics.extraEnvVars Array with extra environment variables to add to Valkey exporter + ## e.g: + # extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param metrics.containerPorts.http Metrics HTTP container port + ## + containerPorts: + http: 9121 + ## @param metrics.podAnnotations [object] Additional annotations for Metrics exporter pod + ## + podAnnotations: + prometheus.io/scrape: "true" + prometheus.io/port: "{{ .Values.metrics.containerPorts.http }}" + ## @param metrics.podLabels Additional labels for Metrics exporter pod + ## + podLabels: {} + ## Containers' Security Context - All fields other than `enabled` get added to the metrics container's security context + ## @param metrics.containerSecurityContext.enabled Enabled containers' Security Context + ## @param metrics.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param metrics.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param metrics.containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup + ## @param metrics.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param metrics.containerSecurityContext.privileged Set container's Security Context privileged + ## @param metrics.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param metrics.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param metrics.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param metrics.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## Enable this if you're using https://github.com/coreos/prometheus-operator + ## + serviceMonitor: + ## @param metrics.serviceMonitor.enabled If `true`, creates a Prometheus Operator ServiceMonitor (also requires `metrics.enabled` to be `true`) + ## + enabled: false + ## @param metrics.serviceMonitor.namespace Optional namespace which Prometheus is running in + ## + namespace: "" + ## @param metrics.serviceMonitor.interval How frequently to scrape metrics (use by default, falling back to Prometheus' default) + ## + interval: "" + ## @param metrics.serviceMonitor.scrapeTimeout Timeout after which the scrape is ended + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint + ## e.g: + ## scrapeTimeout: 10s + ## + scrapeTimeout: "" + ## @param metrics.serviceMonitor.selector Prometheus instance selector labels + ## ref: https://github.com/bitnami/charts/tree/main/bitnami/prometheus-operator#prometheus-configuration + ## e.g: + ## selector: + ## prometheus: my-prometheus + ## + selector: {} + ## @param metrics.serviceMonitor.labels ServiceMonitor extra labels + ## + labels: {} + ## @param metrics.serviceMonitor.annotations ServiceMonitor annotations + ## + annotations: {} + ## @param metrics.serviceMonitor.jobLabel The name of the label on the target service to use as the job name in prometheus. + ## + jobLabel: "" + ## @param metrics.serviceMonitor.relabelings RelabelConfigs to apply to samples before scraping + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#relabelconfig + ## + relabelings: [] + ## @param metrics.serviceMonitor.metricRelabelings MetricRelabelConfigs to apply to samples before ingestion + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#relabelconfig + ## + metricRelabelings: [] + ## 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 + ## @param metrics.prometheusRule.enabled Set this to true to create prometheusRules for Prometheus operator + ## @param metrics.prometheusRule.additionalLabels Additional labels that can be used so prometheusRules will be discovered by Prometheus + ## @param metrics.prometheusRule.namespace namespace where prometheusRules resource should be created + ## @param metrics.prometheusRule.rules Create specified [rules](https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/), check values for an example. + ## + prometheusRule: + enabled: false + additionalLabels: {} + namespace: "" + ## These are just examples rules, please adapt them to your needs. + ## Make sure to constraint the rules to the current postgresql service. + ## - alert: ValkeyDown + ## expr: valkey_up{service="{{ template "common.names.fullname" . }}-metrics"} == 0 + ## for: 2m + ## labels: + ## severity: error + ## annotations: + ## summary: Valkey instance {{ "{{ $instance }}" }} down + ## description: Valkey instance {{ "{{ $instance }}" }} is down. + ## - alert: ValkeyMemoryHigh + ## expr: > + ## valkey_memory_used_bytes{service="{{ template "common.names.fullname" . }}-metrics"} * 100 + ## / + ## valkey_memory_max_bytes{service="{{ template "common.names.fullname" . }}-metrics"} + ## > 90 + ## for: 2m + ## labels: + ## severity: error + ## annotations: + ## summary: Valkey instance {{ "{{ $instance }}" }} is using too much memory + ## description: Valkey instance {{ "{{ $instance }}" }} is using {{ "{{ $value }}" }}% of its available memory. + ## - alert: ValkeyKeyEviction + ## expr: increase(valkey_evicted_keys_total{service="{{ template "common.names.fullname" . }}-metrics"}[5m]) > 0 + ## for: 1s + ## labels: + ## severity: error + ## annotations: + ## summary: Valkey instance {{ "{{ $instance }}" }} has evicted keys + ## description: Valkey instance {{ "{{ $instance }}" }} has evicted {{ "{{ $value }}" }} keys in the last 5 minutes. + ## + rules: [] + ## @param metrics.priorityClassName Metrics exporter pod priorityClassName + ## + priorityClassName: "" + ## @param metrics.service.type Kubernetes Service type (valkey metrics) + ## @param metrics.service.loadBalancerIP Use serviceLoadBalancerIP to request a specific static IP, otherwise leave blank + ## @param metrics.service.annotations Annotations for the services to monitor. + ## @param metrics.service.labels Additional labels for the metrics service + ## + service: + type: ClusterIP + ## @param metrics.service.ports.http Metrics HTTP service port + ## + ports: + http: 9121 + ## @param metrics.service.clusterIP Service Cluster IP + ## e.g.: + ## clusterIP: None + ## + clusterIP: "" + loadBalancerIP: "" + annotations: {} + labels: {} +## @section Sysctl Image parameters +## + +## Sysctl InitContainer +## Used to perform sysctl operation to modify Kernel settings (needed sometimes to avoid warnings) +## +sysctlImage: + ## @param sysctlImage.enabled Enable an init container to modify Kernel settings + ## + enabled: false + ## @param sysctlImage.command sysctlImage command to execute + ## + command: [] + ## @param sysctlImage.registry [default: REGISTRY_NAME] sysctlImage Init container registry + ## @param sysctlImage.repository [default: REPOSITORY_NAME/os-shell] sysctlImage Init container repository + ## @skip sysctlImage.tag sysctlImage Init container tag + ## @param sysctlImage.digest sysctlImage Init container digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param sysctlImage.pullPolicy sysctlImage Init container pull policy + ## @param sysctlImage.pullSecrets Specify docker-registry secret names as an array + ## + registry: docker.io + repository: bitnami/os-shell + tag: 12-debian-12-r51 + digest: "" + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## @param sysctlImage.mountHostSys Mount the host `/sys` folder to `/host-sys` + ## + mountHostSys: false + ## Containers Security Context + ## @param sysctlImage.containerSecurityContext.enabled Enable Containers' Security Context + ## @param sysctlImage.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param sysctlImage.containerSecurityContext.runAsUser User ID for the containers. + ## @param sysctlImage.containerSecurityContext.privileged Run privileged as privileged + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 0 + privileged: true + ## Container resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param sysctlImage.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if sysctlImage.resources is set (sysctlImage.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param sysctlImage.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} diff --git a/backing-services/gitea/charts/valkey/.helmignore b/backing-services/gitea/charts/valkey/.helmignore new file mode 100644 index 0000000..207983f --- /dev/null +++ b/backing-services/gitea/charts/valkey/.helmignore @@ -0,0 +1,25 @@ +# 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 +# img folder +img/ +# Changelog +CHANGELOG.md diff --git a/backing-services/gitea/charts/valkey/Chart.lock b/backing-services/gitea/charts/valkey/Chart.lock new file mode 100644 index 0000000..a2cf513 --- /dev/null +++ b/backing-services/gitea/charts/valkey/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + version: 2.31.4 +digest: sha256:fc442e77200e1914dd46fe26490dcf62f44caa51db673c2f8e67d5319cd4c163 +generated: "2025-08-13T18:19:54.197582447Z" diff --git a/backing-services/gitea/charts/valkey/Chart.yaml b/backing-services/gitea/charts/valkey/Chart.yaml new file mode 100644 index 0000000..946f0fc --- /dev/null +++ b/backing-services/gitea/charts/valkey/Chart.yaml @@ -0,0 +1,39 @@ +annotations: + category: Database + images: | + - name: kubectl + image: docker.io/bitnami/kubectl:1.33.4-debian-12-r0 + - name: os-shell + image: docker.io/bitnami/os-shell:12-debian-12-r51 + - name: redis-exporter + image: docker.io/bitnami/redis-exporter:1.76.0-debian-12-r0 + - name: valkey + image: docker.io/bitnami/valkey:8.1.3-debian-12-r3 + - name: valkey-sentinel + image: docker.io/bitnami/valkey-sentinel:8.1.3-debian-12-r3 + licenses: Apache-2.0 + tanzuCategory: service +apiVersion: v2 +appVersion: 8.1.3 +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + tags: + - bitnami-common + version: 2.x.x +description: Valkey is an open source (BSD) high-performance key/value datastore that + supports a variety workloads such as caching, message queues, and can act as a primary + database. +home: https://bitnami.com +icon: https://dyltqmyl993wv.cloudfront.net/assets/stacks/valkey/img/valkey-stack-220x234.png +keywords: +- valkey +- keyvalue +- database +maintainers: +- name: Broadcom, Inc. All Rights Reserved. + url: https://github.com/bitnami/charts +name: valkey +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/valkey +version: 3.0.31 diff --git a/backing-services/gitea/charts/valkey/README.md b/backing-services/gitea/charts/valkey/README.md new file mode 100644 index 0000000..862d090 --- /dev/null +++ b/backing-services/gitea/charts/valkey/README.md @@ -0,0 +1,1092 @@ + + +# Bitnami package for Valkey + +Valkey is an open source (BSD) high-performance key/value datastore that supports a variety workloads such as caching, message queues, and can act as a primary database. + +[Overview of Valkey](https://valkey.io/) + +Trademarks: This software listing is packaged by Bitnami. The respective trademarks mentioned in the offering are owned by the respective companies, and use of them does not imply any affiliation or endorsement. + +## TL;DR + +```console +helm install my-release oci://registry-1.docker.io/bitnamicharts/valkey +``` + +Looking to use Valkey in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the commercial edition of the Bitnami catalog. + +## ⚠️ Important Notice: Upcoming changes to the Bitnami Catalog + +Beginning August 28th, 2025, Bitnami will evolve its public catalog to offer a curated set of hardened, security-focused images under the new [Bitnami Secure Images initiative](https://news.broadcom.com/app-dev/broadcom-introduces-bitnami-secure-images-for-production-ready-containerized-applications). As part of this transition: + +- Granting community users access for the first time to security-optimized versions of popular container images. +- Bitnami will begin deprecating support for non-hardened, Debian-based software images in its free tier and will gradually remove non-latest tags from the public catalog. As a result, community users will have access to a reduced number of hardened images. These images are published only under the “latest” tag and are intended for development purposes +- Starting August 28th, over two weeks, all existing container images, including older or versioned tags (e.g., 2.50.0, 10.6), will be migrated from the public catalog (docker.io/bitnami) to the “Bitnami Legacy” repository (docker.io/bitnamilegacy), where they will no longer receive updates. +- For production workloads and long-term support, users are encouraged to adopt Bitnami Secure Images, which include hardened containers, smaller attack surfaces, CVE transparency (via VEX/KEV), SBOMs, and enterprise support. + +These changes aim to improve the security posture of all Bitnami users by promoting best practices for software supply chain integrity and up-to-date deployments. For more details, visit the [Bitnami Secure Images announcement](https://github.com/bitnami/containers/issues/83267). + +## Introduction + +This chart bootstraps a [Valkey](https://github.com/bitnami/containers/tree/main/bitnami/valkey) deployment on a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ +- 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 oci://REGISTRY_NAME/REPOSITORY_NAME/valkey +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The command deploys Valkey 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` + +## Configuration and installation details + +### Resource requests and limits + +Bitnami charts allow setting resource requests and limits for all containers inside the chart deployment. These are inside the `resources` value (check parameter table). Setting requests is essential for production workloads and these should be adapted to your specific use case. + +To make this process easier, the chart contains the `resourcesPreset` values, which automatically sets the `resources` section according to different presets. Check these presets in [the bitnami/common chart](https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15). However, in production workloads using `resourcesPreset` is discouraged as it may not fully adapt to your specific needs. Find more information on container resource management in the [official Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). + +### Update credentials + +The Bitnami Valkey chart, when upgrading, reuses the secret previously rendered by the chart or the one specified in `auth.existingSecret`. To update credentials, use one of the following: + +- Run `helm upgrade` specifying a new password in `auth.password` +- Run `helm upgrade` specifying a new secret in `auth.existingSecret` + +### Prometheus metrics + +This chart can be integrated with Prometheus by setting `metrics.enabled` to `true`. This will deploy a sidecar container with [redis_exporter](https://github.com/oliver006/redis_exporter) in all pods and a `metrics` service, which can be configured under the `metrics.service` section. This `metrics` service will have the necessary annotations to be automatically scraped by Prometheus. + +#### Prometheus requirements + +It is necessary to have a working installation of Prometheus or Prometheus Operator for the integration to work. Install the [Bitnami Prometheus helm chart](https://github.com/bitnami/charts/tree/main/bitnami/prometheus) or the [Bitnami Kube Prometheus helm chart](https://github.com/bitnami/charts/tree/main/bitnami/kube-prometheus) to easily have a working Prometheus in your cluster. + +#### Integration with Prometheus Operator + +The chart can deploy `ServiceMonitor` objects for integration with Prometheus Operator installations. To do so, set the value `metrics.serviceMonitor.enabled=true`. Ensure that the Prometheus Operator `CustomResourceDefinitions` are installed in the cluster or it will fail with the following error: + +```text +no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1" +``` + +Install the [Bitnami Kube Prometheus helm chart](https://github.com/bitnami/charts/tree/main/bitnami/kube-prometheus) for having the necessary CRDs and the Prometheus Operator. + +### [Rolling VS Immutable tags](https://docs.bitnami.com/tutorials/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. + +### Use a different Valkey version + +To modify the application version used in this chart, specify a different version of the image using the `image.tag` parameter and/or a different repository using the `image.repository` parameter. + +### Bootstrapping with an External Cluster + +This chart is equipped with the ability to bring online a set of Pods that connect to an existing Valkey deployment that lies outside of Kubernetes. This effectively creates a hybrid Valkey Deployment where both Pods in Kubernetes and Instances such as Virtual Machines can partake in a single Valkey Deployment. This is helpful in situations where one may be migrating Valkey from Virtual Machines into Kubernetes, for example. To take advantage of this, use the following as an example configuration: + +```yaml +replica: + externalPrimary: + enabled: true + host: external-valkey-0.internal +sentinel: + externalPrimary: + enabled: true + host: external-valkey-0.internal +``` + +:warning: This is currently limited to clusters in which Sentinel and Valkey run on the same node! :warning: + +Please also note that the external sentinel must be listening on port `26379`, and this is currently not configurable. + +Once the Kubernetes Valkey Deployment is online and confirmed to be working with the existing cluster, the configuration can then be removed and the cluster will remain connected. + +### External DNS + +This chart is equipped to allow leveraging the ExternalDNS project. Doing so will enable ExternalDNS to publish the FQDN for each instance, in the format of `..`. +Example, when using the following configuration: + +```yaml +useExternalDNS: + enabled: true + suffix: prod.example.org + additionalAnnotations: + ttl: 10 +``` + +On a cluster where the name of the Helm release is `a`, the hostname of a Pod is generated as: `a-valkey-node-0.a-valkey.prod.example.org`. The IP of that FQDN will match that of the associated Pod. This modifies the following parameters of the Valkey/Sentinel configuration using this new FQDN: + +- `replica-announce-ip` +- `known-sentinel` +- `known-replica` +- `announce-ip` + +:warning: This requires a working installation of `external-dns` to be fully functional. :warning: + +See the [official ExternalDNS documentation](https://github.com/kubernetes-sigs/external-dns) for additional configuration options. + +### Cluster topologies + +#### Default: Primary-Replicas + +When installing the chart with `architecture=replication`, it will deploy a Valkey primary StatefulSet and a Valkey replicas StatefulSet. The replicas will be read-replicas of the primary. Two services will be exposed: + +- Valkey Primary service: Points to the primary, where read-write operations can be performed +- Valkey Replicas service: Points to the replicas, where only read operations are allowed by default. + +In case the primary crashes, the replicas will wait until the primary node is respawned again by the Kubernetes Controller Manager. + +#### Standalone + +When installing the chart with `architecture=standalone`, it will deploy a standalone Valkey StatefulSet. A single service will be exposed: + +- Valkey Primary service: Points to the primary, where read-write operations can be performed + +#### Primary-Replicas with Sentinel + +When installing the chart with `architecture=replication` and `sentinel.enabled=true`, it will deploy a single Valkey StatefulSet. In this case, the pods will contain an extra container with Valkey Sentinel. This container will form a cluster of Valkey Sentinel nodes, which will promote a new primary in case the actual one fails. + +On graceful termination of the Valkey primary pod, a failover of the primary is initiated to promote a new primary. The Valkey Sentinel container in this pod will wait for the failover to occur before terminating. If `sentinel.valkeyShutdownWaitFailover=true` is set (the default), the Valkey container will wait for the failover as well before terminating. This increases availability for reads during failover, but may cause stale reads until all clients have switched to the new primary. + +In addition to this, only one service is exposed: + +- Valkey service: Exposes port 6379 for Valkey read-only operations and port 26379 for accessing Valkey Sentinel. + +For read-only operations, access the service using port 6379. For write operations, it's necessary to access the Valkey Sentinel cluster and query the current primary using the command below (using valkey-cli or similar): + +```console +SENTINEL get-primary-addr-by-name +``` + +This command will return the address of the current primary, which can be accessed from inside the cluster. + +In case the current primary crashes, the Sentinel containers will elect a new primary node. + +`primary.replicaCount` greater than `1` is not designed for use when `sentinel.enabled=true`. + +### Multiple primary nodes (experimental) + +When `primary.replicaCount` is greater than `1`, special care must be taken to create a consistent setup. + +An example of use case is the creation of a redundant set of standalone primary nodes or primary-replicas per Kubernetes node where you must ensure: + +- No more than `1` primary can be deployed per Kubernetes node +- Replicas and writers can only see the single primary of their own Kubernetes node + +One way of achieving this is by setting `primary.service.internalTrafficPolicy=Local` in combination with a `primary.affinity.podAntiAffinity` spec to never schedule more than one primary per Kubernetes node. + +It's recommended to only change `primary.replicaCount` if you know what you are doing. +`primary.replicaCount` greater than `1` is not designed for use when `sentinel.enabled=true`. + +### Using a password file + +To use a password file for Valkey you need to create a secret containing the password and then deploy the chart using that secret. Follow these instructions: + +- Create the secret with the password. It is important that the file with the password must be called `valkey-password`. + +```console +kubectl create secret generic valkey-password-secret --from-file=valkey-password.yaml +``` + +- Deploy the Helm Chart using the secret name as parameter: + +```text +usePassword=true +usePasswordFile=true +existingSecret=valkey-password-secret +sentinels.enabled=true +metrics.enabled=true +``` + +### Securing traffic using TLS + +TLS support can be enabled in the chart by specifying the `tls.` parameters while creating a release. The following parameters should be configured to properly enable the TLS support in the cluster: + +- `tls.enabled`: Enable TLS support. Defaults to `false` +- `tls.existingSecret`: Name of the secret that contains the certificates. No defaults. +- `tls.certFilename`: Certificate filename. No defaults. +- `tls.certKeyFilename`: Certificate key filename. No defaults. +- `tls.certCAFilename`: CA Certificate filename. No defaults. + +For example: + +First, create the secret with the certificates files: + +```console +kubectl create secret generic certificates-tls-secret --from-file=./cert.pem --from-file=./cert.key --from-file=./ca.pem +``` + +Then, use the following parameters: + +```console +tls.enabled="true" +tls.existingSecret="certificates-tls-secret" +tls.certFilename="cert.pem" +tls.certKeyFilename="cert.key" +tls.certCAFilename="ca.pem" +``` + +### Metrics + +The chart optionally can start a metrics exporter for [prometheus](https://prometheus.io). The metrics endpoint (port 9121) is exposed in the service. Metrics can be scraped from within the 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). If metrics are to be scraped from outside the cluster, the Kubernetes API proxy can be utilized to access the endpoint. + +If you have enabled TLS by specifying `tls.enabled=true` you also need to specify TLS option to the metrics exporter. You can do that via `metrics.extraArgs`. You can find the metrics exporter CLI flags for TLS [here](https://github.com/oliver006/valkey_exporter#command-line-flags). For example: + +You can either specify `metrics.extraArgs.skip-tls-verification=true` to skip TLS verification or providing the following values under `metrics.extraArgs` for TLS client authentication: + +```console +tls-client-key-file +tls-client-cert-file +tls-ca-cert-file +``` + +### Deploy a custom metrics script in the sidecar + +A custom Lua script can be added to the `redis-exporter` sidecar by way of the `metrics.extraArgs.script` parameter. The pathname of the script must exist on the container, or the `redis_exporter` process (and therefore the whole pod) will refuse to start. The script can be provided to the sidecar containers via the `metrics.extraVolumes` and `metrics.extraVolumeMounts` parameters: + +```yaml +metrics: + extraVolumeMounts: + - name: '{{ printf "%s-metrics-script-file" (include "common.names.fullname" .) }}' + mountPath: '{{ printf "/mnt/%s/" (include "common.names.name" .) }}' + readOnly: true + extraVolumes: + - name: '{{ printf "%s-metrics-script-file" (include "common.names.fullname" .) }}' + configMap: + name: '{{ printf "%s-metrics-script" (include "common.names.fullname" .) }}' + extraArgs: + script: '{{ printf "/mnt/%s/my_custom_metrics.lua" (include "common.names.name" .) }}' +``` + +Then deploy the script into the correct location via `extraDeploy`: + +```yaml +extraDeploy: + - apiVersion: v1 + kind: ConfigMap + metadata: + name: '{{ printf "%s-metrics-script" (include "common.names.fullname" .) }}' + data: + my_custom_metrics.lua: | + -- LUA SCRIPT CODE HERE, e.g., + return {'bitnami_makes_the_best_charts', '1'} +``` + +### Host Kernel Settings + +Valkey may require some changes in the kernel of the host machine to work as expected, in particular increasing the `somaxconn` value and disabling transparent huge pages. To do so, you can set `securityContext.sysctls` which will configure `sysctls` for primary and replica pods. Example: + +```yaml +securityContext: + sysctls: + - name: net.core.somaxconn + value: "10000" +``` + +Note that this will not disable transparent huge tables. + +### Backup and restore + +To backup and restore Valkey deployments on Kubernetes, you will need to create a snapshot of the data in the source cluster, and later restore it in a new cluster with the new parameters. Follow the instructions below: + +#### Step 1: Backup the deployment + +- Connect to one of the nodes and start the Valkey CLI tool. Then, run the commands below: + + ```text + $ kubectl exec -it my-release-primary-0 bash + $ valkey-cli + 127.0.0.1:6379> auth your_current_valkey_password + OK + 127.0.0.1:6379> save + OK + ``` + +- Copy the dump file from the Valkey node: + + ```console + kubectl cp my-release-primary-0:/data/dump.rdb dump.rdb -c valkey + ``` + +#### Step 2: Restore the data on the destination cluster + +To restore the data in a new cluster, you will need to create a PVC and then upload the *dump.rdb* file to the new volume. + +Follow the following steps: + +- In the [*values.yaml*](https://github.com/bitnami/charts/blob/main/bitnami/valkey/values.yaml) file set the *appendonly* parameter to *no*. You can skip this step if it is already configured as *no* + + ```yaml + commonConfiguration: |- + # Enable AOF https://valkey.io/topics/persistence#append-only-file + appendonly no + # Disable RDB persistence, AOF persistence already enabled. + save "" + ``` + + > *Note that the `Enable AOF` comment belongs to the original config file and what you're actually doing is disabling it. This change will only be neccessary for the temporal cluster you're creating to upload the dump.* + +- Start the new cluster to create the PVCs. Use the command below as an example: + + ```console + helm install new-valkey -f values.yaml . --set cluster.enabled=true --set cluster.replicaCount=3 + ``` + +- Now that the PVC were created, stop it and copy the *dump.rdp* file on the persisted data by using a helping pod. + + ```text + $ helm delete new-valkey + + $ kubectl run --generator=run-pod/v1 -i --rm --tty volpod --overrides=' + { + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "name": "valkeyvolpod" + }, + "spec": { + "containers": [{ + "command": [ + "tail", + "-f", + "/dev/null" + ], + "image": "bitnami/os-shell", + "name": "mycontainer", + "volumeMounts": [{ + "mountPath": "/mnt", + "name": "valkeydata" + }] + }], + "restartPolicy": "Never", + "volumes": [{ + "name": "valkeydata", + "persistentVolumeClaim": { + "claimName": "valkey-data-new-valkey-primary-0" + } + }] + } + }' --image="bitnami/os-shell" + + $ kubectl cp dump.rdb valkeyvolpod:/mnt/dump.rdb + $ kubectl delete pod volpod + ``` + +- Restart the cluster: + + > **INFO:** The *appendonly* parameter can be safely restored to your desired value. + + ```console + helm install new-valkey -f values.yaml . --set cluster.enabled=true --set cluster.replicaCount=3 + ``` + +### NetworkPolicy + +To enable network policy for Valkey, 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`. + +With NetworkPolicy enabled, only pods with the generated client label will be able to connect to Valkey. This label will be displayed in the output after a successful install. + +With `networkPolicy.ingressNSMatchLabels` pods from other namespaces can connect to Valkey. Set `networkPolicy.ingressNSPodMatchLabels` to match pod labels in matched namespace. For example, for a namespace labeled `valkey=external` and pods in that namespace labeled `valkey-client=true` the fields should be set: + +```yaml +networkPolicy: + enabled: true + ingressNSMatchLabels: + valkey: external + ingressNSPodMatchLabels: + valkey-client: true +``` + +#### Setting Pod's affinity + +This chart allows you to set your custom affinity using the `XXX.affinity` parameter(s). Find more information about Pod's affinity in the [Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). + +As an alternative, you can use of the preset configurations for pod affinity, pod anti-affinity, and node affinity available at the [bitnami/common](https://github.com/bitnami/charts/tree/main/bitnami/common#affinities) chart. To do so, set the `XXX.podAffinityPreset`, `XXX.podAntiAffinityPreset`, or `XXX.nodeAffinityPreset` parameters. + +## Persistence + +By default, the chart mounts a [Persistent Volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) at the `/data` path. The volume is created using dynamic volume provisioning. If a Persistent Volume Claim already exists, specify it during installation. + +### Existing PersistentVolumeClaim + +1. Create the PersistentVolume +2. Create the PersistentVolumeClaim +3. Install the chart + +```console +helm install my-release --set primary.persistence.existingClaim=PVC_NAME oci://REGISTRY_NAME/REPOSITORY_NAME/valkey +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +## Parameters + +### Global parameters + +| Name | Description | Value | +| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `global.imageRegistry` | Global Docker image registry | `""` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | +| `global.defaultStorageClass` | Global default StorageClass for Persistent Volume(s) | `""` | +| `global.storageClass` | DEPRECATED: use global.defaultStorageClass instead | `""` | +| `global.valkey.password` | Global Valkey password (overrides `auth.password`) | `""` | +| `global.security.allowInsecureImages` | Allows skipping image verification | `false` | +| `global.compatibility.openshift.adaptSecurityContext` | Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) | `auto` | + +### Common parameters + +| Name | Description | Value | +| ------------------------- | -------------------------------------------------------------------------------------------------------------- | --------------- | +| `kubeVersion` | Override Kubernetes version | `""` | +| `apiVersions` | Override Kubernetes API versions reported by .Capabilities | `[]` | +| `nameOverride` | String to partially override common.names.fullname | `""` | +| `fullnameOverride` | String to fully override common.names.fullname | `""` | +| `namespaceOverride` | String to fully override common.names.namespace | `""` | +| `commonLabels` | Labels to add to all deployed objects | `{}` | +| `commonAnnotations` | Annotations to add to all deployed objects | `{}` | +| `secretAnnotations` | Annotations to add to secret | `{}` | +| `clusterDomain` | Kubernetes cluster domain name | `cluster.local` | +| `extraDeploy` | Array of extra objects to deploy with the release | `[]` | +| `useHostnames` | Use hostnames internally when announcing replication. If false, the hostname will be resolved to an IP address | `true` | +| `nameResolutionThreshold` | Failure threshold for internal hostnames resolution | `5` | +| `nameResolutionTimeout` | Timeout seconds between probes for internal hostnames resolution | `5` | +| `diagnosticMode.enabled` | Enable diagnostic mode (all probes will be disabled and the command will be overridden) | `false` | +| `diagnosticMode.command` | Command to override all containers in the deployment | `["sleep"]` | +| `diagnosticMode.args` | Args to override all containers in the deployment | `["infinity"]` | + +### Valkey Image parameters + +| Name | Description | Value | +| ------------------- | ------------------------------------------------------------------------------------------------------ | ------------------------ | +| `image.registry` | Valkey image registry | `REGISTRY_NAME` | +| `image.repository` | Valkey image repository | `REPOSITORY_NAME/valkey` | +| `image.digest` | Valkey image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `image.pullPolicy` | Valkey image pull policy | `IfNotPresent` | +| `image.pullSecrets` | Valkey image pull secrets | `[]` | +| `image.debug` | Enable image debug mode | `false` | + +### Valkey common configuration parameters + +| Name | Description | Value | +| -------------------------------- | --------------------------------------------------------------------------------- | ------------- | +| `architecture` | Valkey architecture. Allowed values: `standalone` or `replication` | `replication` | +| `auth.enabled` | Enable password authentication | `true` | +| `auth.sentinel` | Enable password authentication on sentinels too | `true` | +| `auth.password` | Valkey password | `""` | +| `auth.existingSecret` | The name of an existing secret with Valkey credentials | `""` | +| `auth.existingSecretPasswordKey` | Password key to be retrieved from existing secret | `""` | +| `auth.usePasswordFiles` | Mount credentials as files instead of using an environment variable | `true` | +| `auth.usePasswordFileFromSecret` | Mount password file from secret | `true` | +| `commonConfiguration` | Common configuration to be added into the ConfigMap | `""` | +| `existingConfigmap` | The name of an existing ConfigMap with your custom configuration for Valkey nodes | `""` | + +### Valkey primary configuration parameters + +| Name | Description | Value | +| ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | +| `primary.replicaCount` | Number of Valkey primary instances to deploy (experimental, requires additional configuration) | `1` | +| `primary.configuration` | Configuration for Valkey primary nodes | `""` | +| `primary.disableCommands` | Array with Valkey commands to disable on primary nodes | `["FLUSHDB","FLUSHALL"]` | +| `primary.command` | Override default container command (useful when using custom images) | `[]` | +| `primary.args` | Override default container args (useful when using custom images) | `[]` | +| `primary.enableServiceLinks` | Whether information about services should be injected into pod's environment variable | `true` | +| `primary.preExecCmds` | Additional commands to run prior to starting Valkey primary | `[]` | +| `primary.extraFlags` | Array with additional command line flags for Valkey primary | `[]` | +| `primary.extraEnvVars` | Array with extra environment variables to add to Valkey primary nodes | `[]` | +| `primary.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for Valkey primary nodes | `""` | +| `primary.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for Valkey primary nodes | `""` | +| `primary.containerPorts.valkey` | Container port to open on Valkey primary nodes | `6379` | +| `primary.startupProbe.enabled` | Enable startupProbe on Valkey primary nodes | `false` | +| `primary.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `20` | +| `primary.startupProbe.periodSeconds` | Period seconds for startupProbe | `5` | +| `primary.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `primary.startupProbe.failureThreshold` | Failure threshold for startupProbe | `5` | +| `primary.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `primary.livenessProbe.enabled` | Enable livenessProbe on Valkey primary nodes | `true` | +| `primary.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `20` | +| `primary.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `5` | +| `primary.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `primary.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `5` | +| `primary.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `primary.readinessProbe.enabled` | Enable readinessProbe on Valkey primary nodes | `true` | +| `primary.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `20` | +| `primary.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `5` | +| `primary.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `1` | +| `primary.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `5` | +| `primary.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `primary.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `primary.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `primary.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `primary.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if primary.resources is set (primary.resources is recommended for production). | `nano` | +| `primary.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `primary.podSecurityContext.enabled` | Enabled Valkey primary pods' Security Context | `true` | +| `primary.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `primary.podSecurityContext.sysctls` | Set kernel settings using the sysctl interface | `[]` | +| `primary.podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `primary.podSecurityContext.fsGroup` | Set Valkey primary pod's Security Context fsGroup | `1001` | +| `primary.containerSecurityContext.enabled` | Enabled Valkey primary containers' Security Context | `true` | +| `primary.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `primary.containerSecurityContext.runAsUser` | Set Valkey primary containers' Security Context runAsUser | `1001` | +| `primary.containerSecurityContext.runAsGroup` | Set Valkey primary containers' Security Context runAsGroup | `1001` | +| `primary.containerSecurityContext.runAsNonRoot` | Set Valkey primary containers' Security Context runAsNonRoot | `true` | +| `primary.containerSecurityContext.allowPrivilegeEscalation` | Is it possible to escalate Valkey pod(s) privileges | `false` | +| `primary.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context read-only root filesystem | `true` | +| `primary.containerSecurityContext.seccompProfile.type` | Set Valkey primary containers' Security Context seccompProfile | `RuntimeDefault` | +| `primary.containerSecurityContext.capabilities.drop` | Set Valkey primary containers' Security Context capabilities to drop | `["ALL"]` | +| `primary.kind` | Use either Deployment, StatefulSet (default) or DaemonSet | `StatefulSet` | +| `primary.schedulerName` | Alternate scheduler for Valkey primary pods | `""` | +| `primary.updateStrategy.type` | Valkey primary statefulset strategy type | `RollingUpdate` | +| `primary.minReadySeconds` | How many seconds a pod needs to be ready before killing the next, during update | `0` | +| `primary.priorityClassName` | Valkey primary pods' priorityClassName | `""` | +| `primary.automountServiceAccountToken` | Mount Service Account token in pod | `false` | +| `primary.hostAliases` | Valkey primary pods host aliases | `[]` | +| `primary.podLabels` | Extra labels for Valkey primary pods | `{}` | +| `primary.podAnnotations` | Annotations for Valkey primary pods | `{}` | +| `primary.shareProcessNamespace` | Share a single process namespace between all of the containers in Valkey primary pods | `false` | +| `primary.podAffinityPreset` | Pod affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `primary.podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `primary.nodeAffinityPreset.type` | Node affinity preset type. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `primary.nodeAffinityPreset.key` | Node label key to match. Ignored if `primary.affinity` is set | `""` | +| `primary.nodeAffinityPreset.values` | Node label values to match. Ignored if `primary.affinity` is set | `[]` | +| `primary.affinity` | Affinity for Valkey primary pods assignment | `{}` | +| `primary.nodeSelector` | Node labels for Valkey primary pods assignment | `{}` | +| `primary.tolerations` | Tolerations for Valkey primary pods assignment | `[]` | +| `primary.topologySpreadConstraints` | Spread Constraints for Valkey primary pod assignment | `[]` | +| `primary.dnsPolicy` | DNS Policy for Valkey primary pod | `""` | +| `primary.dnsConfig` | DNS Configuration for Valkey primary pod | `{}` | +| `primary.lifecycleHooks` | for the Valkey primary container(s) to automate configuration before or after startup | `{}` | +| `primary.extraVolumes` | Optionally specify extra list of additional volumes for the Valkey primary pod(s) | `[]` | +| `primary.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the Valkey primary container(s) | `[]` | +| `primary.sidecars` | Add additional sidecar containers to the Valkey primary pod(s) | `[]` | +| `primary.initContainers` | Add additional init containers to the Valkey primary pod(s) | `[]` | +| `primary.persistence.enabled` | Enable persistence on Valkey primary nodes using Persistent Volume Claims | `true` | +| `primary.persistence.medium` | Provide a medium for `emptyDir` volumes. | `""` | +| `primary.persistence.sizeLimit` | Set this to enable a size limit for `emptyDir` volumes. | `""` | +| `primary.persistence.path` | The path the volume will be mounted at on Valkey primary containers | `/data` | +| `primary.persistence.subPath` | The subdirectory of the volume to mount on Valkey primary containers | `""` | +| `primary.persistence.subPathExpr` | Used to construct the subPath subdirectory of the volume to mount on Valkey primary containers | `""` | +| `primary.persistence.storageClass` | Persistent Volume storage class | `""` | +| `primary.persistence.accessModes` | Persistent Volume access modes | `["ReadWriteOnce"]` | +| `primary.persistence.size` | Persistent Volume size | `8Gi` | +| `primary.persistence.annotations` | Additional custom annotations for the PVC | `{}` | +| `primary.persistence.labels` | Additional custom labels for the PVC | `{}` | +| `primary.persistence.selector` | Additional labels to match for the PVC | `{}` | +| `primary.persistence.dataSource` | Custom PVC data source | `{}` | +| `primary.persistence.existingClaim` | Use a existing PVC which must be created manually before bound | `""` | +| `primary.persistentVolumeClaimRetentionPolicy.enabled` | Controls if and how PVCs are deleted during the lifecycle of a StatefulSet | `false` | +| `primary.persistentVolumeClaimRetentionPolicy.whenScaled` | Volume retention behavior when the replica count of the StatefulSet is reduced | `Retain` | +| `primary.persistentVolumeClaimRetentionPolicy.whenDeleted` | Volume retention behavior that applies when the StatefulSet is deleted | `Retain` | +| `primary.service.type` | Valkey primary service type | `ClusterIP` | +| `primary.service.ports.valkey` | Valkey primary service port | `6379` | +| `primary.service.nodePorts.valkey` | Node port for Valkey primary | `""` | +| `primary.service.externalTrafficPolicy` | Valkey primary service external traffic policy | `Cluster` | +| `primary.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `primary.service.internalTrafficPolicy` | Valkey primary service internal traffic policy (requires Kubernetes v1.22 or greater to be usable) | `Cluster` | +| `primary.service.clusterIP` | Valkey primary service Cluster IP | `""` | +| `primary.service.loadBalancerIP` | Valkey primary service Load Balancer IP | `""` | +| `primary.service.loadBalancerClass` | primary service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) | `""` | +| `primary.service.loadBalancerSourceRanges` | Valkey primary service Load Balancer sources | `[]` | +| `primary.service.externalIPs` | Valkey primary service External IPs | `[]` | +| `primary.service.annotations` | Additional custom annotations for Valkey primary service | `{}` | +| `primary.service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` | +| `primary.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `primary.terminationGracePeriodSeconds` | Integer setting the termination grace period for the valkey-primary pods | `30` | +| `primary.serviceAccount.create` | Specifies whether a ServiceAccount should be created | `true` | +| `primary.serviceAccount.name` | The name of the ServiceAccount to use. | `""` | +| `primary.serviceAccount.automountServiceAccountToken` | Whether to auto mount the service account token | `false` | +| `primary.serviceAccount.annotations` | Additional custom annotations for the ServiceAccount | `{}` | +| `primary.pdb.create` | Enable/disable a Pod Disruption Budget creation | `true` | +| `primary.pdb.minAvailable` | Minimum number/percentage of pods that should remain scheduled | `{}` | +| `primary.pdb.maxUnavailable` | Maximum number/percentage of pods that may be made unavailable. Defaults to `1` if both `primary.pdb.minAvailable` and `primary.pdb.maxUnavailable` are empty. | `{}` | + +### Valkey replicas configuration parameters + +| Name | Description | Value | +| ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | +| `replica.kind` | Use either DaemonSet or StatefulSet (default) | `StatefulSet` | +| `replica.replicaCount` | Number of Valkey replicas to deploy | `3` | +| `replica.configuration` | Configuration for Valkey replicas nodes | `""` | +| `replica.disableCommands` | Array with Valkey commands to disable on replicas nodes | `["FLUSHDB","FLUSHALL"]` | +| `replica.command` | Override default container command (useful when using custom images) | `[]` | +| `replica.args` | Override default container args (useful when using custom images) | `[]` | +| `replica.enableServiceLinks` | Whether information about services should be injected into pod's environment variable | `true` | +| `replica.preExecCmds` | Additional commands to run prior to starting Valkey replicas | `[]` | +| `replica.extraFlags` | Array with additional command line flags for Valkey replicas | `[]` | +| `replica.extraEnvVars` | Array with extra environment variables to add to Valkey replicas nodes | `[]` | +| `replica.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for Valkey replicas nodes | `""` | +| `replica.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for Valkey replicas nodes | `""` | +| `replica.externalPrimary.enabled` | Use external primary for bootstrapping | `false` | +| `replica.externalPrimary.host` | External primary host to bootstrap from | `""` | +| `replica.externalPrimary.port` | Port for Valkey service external primary host | `6379` | +| `replica.containerPorts.valkey` | Container port to open on Valkey replicas nodes | `6379` | +| `replica.startupProbe.enabled` | Enable startupProbe on Valkey replicas nodes | `true` | +| `replica.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `10` | +| `replica.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `replica.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `replica.startupProbe.failureThreshold` | Failure threshold for startupProbe | `22` | +| `replica.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `replica.livenessProbe.enabled` | Enable livenessProbe on Valkey replicas nodes | `true` | +| `replica.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `20` | +| `replica.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `5` | +| `replica.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `replica.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `5` | +| `replica.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `replica.readinessProbe.enabled` | Enable readinessProbe on Valkey replicas nodes | `true` | +| `replica.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `20` | +| `replica.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `5` | +| `replica.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `1` | +| `replica.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `5` | +| `replica.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `replica.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `replica.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `replica.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `replica.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if replica.resources is set (replica.resources is recommended for production). | `nano` | +| `replica.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `replica.podSecurityContext.enabled` | Enabled Valkey replicas pods' Security Context | `true` | +| `replica.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `replica.podSecurityContext.sysctls` | Set kernel settings using the sysctl interface | `[]` | +| `replica.podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `replica.podSecurityContext.fsGroup` | Set Valkey replicas pod's Security Context fsGroup | `1001` | +| `replica.containerSecurityContext.enabled` | Enabled Valkey replicas containers' Security Context | `true` | +| `replica.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `replica.containerSecurityContext.runAsUser` | Set Valkey replicas containers' Security Context runAsUser | `1001` | +| `replica.containerSecurityContext.runAsGroup` | Set Valkey replicas containers' Security Context runAsGroup | `1001` | +| `replica.containerSecurityContext.runAsNonRoot` | Set Valkey replicas containers' Security Context runAsNonRoot | `true` | +| `replica.containerSecurityContext.allowPrivilegeEscalation` | Set Valkey replicas pod's Security Context allowPrivilegeEscalation | `false` | +| `replica.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context read-only root filesystem | `true` | +| `replica.containerSecurityContext.seccompProfile.type` | Set Valkey replicas containers' Security Context seccompProfile | `RuntimeDefault` | +| `replica.containerSecurityContext.capabilities.drop` | Set Valkey replicas containers' Security Context capabilities to drop | `["ALL"]` | +| `replica.schedulerName` | Alternate scheduler for Valkey replicas pods | `""` | +| `replica.updateStrategy.type` | Valkey replicas statefulset strategy type | `RollingUpdate` | +| `replica.minReadySeconds` | How many seconds a pod needs to be ready before killing the next, during update | `0` | +| `replica.priorityClassName` | Valkey replicas pods' priorityClassName | `""` | +| `replica.podManagementPolicy` | podManagementPolicy to manage scaling operation of %%MAIN_CONTAINER_NAME%% pods | `""` | +| `replica.automountServiceAccountToken` | Mount Service Account token in pod | `false` | +| `replica.hostAliases` | Valkey replicas pods host aliases | `[]` | +| `replica.podLabels` | Extra labels for Valkey replicas pods | `{}` | +| `replica.podAnnotations` | Annotations for Valkey replicas pods | `{}` | +| `replica.shareProcessNamespace` | Share a single process namespace between all of the containers in Valkey replicas pods | `false` | +| `replica.podAffinityPreset` | Pod affinity preset. Ignored if `replica.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `replica.podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `replica.affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `replica.nodeAffinityPreset.type` | Node affinity preset type. Ignored if `replica.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `replica.nodeAffinityPreset.key` | Node label key to match. Ignored if `replica.affinity` is set | `""` | +| `replica.nodeAffinityPreset.values` | Node label values to match. Ignored if `replica.affinity` is set | `[]` | +| `replica.affinity` | Affinity for Valkey replicas pods assignment | `{}` | +| `replica.nodeSelector` | Node labels for Valkey replicas pods assignment | `{}` | +| `replica.tolerations` | Tolerations for Valkey replicas pods assignment | `[]` | +| `replica.topologySpreadConstraints` | Spread Constraints for Valkey replicas pod assignment | `[]` | +| `replica.dnsPolicy` | DNS Policy for Valkey replica pods | `""` | +| `replica.dnsConfig` | DNS Configuration for Valkey replica pods | `{}` | +| `replica.lifecycleHooks` | for the Valkey replica container(s) to automate configuration before or after startup | `{}` | +| `replica.extraVolumes` | Optionally specify extra list of additional volumes for the Valkey replicas pod(s) | `[]` | +| `replica.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the Valkey replicas container(s) | `[]` | +| `replica.sidecars` | Add additional sidecar containers to the Valkey replicas pod(s) | `[]` | +| `replica.initContainers` | Add additional init containers to the Valkey replicas pod(s) | `[]` | +| `replica.persistence.enabled` | Enable persistence on Valkey replicas nodes using Persistent Volume Claims | `true` | +| `replica.persistence.medium` | Provide a medium for `emptyDir` volumes. | `""` | +| `replica.persistence.sizeLimit` | Set this to enable a size limit for `emptyDir` volumes. | `""` | +| `replica.persistence.path` | The path the volume will be mounted at on Valkey replicas containers | `/data` | +| `replica.persistence.subPath` | The subdirectory of the volume to mount on Valkey replicas containers | `""` | +| `replica.persistence.subPathExpr` | Used to construct the subPath subdirectory of the volume to mount on Valkey replicas containers | `""` | +| `replica.persistence.storageClass` | Persistent Volume storage class | `""` | +| `replica.persistence.accessModes` | Persistent Volume access modes | `["ReadWriteOnce"]` | +| `replica.persistence.size` | Persistent Volume size | `8Gi` | +| `replica.persistence.annotations` | Additional custom annotations for the PVC | `{}` | +| `replica.persistence.labels` | Additional custom labels for the PVC | `{}` | +| `replica.persistence.selector` | Additional labels to match for the PVC | `{}` | +| `replica.persistence.dataSource` | Custom PVC data source | `{}` | +| `replica.persistence.existingClaim` | Use a existing PVC which must be created manually before bound | `""` | +| `replica.persistentVolumeClaimRetentionPolicy.enabled` | Controls if and how PVCs are deleted during the lifecycle of a StatefulSet | `false` | +| `replica.persistentVolumeClaimRetentionPolicy.whenScaled` | Volume retention behavior when the replica count of the StatefulSet is reduced | `Retain` | +| `replica.persistentVolumeClaimRetentionPolicy.whenDeleted` | Volume retention behavior that applies when the StatefulSet is deleted | `Retain` | +| `replica.service.type` | Valkey replicas service type | `ClusterIP` | +| `replica.service.ports.valkey` | Valkey replicas service port | `6379` | +| `replica.service.nodePorts.valkey` | Node port for Valkey replicas | `""` | +| `replica.service.externalTrafficPolicy` | Valkey replicas service external traffic policy | `Cluster` | +| `replica.service.internalTrafficPolicy` | Valkey replicas service internal traffic policy (requires Kubernetes v1.22 or greater to be usable) | `Cluster` | +| `replica.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `replica.service.clusterIP` | Valkey replicas service Cluster IP | `""` | +| `replica.service.loadBalancerIP` | Valkey replicas service Load Balancer IP | `""` | +| `replica.service.loadBalancerClass` | replicas service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) | `""` | +| `replica.service.loadBalancerSourceRanges` | Valkey replicas service Load Balancer sources | `[]` | +| `replica.service.annotations` | Additional custom annotations for Valkey replicas service | `{}` | +| `replica.service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` | +| `replica.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `replica.terminationGracePeriodSeconds` | Integer setting the termination grace period for the valkey-replicas pods | `30` | + +### Autoscaling + +| Name | Description | Value | +| --------------------------------------------- | ---------------------------------------------------------------------------------------------- | ------- | +| `replica.autoscaling.vpa.enabled` | Enable VPA | `false` | +| `replica.autoscaling.vpa.annotations` | Annotations for VPA resource | `{}` | +| `replica.autoscaling.vpa.controlledResources` | VPA List of resources that the vertical pod autoscaler can control. Defaults to cpu and memory | `[]` | +| `replica.autoscaling.vpa.maxAllowed` | VPA Max allowed resources for the pod | `{}` | +| `replica.autoscaling.vpa.minAllowed` | VPA Min allowed resources for the pod | `{}` | + +### VPA update policy + +| Name | Description | Value | +| ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `replica.autoscaling.vpa.updatePolicy.updateMode` | Autoscaling update policy Specifies whether recommended updates are applied when a Pod is started and whether recommended updates are applied during the life of a Pod | `Auto` | +| `replica.autoscaling.hpa.enabled` | Enable HPA | `false` | +| `replica.autoscaling.hpa.minReplicas` | Minimum number of replicas | `""` | +| `replica.autoscaling.hpa.maxReplicas` | Maximum number of replicas | `""` | +| `replica.autoscaling.hpa.targetCPU` | Target CPU utilization percentage | `""` | +| `replica.autoscaling.hpa.targetMemory` | Target Memory utilization percentage | `""` | +| `replica.serviceAccount.create` | Specifies whether a ServiceAccount should be created | `true` | +| `replica.serviceAccount.name` | The name of the ServiceAccount to use. | `""` | +| `replica.serviceAccount.automountServiceAccountToken` | Whether to auto mount the service account token | `false` | +| `replica.serviceAccount.annotations` | Additional custom annotations for the ServiceAccount | `{}` | +| `replica.pdb.create` | Enable/disable a Pod Disruption Budget creation | `true` | +| `replica.pdb.minAvailable` | Minimum number/percentage of pods that should remain scheduled | `{}` | +| `replica.pdb.maxUnavailable` | Maximum number/percentage of pods that may be made unavailable. Defaults to `1` if both `replica.pdb.minAvailable` and `replica.pdb.maxUnavailable` are empty. | `{}` | + +### Valkey Sentinel configuration parameters + +| Name | Description | Value | +| ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- | +| `sentinel.enabled` | Use Valkey Sentinel on Valkey pods. | `false` | +| `sentinel.image.registry` | Valkey Sentinel image registry | `REGISTRY_NAME` | +| `sentinel.image.repository` | Valkey Sentinel image repository | `REPOSITORY_NAME/valkey-sentinel` | +| `sentinel.image.digest` | Valkey Sentinel image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `sentinel.image.pullPolicy` | Valkey Sentinel image pull policy | `IfNotPresent` | +| `sentinel.image.pullSecrets` | Valkey Sentinel image pull secrets | `[]` | +| `sentinel.image.debug` | Enable image debug mode | `false` | +| `sentinel.annotations` | Additional custom annotations for Valkey Sentinel resource | `{}` | +| `sentinel.primarySet` | Primary set name | `myprimary` | +| `sentinel.quorum` | Sentinel Quorum | `2` | +| `sentinel.getPrimaryTimeout` | Amount of time to allow before get_sentinel_primary_info() times out. | `90` | +| `sentinel.automateClusterRecovery` | Automate cluster recovery in cases where the last replica is not considered a good replica and Sentinel won't automatically failover to it. | `false` | +| `sentinel.valkeyShutdownWaitFailover` | Whether the Valkey primary container waits for the failover at shutdown (in addition to the Valkey Sentinel container). | `true` | +| `sentinel.downAfterMilliseconds` | Timeout for detecting a Valkey node is down | `60000` | +| `sentinel.failoverTimeout` | Timeout for performing a election failover | `180000` | +| `sentinel.parallelSyncs` | Number of replicas that can be reconfigured in parallel to use the new primary after a failover | `1` | +| `sentinel.configuration` | Configuration for Valkey Sentinel nodes | `""` | +| `sentinel.command` | Override default container command (useful when using custom images) | `[]` | +| `sentinel.args` | Override default container args (useful when using custom images) | `[]` | +| `sentinel.enableServiceLinks` | Whether information about services should be injected into pod's environment variable | `true` | +| `sentinel.preExecCmds` | Additional commands to run prior to starting Valkey Sentinel | `[]` | +| `sentinel.extraEnvVars` | Array with extra environment variables to add to Valkey Sentinel nodes | `[]` | +| `sentinel.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for Valkey Sentinel nodes | `""` | +| `sentinel.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for Valkey Sentinel nodes | `""` | +| `sentinel.externalPrimary.enabled` | Use external primary for bootstrapping | `false` | +| `sentinel.externalPrimary.host` | External primary host to bootstrap from | `""` | +| `sentinel.externalPrimary.port` | Port for Valkey service external primary host | `6379` | +| `sentinel.containerPorts.sentinel` | Container port to open on Valkey Sentinel nodes | `26379` | +| `sentinel.startupProbe.enabled` | Enable startupProbe on Valkey Sentinel nodes | `true` | +| `sentinel.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `10` | +| `sentinel.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `sentinel.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `sentinel.startupProbe.failureThreshold` | Failure threshold for startupProbe | `22` | +| `sentinel.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `sentinel.livenessProbe.enabled` | Enable livenessProbe on Valkey Sentinel nodes | `true` | +| `sentinel.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `20` | +| `sentinel.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `sentinel.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `sentinel.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `sentinel.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `sentinel.readinessProbe.enabled` | Enable readinessProbe on Valkey Sentinel nodes | `true` | +| `sentinel.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `20` | +| `sentinel.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `5` | +| `sentinel.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `1` | +| `sentinel.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `sentinel.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `sentinel.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `sentinel.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `sentinel.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `sentinel.persistence.enabled` | Enable persistence on Valkey sentinel nodes using Persistent Volume Claims (Experimental) | `false` | +| `sentinel.persistence.storageClass` | Persistent Volume storage class | `""` | +| `sentinel.persistence.accessModes` | Persistent Volume access modes | `["ReadWriteOnce"]` | +| `sentinel.persistence.size` | Persistent Volume size | `100Mi` | +| `sentinel.persistence.annotations` | Additional custom annotations for the PVC | `{}` | +| `sentinel.persistence.labels` | Additional custom labels for the PVC | `{}` | +| `sentinel.persistence.selector` | Additional labels to match for the PVC | `{}` | +| `sentinel.persistence.dataSource` | Custom PVC data source | `{}` | +| `sentinel.persistence.medium` | Provide a medium for `emptyDir` volumes. | `""` | +| `sentinel.persistence.sizeLimit` | Set this to enable a size limit for `emptyDir` volumes. | `""` | +| `sentinel.persistentVolumeClaimRetentionPolicy.enabled` | Controls if and how PVCs are deleted during the lifecycle of a StatefulSet | `false` | +| `sentinel.persistentVolumeClaimRetentionPolicy.whenScaled` | Volume retention behavior when the replica count of the StatefulSet is reduced | `Retain` | +| `sentinel.persistentVolumeClaimRetentionPolicy.whenDeleted` | Volume retention behavior that applies when the StatefulSet is deleted | `Retain` | +| `sentinel.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if sentinel.resources is set (sentinel.resources is recommended for production). | `nano` | +| `sentinel.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `sentinel.containerSecurityContext.enabled` | Enabled Valkey Sentinel containers' Security Context | `true` | +| `sentinel.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `sentinel.containerSecurityContext.runAsUser` | Set Valkey Sentinel containers' Security Context runAsUser | `1001` | +| `sentinel.containerSecurityContext.runAsGroup` | Set Valkey Sentinel containers' Security Context runAsGroup | `1001` | +| `sentinel.containerSecurityContext.runAsNonRoot` | Set Valkey Sentinel containers' Security Context runAsNonRoot | `true` | +| `sentinel.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context read-only root filesystem | `true` | +| `sentinel.containerSecurityContext.allowPrivilegeEscalation` | Set Valkey Sentinel containers' Security Context allowPrivilegeEscalation | `false` | +| `sentinel.containerSecurityContext.seccompProfile.type` | Set Valkey Sentinel containers' Security Context seccompProfile | `RuntimeDefault` | +| `sentinel.containerSecurityContext.capabilities.drop` | Set Valkey Sentinel containers' Security Context capabilities to drop | `["ALL"]` | +| `sentinel.lifecycleHooks` | for the Valkey sentinel container(s) to automate configuration before or after startup | `{}` | +| `sentinel.extraVolumes` | Optionally specify extra list of additional volumes for the Valkey Sentinel | `[]` | +| `sentinel.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the Valkey Sentinel container(s) | `[]` | +| `sentinel.service.type` | Valkey Sentinel service type | `ClusterIP` | +| `sentinel.service.ports.valkey` | Valkey service port for Valkey | `6379` | +| `sentinel.service.ports.sentinel` | Valkey service port for Valkey Sentinel | `26379` | +| `sentinel.service.nodePorts.valkey` | Node port for Valkey | `""` | +| `sentinel.service.nodePorts.sentinel` | Node port for Sentinel | `""` | +| `sentinel.service.externalTrafficPolicy` | Valkey Sentinel service external traffic policy | `Cluster` | +| `sentinel.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `sentinel.service.clusterIP` | Valkey Sentinel service Cluster IP | `""` | +| `sentinel.service.createPrimary` | Enable primary service pointing to the current primary (experimental) | `false` | +| `sentinel.service.loadBalancerIP` | Valkey Sentinel service Load Balancer IP | `""` | +| `sentinel.service.loadBalancerClass` | sentinel service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) | `""` | +| `sentinel.service.loadBalancerSourceRanges` | Valkey Sentinel service Load Balancer sources | `[]` | +| `sentinel.service.annotations` | Additional custom annotations for Valkey Sentinel service | `{}` | +| `sentinel.service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` | +| `sentinel.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `sentinel.service.headless.annotations` | Annotations for the headless service. | `{}` | +| `sentinel.terminationGracePeriodSeconds` | Integer setting the termination grace period for the valkey-node pods | `30` | + +### Other Parameters + +| Name | Description | Value | +| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `serviceBindings.enabled` | Create secret for service binding (Experimental) | `false` | +| `networkPolicy.enabled` | Enable creation of NetworkPolicy resources | `true` | +| `networkPolicy.allowExternal` | Don't require client label for connections | `true` | +| `networkPolicy.allowExternalEgress` | Allow the pod to access any range of port and all destinations. | `true` | +| `networkPolicy.extraIngress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `networkPolicy.extraEgress` | Add extra egress rules to the NetworkPolicy | `[]` | +| `networkPolicy.ingressNSMatchLabels` | Labels to match to allow traffic from other namespaces | `{}` | +| `networkPolicy.ingressNSPodMatchLabels` | Pod labels to match to allow traffic from other namespaces | `{}` | +| `networkPolicy.metrics.allowExternal` | Don't require client label for connections for metrics endpoint | `true` | +| `networkPolicy.metrics.ingressNSMatchLabels` | Labels to match to allow traffic from other namespaces to metrics endpoint | `{}` | +| `networkPolicy.metrics.ingressNSPodMatchLabels` | Pod labels to match to allow traffic from other namespaces to metrics endpoint | `{}` | +| `podSecurityPolicy.create` | Whether to create a PodSecurityPolicy. WARNING: PodSecurityPolicy is deprecated in Kubernetes v1.21 or later, unavailable in v1.25 or later | `false` | +| `podSecurityPolicy.enabled` | Enable PodSecurityPolicy's RBAC rules | `false` | +| `rbac.create` | Specifies whether RBAC resources should be created | `false` | +| `rbac.rules` | Custom RBAC rules to set | `[]` | +| `serviceAccount.create` | Specifies whether a ServiceAccount should be created | `true` | +| `serviceAccount.name` | The name of the ServiceAccount to use. | `""` | +| `serviceAccount.automountServiceAccountToken` | Whether to auto mount the service account token | `false` | +| `serviceAccount.annotations` | Additional custom annotations for the ServiceAccount | `{}` | +| `pdb` | DEPRECATED Please use `primary.pdb` and `replica.pdb` values instead | `{}` | +| `tls.enabled` | Enable TLS traffic | `false` | +| `tls.authClients` | Require clients to authenticate | `true` | +| `tls.autoGenerated` | Enable autogenerated certificates | `false` | +| `tls.existingSecret` | The name of the existing secret that contains the TLS certificates | `""` | +| `tls.certFilename` | Certificate filename | `""` | +| `tls.certKeyFilename` | Certificate Key filename | `""` | +| `tls.certCAFilename` | CA Certificate filename | `""` | +| `tls.dhParamsFilename` | File containing DH params (in order to support DH based ciphers) | `""` | + +### Metrics Parameters + +| Name | Description | Value | +| ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- | +| `metrics.enabled` | Start a sidecar prometheus exporter to expose Valkey metrics | `false` | +| `metrics.image.registry` | Valkey Exporter image registry | `REGISTRY_NAME` | +| `metrics.image.repository` | Valkey Exporter image repository | `REPOSITORY_NAME/valkey-exporter` | +| `metrics.image.digest` | Valkey Exporter image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `metrics.image.pullPolicy` | Valkey Exporter image pull policy | `IfNotPresent` | +| `metrics.image.pullSecrets` | Valkey Exporter image pull secrets | `[]` | +| `metrics.containerPorts.http` | Metrics HTTP container port | `9121` | +| `metrics.startupProbe.enabled` | Enable startupProbe on Valkey replicas nodes | `false` | +| `metrics.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `10` | +| `metrics.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `metrics.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `metrics.startupProbe.failureThreshold` | Failure threshold for startupProbe | `5` | +| `metrics.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `metrics.livenessProbe.enabled` | Enable livenessProbe on Valkey replicas nodes | `true` | +| `metrics.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `10` | +| `metrics.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `metrics.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `metrics.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `5` | +| `metrics.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `metrics.readinessProbe.enabled` | Enable readinessProbe on Valkey replicas nodes | `true` | +| `metrics.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `metrics.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `metrics.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `1` | +| `metrics.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `3` | +| `metrics.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `metrics.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `metrics.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `metrics.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `metrics.command` | Override default metrics container init command (useful when using custom images) | `[]` | +| `metrics.valkeyTargetHost` | A way to specify an alternative Valkey hostname | `localhost` | +| `metrics.extraArgs` | Extra arguments for Valkey exporter, for example: | `{}` | +| `metrics.extraEnvVars` | Array with extra environment variables to add to Valkey exporter | `[]` | +| `metrics.containerSecurityContext.enabled` | Enabled Valkey exporter containers' Security Context | `true` | +| `metrics.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `metrics.containerSecurityContext.runAsUser` | Set Valkey exporter containers' Security Context runAsUser | `1001` | +| `metrics.containerSecurityContext.runAsGroup` | Set Valkey exporter containers' Security Context runAsGroup | `1001` | +| `metrics.containerSecurityContext.runAsNonRoot` | Set Valkey exporter containers' Security Context runAsNonRoot | `true` | +| `metrics.containerSecurityContext.allowPrivilegeEscalation` | Set Valkey exporter containers' Security Context allowPrivilegeEscalation | `false` | +| `metrics.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context read-only root filesystem | `true` | +| `metrics.containerSecurityContext.seccompProfile.type` | Set Valkey exporter containers' Security Context seccompProfile | `RuntimeDefault` | +| `metrics.containerSecurityContext.capabilities.drop` | Set Valkey exporter containers' Security Context capabilities to drop | `["ALL"]` | +| `metrics.extraVolumes` | Optionally specify extra list of additional volumes for the Valkey metrics sidecar | `[]` | +| `metrics.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the Valkey metrics sidecar | `[]` | +| `metrics.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if metrics.resources is set (metrics.resources is recommended for production). | `nano` | +| `metrics.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `metrics.podLabels` | Extra labels for Valkey exporter pods | `{}` | +| `metrics.podAnnotations` | Annotations for Valkey exporter pods | `{}` | +| `metrics.service.enabled` | Create Service resource(s) for scraping metrics using PrometheusOperator ServiceMonitor, can be disabled when using a PodMonitor | `true` | +| `metrics.service.type` | Valkey exporter service type | `ClusterIP` | +| `metrics.service.ports.http` | Valkey exporter service port | `9121` | +| `metrics.service.externalTrafficPolicy` | Valkey exporter service external traffic policy | `Cluster` | +| `metrics.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `metrics.service.loadBalancerIP` | Valkey exporter service Load Balancer IP | `""` | +| `metrics.service.loadBalancerClass` | exporter service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) | `""` | +| `metrics.service.loadBalancerSourceRanges` | Valkey exporter service Load Balancer sources | `[]` | +| `metrics.service.annotations` | Additional custom annotations for Valkey exporter service | `{}` | +| `metrics.service.clusterIP` | Valkey exporter service Cluster IP | `""` | +| `metrics.serviceMonitor.port` | the service port to scrape metrics from | `http-metrics` | +| `metrics.serviceMonitor.enabled` | Create ServiceMonitor resource(s) for scraping metrics using PrometheusOperator | `false` | +| `metrics.serviceMonitor.namespace` | The namespace in which the ServiceMonitor will be created | `""` | +| `metrics.serviceMonitor.interval` | The interval at which metrics should be scraped | `30s` | +| `metrics.serviceMonitor.scrapeTimeout` | The timeout after which the scrape is ended | `""` | +| `metrics.serviceMonitor.relabelings` | Metrics RelabelConfigs to apply to samples before scraping. | `[]` | +| `metrics.serviceMonitor.metricRelabelings` | Metrics RelabelConfigs to apply to samples before ingestion. | `[]` | +| `metrics.serviceMonitor.honorLabels` | Specify honorLabels parameter to add the scrape endpoint | `false` | +| `metrics.serviceMonitor.additionalLabels` | Additional labels that can be used so ServiceMonitor resource(s) can be discovered by Prometheus | `{}` | +| `metrics.serviceMonitor.podTargetLabels` | Labels from the Kubernetes pod to be transferred to the created metrics | `[]` | +| `metrics.serviceMonitor.sampleLimit` | Limit of how many samples should be scraped from every Pod | `false` | +| `metrics.serviceMonitor.targetLimit` | Limit of how many targets should be scraped | `false` | +| `metrics.serviceMonitor.additionalEndpoints` | Additional endpoints to scrape (e.g sentinel) | `[]` | +| `metrics.podMonitor.port` | the pod port to scrape metrics from | `metrics` | +| `metrics.podMonitor.enabled` | Create PodMonitor resource(s) for scraping metrics using PrometheusOperator | `false` | +| `metrics.podMonitor.namespace` | The namespace in which the PodMonitor will be created | `""` | +| `metrics.podMonitor.interval` | The interval at which metrics should be scraped | `30s` | +| `metrics.podMonitor.scrapeTimeout` | The timeout after which the scrape is ended | `""` | +| `metrics.podMonitor.relabelings` | Metrics RelabelConfigs to apply to samples before scraping. | `[]` | +| `metrics.podMonitor.metricRelabelings` | Metrics RelabelConfigs to apply to samples before ingestion. | `[]` | +| `metrics.podMonitor.honorLabels` | Specify honorLabels parameter to add the scrape endpoint | `false` | +| `metrics.podMonitor.additionalLabels` | Additional labels that can be used so PodMonitor resource(s) can be discovered by Prometheus | `{}` | +| `metrics.podMonitor.podTargetLabels` | Labels from the Kubernetes pod to be transferred to the created metrics | `[]` | +| `metrics.podMonitor.sampleLimit` | Limit of how many samples should be scraped from every Pod | `false` | +| `metrics.podMonitor.targetLimit` | Limit of how many targets should be scraped | `false` | +| `metrics.podMonitor.additionalEndpoints` | Additional endpoints to scrape (e.g sentinel) | `[]` | +| `metrics.prometheusRule.enabled` | Create a custom prometheusRule Resource for scraping metrics using PrometheusOperator | `false` | +| `metrics.prometheusRule.namespace` | The namespace in which the prometheusRule will be created | `""` | +| `metrics.prometheusRule.additionalLabels` | Additional labels for the prometheusRule | `{}` | +| `metrics.prometheusRule.rules` | Custom Prometheus rules | `[]` | + +### Init Container Parameters + +| Name | Description | Value | +| ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | +| `volumePermissions.enabled` | Enable init container that changes the owner/group of the PV mount point to `runAsUser:fsGroup` | `false` | +| `volumePermissions.image.registry` | OS Shell + Utility image registry | `REGISTRY_NAME` | +| `volumePermissions.image.repository` | OS Shell + Utility image repository | `REPOSITORY_NAME/os-shell` | +| `volumePermissions.image.digest` | OS Shell + Utility image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `volumePermissions.image.pullPolicy` | OS Shell + Utility image pull policy | `IfNotPresent` | +| `volumePermissions.image.pullSecrets` | OS Shell + Utility image pull secrets | `[]` | +| `volumePermissions.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if volumePermissions.resources is set (volumePermissions.resources is recommended for production). | `nano` | +| `volumePermissions.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `volumePermissions.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `volumePermissions.containerSecurityContext.runAsUser` | Set init container's Security Context runAsUser | `0` | +| `kubectl.image.registry` | Kubectl image registry | `REGISTRY_NAME` | +| `kubectl.image.repository` | Kubectl image repository | `REPOSITORY_NAME/kubectl` | +| `kubectl.image.digest` | Kubectl image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `kubectl.image.pullPolicy` | Kubectl image pull policy | `IfNotPresent` | +| `kubectl.image.pullSecrets` | Kubectl pull secrets | `[]` | +| `kubectl.command` | kubectl command to execute | `["/opt/bitnami/scripts/kubectl-scripts/update-primary-label.sh"]` | +| `kubectl.containerSecurityContext.enabled` | Enabled kubectl containers' Security Context | `true` | +| `kubectl.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `kubectl.containerSecurityContext.runAsUser` | Set kubectl containers' Security Context runAsUser | `1001` | +| `kubectl.containerSecurityContext.runAsGroup` | Set kubectl containers' Security Context runAsGroup | `1001` | +| `kubectl.containerSecurityContext.runAsNonRoot` | Set kubectl containers' Security Context runAsNonRoot | `true` | +| `kubectl.containerSecurityContext.allowPrivilegeEscalation` | Set kubectl containers' Security Context allowPrivilegeEscalation | `false` | +| `kubectl.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context read-only root filesystem | `true` | +| `kubectl.containerSecurityContext.seccompProfile.type` | Set kubectl containers' Security Context seccompProfile | `RuntimeDefault` | +| `kubectl.containerSecurityContext.capabilities.drop` | Set kubectl containers' Security Context capabilities to drop | `["ALL"]` | +| `kubectl.resources.limits` | The resources limits for the kubectl containers | `{}` | +| `kubectl.resources.requests` | The requested resources for the kubectl containers | `{}` | + +### useExternalDNS Parameters + +| Name | Description | Value | +| -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | +| `useExternalDNS.enabled` | Enable various syntax that would enable external-dns to work. Note this requires a working installation of `external-dns` to be usable. | `false` | +| `useExternalDNS.additionalAnnotations` | Extra annotations to be utilized when `external-dns` is enabled. | `{}` | +| `useExternalDNS.annotationKey` | The annotation key utilized when `external-dns` is enabled. Setting this to `false` will disable annotations. | `external-dns.alpha.kubernetes.io/` | +| `useExternalDNS.suffix` | The DNS suffix utilized when `external-dns` is enabled. Note that we prepend the suffix with the full name of the release. | `""` | + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +helm install my-release \ + --set auth.password=secretpassword \ + oci://REGISTRY_NAME/REPOSITORY_NAME/valkey +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The above command sets the Valkey server password to `secretpassword`. + +> NOTE: Once this chart is deployed, it is not possible to change the application's access credentials, such as usernames or passwords, using Helm. To change these application credentials after deployment, delete any persistent volumes (PVs) used by the chart and re-deploy it, or use the application's built-in administrative tools if available. + +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 oci://REGISTRY_NAME/REPOSITORY_NAME/valkey +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> **Tip**: You can use the default [values.yaml](https://github.com/bitnami/charts/tree/main/bitnami/valkey/values.yaml) + +## Troubleshooting + +Find more information about how to deal with common errors related to Bitnami's Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues). + +## Upgrading + +### To 2.2.0 + +This version introduces image verification for security purposes. To disable it, set `global.security.allowInsecureImages` to `true`. More details at [GitHub issue](https://github.com/bitnami/charts/issues/30850). + +### To 2.0.0 + +This major updates all the references from `master/slave` to `primary/replica` to follow the upstream project strategy: + +- The term *master* has been replaced by the term *primary*. Therefore, parameters prefixed with `master` are now prefixed with `primary`. +- Environment variables previously prefixed as `VALKEY_MASTER` or `VALKEY_SENTINEL_MASTER` use `VALKEY_PRIMARY` and `VALKEY_SENTINEL_PRIMARY` now. + +Consequences: + +Backwards compatibility is not guaranteed. To upgrade to `2.0.0`, install a new release of the Valkey chart, and migrate the data from your previous release. You have 2 alternatives to do so: + +- Create a backup of the database, and restore it on the new release as explained in the [Backup and restore](#backup-and-restore) section. +- Reuse the PVC used to hold the master data on your previous release. To do so, use the `primary.persistence.existingClaim` parameter. The following example assumes that the release name is `valkey`: + +```console +helm install valkey oci://REGISTRY_NAME/REPOSITORY_NAME/valkey --set auth.password=[PASSWORD] --set primary.persistence.existingClaim=[EXISTING_PVC] +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +| Note: you need to substitute the placeholder *[EXISTING_PVC]* with the name of the PVC used on your previous release, and *[PASSWORD]* with the password used in your previous release. + +## License + +Copyright © 2025 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/backing-services/gitea/charts/valkey/charts/common/.helmignore b/backing-services/gitea/charts/valkey/charts/common/.helmignore new file mode 100644 index 0000000..d0e1084 --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/.helmignore @@ -0,0 +1,26 @@ +# 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 +.vscode/ +# img folder +img/ +# Changelog +CHANGELOG.md diff --git a/backing-services/gitea/charts/valkey/charts/common/Chart.yaml b/backing-services/gitea/charts/valkey/charts/common/Chart.yaml new file mode 100644 index 0000000..fb04f76 --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/Chart.yaml @@ -0,0 +1,23 @@ +annotations: + category: Infrastructure + licenses: Apache-2.0 +apiVersion: v2 +appVersion: 2.31.4 +description: A Library Helm Chart for grouping common logic between bitnami charts. + This chart is not deployable by itself. +home: https://bitnami.com +icon: https://dyltqmyl993wv.cloudfront.net/downloads/logos/bitnami-mark.png +keywords: +- common +- helper +- template +- function +- bitnami +maintainers: +- name: Broadcom, Inc. All Rights Reserved. + url: https://github.com/bitnami/charts +name: common +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/common +type: library +version: 2.31.4 diff --git a/backing-services/gitea/charts/valkey/charts/common/README.md b/backing-services/gitea/charts/valkey/charts/common/README.md new file mode 100644 index 0000000..71368aa --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/README.md @@ -0,0 +1,387 @@ +# Bitnami Common Library Chart + +A [Helm Library Chart](https://helm.sh/docs/topics/library_charts/#helm) for grouping common logic between Bitnami charts. + +## TL;DR + +```yaml +dependencies: + - name: common + version: 2.x.x + repository: oci://registry-1.docker.io/bitnamicharts +``` + +```console +helm dependency update +``` + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "common.names.fullname" . }} +data: + myvalue: "Hello World" +``` + +Looking to use our applications in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the commercial edition of the Bitnami catalog. + +## ⚠️ Important Notice: Upcoming changes to the Bitnami Catalog + +Beginning August 28th, 2025, Bitnami will evolve its public catalog to offer a curated set of hardened, security-focused images under the new [Bitnami Secure Images initiative](https://news.broadcom.com/app-dev/broadcom-introduces-bitnami-secure-images-for-production-ready-containerized-applications). As part of this transition: + +- Granting community users access for the first time to security-optimized versions of popular container images. +- Bitnami will begin deprecating support for non-hardened, Debian-based software images in its free tier and will gradually remove non-latest tags from the public catalog. As a result, community users will have access to a reduced number of hardened images. These images are published only under the “latest” tag and are intended for development purposes +- Starting August 28th, over two weeks, all existing container images, including older or versioned tags (e.g., 2.50.0, 10.6), will be migrated from the public catalog (docker.io/bitnami) to the “Bitnami Legacy” repository (docker.io/bitnamilegacy), where they will no longer receive updates. +- For production workloads and long-term support, users are encouraged to adopt Bitnami Secure Images, which include hardened containers, smaller attack surfaces, CVE transparency (via VEX/KEV), SBOMs, and enterprise support. + +These changes aim to improve the security posture of all Bitnami users by promoting best practices for software supply chain integrity and up-to-date deployments. For more details, visit the [Bitnami Secure Images announcement](https://github.com/bitnami/containers/issues/83267). + +## Introduction + +This chart provides a common template helpers which can be used to develop new charts using [Helm](https://helm.sh) package manager. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ + +## Parameters + +The following table lists the helpers available in the library which are scoped in different sections. + +### Affinities + +| Helper identifier | Description | Expected Input | +| ------------------------------- | ---------------------------------------------------- | ------------------------------------------------------------ | +| `common.affinities.nodes.soft` | Return a soft nodeAffinity definition | `dict "key" "FOO" "values" (list "BAR" "BAZ")` | +| `common.affinities.nodes.hard` | Return a hard nodeAffinity definition | `dict "key" "FOO" "values" (list "BAR" "BAZ")` | +| `common.affinities.nodes` | Return a nodeAffinity definition | `dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")` | +| `common.affinities.topologyKey` | Return a topologyKey definition | `dict "topologyKey" "FOO"` | +| `common.affinities.pods.soft` | Return a soft podAffinity/podAntiAffinity definition | `dict "component" "FOO" "context" $` | +| `common.affinities.pods.hard` | Return a hard podAffinity/podAntiAffinity definition | `dict "component" "FOO" "context" $` | +| `common.affinities.pods` | Return a podAffinity/podAntiAffinity definition | `dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")` | + +### Capabilities + +| Helper identifier | Description | Expected Input | +| --------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------- | +| `common.capabilities.kubeVersion` | Return the target Kubernetes version (using client default if .Values.kubeVersion is not set). | `.` Chart context | +| `common.capabilities.apiVersions.has` | Return true if the apiVersion is supported | `dict "version" "batch/v1" "context" $` | +| `common.capabilities.job.apiVersion` | Return the appropriate apiVersion for job. | `.` Chart context | +| `common.capabilities.cronjob.apiVersion` | Return the appropriate apiVersion for cronjob. | `.` Chart context | +| `common.capabilities.daemonset.apiVersion` | Return the appropriate apiVersion for daemonset. | `.` Chart context | +| `common.capabilities.deployment.apiVersion` | Return the appropriate apiVersion for deployment. | `.` Chart context | +| `common.capabilities.statefulset.apiVersion` | Return the appropriate apiVersion for statefulset. | `.` Chart context | +| `common.capabilities.ingress.apiVersion` | Return the appropriate apiVersion for ingress. | `.` Chart context | +| `common.capabilities.rbac.apiVersion` | Return the appropriate apiVersion for RBAC resources. | `.` Chart context | +| `common.capabilities.crd.apiVersion` | Return the appropriate apiVersion for CRDs. | `.` Chart context | +| `common.capabilities.policy.apiVersion` | Return the appropriate apiVersion for podsecuritypolicy. | `.` Chart context | +| `common.capabilities.networkPolicy.apiVersion` | Return the appropriate apiVersion for networkpolicy. | `.` Chart context | +| `common.capabilities.apiService.apiVersion` | Return the appropriate apiVersion for APIService. | `.` Chart context | +| `common.capabilities.hpa.apiVersion` | Return the appropriate apiVersion for Horizontal Pod Autoscaler | `.` Chart context | +| `common.capabilities.vpa.apiVersion` | Return the appropriate apiVersion for Vertical Pod Autoscaler. | `.` Chart context | +| `common.capabilities.psp.supported` | Returns true if PodSecurityPolicy is supported | `.` Chart context | +| `common.capabilities.supportsHelmVersion` | Returns true if the used Helm version is 3.3+ | `.` Chart context | +| `common.capabilities.admissionConfiguration.supported` | Returns true if AdmissionConfiguration is supported | `.` Chart context | +| `common.capabilities.admissionConfiguration.apiVersion` | Return the appropriate apiVersion for AdmissionConfiguration. | `.` Chart context | +| `common.capabilities.podSecurityConfiguration.apiVersion` | Return the appropriate apiVersion for PodSecurityConfiguration. | `.` Chart context | + +### Compatibility + +| Helper identifier | Description | Expected Input | +| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | +| `common.compatibility.isOpenshift` | Return true if the detected platform is Openshift | `.` Chart context | +| `common.compatibility.renderSecurityContext` | Render a compatible securityContext depending on the platform. By default it is maintained as it is. In other platforms like Openshift we remove default user/group values that do not work out of the box with the restricted-v1 SCC | `dict "secContext" .Values.containerSecurityContext "context" $` | + +### Errors + +| Helper identifier | Description | Expected Input | +| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | +| `common.errors.upgrade.passwords.empty` | It will ensure required passwords are given when we are upgrading a chart. If `validationErrors` is not empty it will throw an error and will stop the upgrade action. | `dict "validationErrors" (list $validationError00 $validationError01) "context" $` | +| `common.errors.insecureImages` | Throw error when original container images are replaced. The error can be bypassed by setting the `global.security.allowInsecureImages` to true. | `dict "images" (list .Values.path.to.the.imageRoot) "context" $` | + +### Images + +| Helper identifier | Description | Expected Input | +| --------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | +| `common.images.image` | Return the proper and full image name | `dict "imageRoot" .Values.path.to.the.image "global" $`, see [ImageRoot](#imageroot) for the structure. | +| `common.images.pullSecrets` | Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead) | `dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global` | +| `common.images.renderPullSecrets` | Return the proper Docker Image Registry Secret Names (evaluates values as templates) | `dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $` | +| `common.images.version` | Return the proper image version | `dict "imageRoot" .Values.path.to.the.image "chart" .Chart` , see [ImageRoot](#imageroot) for the structure. | + +### Ingress + +| Helper identifier | Description | Expected Input | +| ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `common.ingress.backend` | Generate a proper Ingress backend entry depending on the API version | `dict "serviceName" "foo" "servicePort" "bar"`, see the [Ingress deprecation notice](https://kubernetes.io/blog/2019/07/18/api-deprecations-in-1-16/) for the syntax differences | +| `common.ingress.certManagerRequest` | Prints "true" if required cert-manager annotations for TLS signed certificates are set in the Ingress annotations | `dict "annotations" .Values.path.to.the.ingress.annotations` | + +### Labels + +| Helper identifier | Description | Expected Input | +| --------------------------- | --------------------------------------------------------------------------- | ----------------- | +| `common.labels.standard` | Return Kubernetes standard labels | `.` Chart context | +| `common.labels.matchLabels` | Labels to use on `deploy.spec.selector.matchLabels` and `svc.spec.selector` | `.` Chart context | + +### Names + +| Helper identifier | Description | Expected Input | +| ---------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | +| `common.names.name` | Expand the name of the chart or use `.Values.nameOverride` | `.` Chart context | +| `common.names.fullname` | Create a default fully qualified app name. | `.` Chart context | +| `common.names.namespace` | Allow the release namespace to be overridden | `.` Chart context | +| `common.names.fullname.namespace` | Create a fully qualified app name adding the installation's namespace | `.` Chart context | +| `common.names.chart` | Chart name plus version | `.` Chart context | +| `common.names.dependency.fullname` | Create a default fully qualified dependency name. | `dict "chartName" "dependency-chart-name" "chartValues" .Values.dependency-chart "context" $` | + +### Resources + +| Helper identifier | Description | Expected Input | +| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | +| `common.resources.preset` | Return a resource request/limit object based on a given preset. These presets are for basic testing and not meant to be used in production. | `dict "type" "nano"` | + +### Secrets + +| Helper identifier | Description | Expected Input | +| --------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `common.secrets.name` | Generate the name of the secret. | `dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $` see [ExistingSecret](#existingsecret) for the structure. | +| `common.secrets.key` | Generate secret key. | `dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName"` see [ExistingSecret](#existingsecret) for the structure. | +| `common.secrets.passwords.manage` | Generate secret password or retrieve one if already created. | `dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "honorProvidedValues" false "context" $`, length, strong, honorProvidedValues and chartName fields are optional. | +| `common.secrets.exists` | Returns whether a previous generated secret already exists. | `dict "secret" "secret-name" "context" $` | +| `common.secrets.lookup` | Reuses the value from an existing secret, otherwise sets its value to a default value. | `dict "secret" "secret-name" "key" "keyName" "defaultValue" .Values.myValue "context" $` | + +### Storage + +| Helper identifier | Description | Expected Input | +| ---------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------- | +| `common.storage.class` | Return the proper Storage Class | `dict "persistence" .Values.path.to.the.persistence "global" $`, see [Persistence](#persistence) for the structure. | + +### TplValues + +| Helper identifier | Description | Expected Input | +| ---------------------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `common.tplvalues.render` | Renders a value that contains template | `dict "value" .Values.path.to.the.Value "context" $`, value is the value should rendered as template, context frequently is the chart context `$` or `.` | +| `common.tplvalues.merge` | Merge a list of values that contains template after rendering them. | `dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $` | +| `common.tplvalues.merge-overwrite` | Merge a list of values that contains template after rendering them. | `dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $` | + +### Utils + +| Helper identifier | Description | Expected Input | +| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | +| `common.utils.fieldToEnvVar` | Build environment variable name given a field. | `dict "field" "my-password"` | +| `common.utils.secret.getvalue` | Print instructions to get a secret value. | `dict "secret" "secret-name" "field" "secret-value-field" "context" $` | +| `common.utils.getValueFromKey` | Gets a value from `.Values` object given its key path | `dict "key" "path.to.key" "context" $` | +| `common.utils.getKeyFromList` | Returns first `.Values` key with a defined value or first of the list if all non-defined | `dict "keys" (list "path.to.key1" "path.to.key2") "context" $` | +| `common.utils.checksumTemplate` | Checksum a template at "path" containing a *single* resource (ConfigMap,Secret) for use in pod annotations, excluding the metadata (see #18376) | `dict "path" "/configmap.yaml" "context" $` | + +### Validations + +| Helper identifier | Description | Expected Input | +| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `common.validations.values.single.empty` | Validate a value must not be empty. | `dict "valueKey" "path.to.value" "secret" "secret.name" "field" "my-password" "subchart" "subchart" "context" $` secret, field and subchart are optional. In case they are given, the helper will generate a how to get instruction. See [ValidateValue](#validatevalue) | +| `common.validations.values.multiple.empty` | Validate a multiple values must not be empty. It returns a shared error for all the values. | `dict "required" (list $validateValueConf00 $validateValueConf01) "context" $`. See [ValidateValue](#validatevalue) | +| `common.validations.values.mariadb.passwords` | This helper will ensure required password for MariaDB are not empty. It returns a shared error for all the values. | `dict "secret" "mariadb-secret" "subchart" "true" "context" $` subchart field is optional and could be true or false it depends on where you will use mariadb chart and the helper. | + +### Warnings + +| Helper identifier | Description | Expected Input | +| -------------------------------- | ----------------------------------------------------------------- | ---------------------------------------------------------- | +| `common.warnings.rollingTag` | Warning about using rolling tag. | `ImageRoot` see [ImageRoot](#imageroot) for the structure. | +| `common.warnings.modifiedImages` | Warning about replaced images from the original. | `ImageRoot` see [ImageRoot](#imageroot) for the structure. | +| `common.warnings.resources` | Warning about not setting the resource object in all deployments. | `dict "sections" (list "path1" "path2") context $` | + +## Special input schemas + +### ImageRoot + +```yaml +registry: + type: string + description: Docker registry where the image is located + example: docker.io + +repository: + type: string + description: Repository and image name + example: bitnami/nginx + +tag: + type: string + description: image tag + example: 1.16.1-debian-10-r63 + +pullPolicy: + type: string + description: Specify a imagePullPolicy.' + +pullSecrets: + type: array + items: + type: string + description: Optionally specify an array of imagePullSecrets (evaluated as templates). + +debug: + type: boolean + description: Set to true if you would like to see extra information on logs + example: false + +## An instance would be: +# registry: docker.io +# repository: bitnami/nginx +# tag: 1.16.1-debian-10-r63 +# pullPolicy: IfNotPresent +# debug: false +``` + +### Persistence + +```yaml +enabled: + type: boolean + description: Whether enable persistence. + example: true + +storageClass: + type: string + description: Ghost data Persistent Volume Storage Class, If set to "-", storageClassName: "" which disables dynamic provisioning. + example: "-" + +accessMode: + type: string + description: Access mode for the Persistent Volume Storage. + example: ReadWriteOnce + +size: + type: string + description: Size the Persistent Volume Storage. + example: 8Gi + +path: + type: string + description: Path to be persisted. + example: /bitnami + +## An instance would be: +# enabled: true +# storageClass: "-" +# accessMode: ReadWriteOnce +# size: 8Gi +# path: /bitnami +``` + +### ExistingSecret + +```yaml +name: + type: string + description: Name of the existing secret. + example: mySecret +keyMapping: + description: Mapping between the expected key name and the name of the key in the existing secret. + type: object + +## An instance would be: +# name: mySecret +# keyMapping: +# password: myPasswordKey +``` + +#### Example of use + +When we store sensitive data for a deployment in a secret, some times we want to give to users the possibility of using theirs existing secrets. + +```yaml +# templates/secret.yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }} + labels: + app: {{ include "common.names.fullname" . }} +type: Opaque +data: + password: {{ .Values.password | b64enc | quote }} + +# templates/dpl.yaml +--- +... + env: + - name: PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "common.secrets.name" (dict "existingSecret" .Values.existingSecret "context" $) }} + key: {{ include "common.secrets.key" (dict "existingSecret" .Values.existingSecret "key" "password") }} +... + +# values.yaml +--- +name: mySecret +keyMapping: + password: myPasswordKey +``` + +### ValidateValue + +#### NOTES.txt + +```console +{{- $validateValueConf00 := (dict "valueKey" "path.to.value00" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value01" "secret" "secretName" "field" "password-01") -}} + +{{ include "common.validations.values.multiple.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} +``` + +If we force those values to be empty we will see some alerts + +```console +helm install test mychart --set path.to.value00="",path.to.value01="" + 'path.to.value00' must not be empty, please add '--set path.to.value00=$PASSWORD_00' to the command. To get the current value: + + export PASSWORD_00=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-00}" | base64 -d) + + 'path.to.value01' must not be empty, please add '--set path.to.value01=$PASSWORD_01' to the command. To get the current value: + + export PASSWORD_01=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-01}" | base64 -d) +``` + +## Upgrading + +### To 1.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +#### What changes were introduced in this major version? + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- Use `type: library`. [Here](https://v3.helm.sh/docs/faq/#library-chart-support) you can find more information. +- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts + +#### Considerations when upgrading to this version + +- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues +- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore +- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 + +#### Useful links + +- +- +- + +## License + +Copyright © 2025 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/backing-services/gitea/charts/valkey/charts/common/templates/_affinities.tpl b/backing-services/gitea/charts/valkey/charts/common/templates/_affinities.tpl new file mode 100644 index 0000000..c6ccc62 --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/templates/_affinities.tpl @@ -0,0 +1,169 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a soft nodeAffinity definition +{{ include "common.affinities.nodes.soft" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.soft" -}} +preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} + weight: 1 +{{- end -}} + +{{/* +Return a hard nodeAffinity definition +{{ include "common.affinities.nodes.hard" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.hard" -}} +requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} +{{- end -}} + +{{/* +Return a nodeAffinity definition +{{ include "common.affinities.nodes" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.nodes.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.nodes.hard" . -}} + {{- end -}} +{{- end -}} + +{{/* +Return a topologyKey definition +{{ include "common.affinities.topologyKey" (dict "topologyKey" "BAR") -}} +*/}} +{{- define "common.affinities.topologyKey" -}} +{{ .topologyKey | default "kubernetes.io/hostname" -}} +{{- end -}} + +{{/* +Return a soft podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.soft" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "extraNamespaces" (list "namespace1" "namespace2") "context" $) -}} +*/}} +{{- define "common.affinities.pods.soft" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +{{- $extraNamespaces := default (list) .extraNamespaces -}} +preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if $extraNamespaces }} + namespaces: + - {{ .context.Release.Namespace }} + {{- with $extraNamespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: 1 + {{- range $extraPodAffinityTerms }} + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if .namespaces }} + namespaces: + - {{ $.context.Release.Namespace }} + {{- with .namespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: {{ .weight | default 1 -}} + {{- end -}} +{{- end -}} + +{{/* +Return a hard podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.hard" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "extraNamespaces" (list "namespace1" "namespace2") "context" $) -}} +*/}} +{{- define "common.affinities.pods.hard" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +{{- $extraNamespaces := default (list) .extraNamespaces -}} +requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if $extraNamespaces }} + namespaces: + - {{ .context.Release.Namespace }} + {{- with $extraNamespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 6 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- range $extraPodAffinityTerms }} + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if .namespaces }} + namespaces: + - {{ $.context.Release.Namespace }} + {{- with .namespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 6 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- end -}} +{{- end -}} + +{{/* +Return a podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.pods" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.pods.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.pods.hard" . -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey/charts/common/templates/_capabilities.tpl b/backing-services/gitea/charts/valkey/charts/common/templates/_capabilities.tpl new file mode 100644 index 0000000..58f58c1 --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/templates/_capabilities.tpl @@ -0,0 +1,178 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the target Kubernetes version +*/}} +{{- define "common.capabilities.kubeVersion" -}} +{{- default (default .Capabilities.KubeVersion.Version .Values.kubeVersion) ((.Values.global).kubeVersion) -}} +{{- end -}} + +{{/* +Return true if the apiVersion is supported +Usage: +{{ include "common.capabilities.apiVersions.has" (dict "version" "batch/v1" "context" $) }} +*/}} +{{- define "common.capabilities.apiVersions.has" -}} +{{- $providedAPIVersions := default .context.Values.apiVersions ((.context.Values.global).apiVersions) -}} +{{- if and (empty $providedAPIVersions) (.context.Capabilities.APIVersions.Has .version) -}} + {{- true -}} +{{- else if has .version $providedAPIVersions -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for poddisruptionbudget. +*/}} +{{- define "common.capabilities.policy.apiVersion" -}} +{{- print "policy/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "common.capabilities.networkPolicy.apiVersion" -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for job. +*/}} +{{- define "common.capabilities.job.apiVersion" -}} +{{- print "batch/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for cronjob. +*/}} +{{- define "common.capabilities.cronjob.apiVersion" -}} +{{- print "batch/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for daemonset. +*/}} +{{- define "common.capabilities.daemonset.apiVersion" -}} +{{- print "apps/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for deployment. +*/}} +{{- define "common.capabilities.deployment.apiVersion" -}} +{{- print "apps/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for statefulset. +*/}} +{{- define "common.capabilities.statefulset.apiVersion" -}} +{{- print "apps/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "common.capabilities.ingress.apiVersion" -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for RBAC resources. +*/}} +{{- define "common.capabilities.rbac.apiVersion" -}} +{{- print "rbac.authorization.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for CRDs. +*/}} +{{- define "common.capabilities.crd.apiVersion" -}} +{{- print "apiextensions.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for APIService. +*/}} +{{- define "common.capabilities.apiService.apiVersion" -}} +{{- print "apiregistration.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Horizontal Pod Autoscaler. +*/}} +{{- define "common.capabilities.hpa.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" .context -}} +{{- print "autoscaling/v2" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Vertical Pod Autoscaler. +*/}} +{{- define "common.capabilities.vpa.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "autoscaling/v1beta2" -}} +{{- else -}} +{{- print "autoscaling/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if PodSecurityPolicy is supported +*/}} +{{- define "common.capabilities.psp.supported" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if or (empty $kubeVersion) (semverCompare "<1.25-0" $kubeVersion) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if AdmissionConfiguration is supported +*/}} +{{- define "common.capabilities.admissionConfiguration.supported" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} + {{- true -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for AdmissionConfiguration. +*/}} +{{- define "common.capabilities.admissionConfiguration.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "apiserver.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiserver.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for PodSecurityConfiguration. +*/}} +{{- define "common.capabilities.podSecurityConfiguration.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "pod-security.admission.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "pod-security.admission.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the used Helm version is 3.3+. +A way to check the used Helm version was not introduced until version 3.3.0 with .Capabilities.HelmVersion, which contains an additional "{}}" structure. +This check is introduced as a regexMatch instead of {{ if .Capabilities.HelmVersion }} because checking for the key HelmVersion in <3.3 results in a "interface not found" error. +**To be removed when the catalog's minimun Helm version is 3.3** +*/}} +{{- define "common.capabilities.supportsHelmVersion" -}} +{{- if regexMatch "{(v[0-9])*[^}]*}}$" (.Capabilities | toString ) }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey/charts/common/templates/_compatibility.tpl b/backing-services/gitea/charts/valkey/charts/common/templates/_compatibility.tpl new file mode 100644 index 0000000..19c26db --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/templates/_compatibility.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return true if the detected platform is Openshift +Usage: +{{- include "common.compatibility.isOpenshift" . -}} +*/}} +{{- define "common.compatibility.isOpenshift" -}} +{{- if .Capabilities.APIVersions.Has "security.openshift.io/v1" -}} +{{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Render a compatible securityContext depending on the platform. By default it is maintained as it is. In other platforms like Openshift we remove default user/group values that do not work out of the box with the restricted-v1 SCC +Usage: +{{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) -}} +*/}} +{{- define "common.compatibility.renderSecurityContext" -}} +{{- $adaptedContext := .secContext -}} + +{{- if (((.context.Values.global).compatibility).openshift) -}} + {{- if or (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "force") (and (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "auto") (include "common.compatibility.isOpenshift" .context)) -}} + {{/* Remove incompatible user/group values that do not work in Openshift out of the box */}} + {{- $adaptedContext = omit $adaptedContext "fsGroup" "runAsUser" "runAsGroup" -}} + {{- if not .secContext.seLinuxOptions -}} + {{/* If it is an empty object, we remove it from the resulting context because it causes validation issues */}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{/* Remove empty seLinuxOptions object if global.compatibility.omitEmptySeLinuxOptions is set to true */}} +{{- if and (((.context.Values.global).compatibility).omitEmptySeLinuxOptions) (not .secContext.seLinuxOptions) -}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} +{{- end -}} +{{/* Remove fields that are disregarded when running the container in privileged mode */}} +{{- if $adaptedContext.privileged -}} + {{- $adaptedContext = omit $adaptedContext "capabilities" -}} +{{- end -}} +{{- omit $adaptedContext "enabled" | toYaml -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey/charts/common/templates/_errors.tpl b/backing-services/gitea/charts/valkey/charts/common/templates/_errors.tpl new file mode 100644 index 0000000..fb704c9 --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/templates/_errors.tpl @@ -0,0 +1,92 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Throw error when upgrading using empty passwords values that must not be empty. + +Usage: +{{- $validationError00 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password00" "secret" "secretName" "field" "password-00") -}} +{{- $validationError01 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password01" "secret" "secretName" "field" "password-01") -}} +{{ include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $validationError00 $validationError01) "context" $) }} + +Required password params: + - validationErrors - String - Required. List of validation strings to be return, if it is empty it won't throw error. + - context - Context - Required. Parent context. +*/}} +{{- define "common.errors.upgrade.passwords.empty" -}} + {{- $validationErrors := join "" .validationErrors -}} + {{- if and $validationErrors .context.Release.IsUpgrade -}} + {{- $errorString := "\nPASSWORDS ERROR: You must provide your current passwords when upgrading the release." -}} + {{- $errorString = print $errorString "\n Note that even after reinstallation, old credentials may be needed as they may be kept in persistent volume claims." -}} + {{- $errorString = print $errorString "\n Further information can be obtained at https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues/#credential-errors-while-upgrading-chart-releases" -}} + {{- $errorString = print $errorString "\n%s" -}} + {{- printf $errorString $validationErrors | fail -}} + {{- end -}} +{{- end -}} + +{{/* +Throw error when original container images are replaced. +The error can be bypassed by setting the "global.security.allowInsecureImages" to true. In this case, +a warning message will be shown instead. + +Usage: +{{ include "common.errors.insecureImages" (dict "images" (list .Values.path.to.the.imageRoot) "context" $) }} +*/}} +{{- define "common.errors.insecureImages" -}} +{{- $relocatedImages := list -}} +{{- $replacedImages := list -}} +{{- $bitnamiLegacyImages := list -}} +{{- $retaggedImages := list -}} +{{- $globalRegistry := ((.context.Values.global).imageRegistry) -}} +{{- $originalImages := .context.Chart.Annotations.images -}} +{{- range .images -}} + {{- $registryName := default .registry $globalRegistry -}} + {{- $fullImageNameNoTag := printf "%s/%s" $registryName .repository -}} + {{- $fullImageName := printf "%s:%s" $fullImageNameNoTag .tag -}} + {{- if not (contains $fullImageNameNoTag $originalImages) -}} + {{- if not (contains $registryName $originalImages) -}} + {{- $relocatedImages = append $relocatedImages $fullImageName -}} + {{- else if not (contains .repository $originalImages) -}} + {{- $replacedImages = append $replacedImages $fullImageName -}} + {{- if contains "docker.io/bitnamilegacy/" $fullImageNameNoTag -}} + {{- $bitnamiLegacyImages = append $bitnamiLegacyImages $fullImageName -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- if not (contains (printf "%s:%s" .repository .tag) $originalImages) -}} + {{- $retaggedImages = append $retaggedImages $fullImageName -}} + {{- end -}} +{{- end -}} + +{{- if and (or (gt (len $relocatedImages) 0) (gt (len $replacedImages) 0)) (((.context.Values.global).security).allowInsecureImages) -}} + {{- print "\n\n⚠ SECURITY WARNING: Verifying original container images was skipped. Please note this Helm chart was designed, tested, and validated on multiple platforms using a specific set of Bitnami and Bitnami Secure Images containers. Substituting other containers is likely to cause degraded security and performance, broken chart features, and missing environment variables.\n" -}} +{{- else if (or (gt (len $relocatedImages) 0) (gt (len $replacedImages) 0)) -}} + {{- $errorString := "Original containers have been substituted for unrecognized ones. Deploying this chart with non-standard containers is likely to cause degraded security and performance, broken chart features, and missing environment variables." -}} + {{- $errorString = print $errorString "\n\nUnrecognized images:" -}} + {{- range (concat $relocatedImages $replacedImages) -}} + {{- $errorString = print $errorString "\n - " . -}} + {{- end -}} + {{- if and (eq (len $relocatedImages) 0) (eq (len $replacedImages) (len $bitnamiLegacyImages)) -}} + {{- $errorString = print "\n\n⚠ WARNING: " $errorString -}} + {{- print $errorString -}} + {{- else if or (contains "docker.io/bitnami/" $originalImages) (contains "docker.io/bitnamiprem/" $originalImages) (contains "docker.io/bitnamisecure/" $originalImages) -}} + {{- $errorString = print "\n\n⚠ ERROR: " $errorString -}} + {{- $errorString = print $errorString "\n\nIf you are sure you want to proceed with non-standard containers, you can skip container image verification by setting the global parameter 'global.security.allowInsecureImages' to true." -}} + {{- $errorString = print $errorString "\nFurther information can be obtained at https://github.com/bitnami/charts/issues/30850" -}} + {{- print $errorString | fail -}} + {{- else if gt (len $replacedImages) 0 -}} + {{- $errorString = print "\n\n⚠ WARNING: " $errorString -}} + {{- print $errorString -}} + {{- end -}} +{{- else if gt (len $retaggedImages) 0 -}} + {{- $warnString := "\n\n⚠ WARNING: Original containers have been retagged. Please note this Helm chart was tested, and validated on multiple platforms using a specific set of Bitnami and Bitnami Secure Images containers. Substituting original image tags could cause unexpected behavior." -}} + {{- $warnString = print $warnString "\n\nRetagged images:" -}} + {{- range $retaggedImages -}} + {{- $warnString = print $warnString "\n - " . -}} + {{- end -}} + {{- print $warnString -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey/charts/common/templates/_images.tpl b/backing-services/gitea/charts/valkey/charts/common/templates/_images.tpl new file mode 100644 index 0000000..76bb7ce --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/templates/_images.tpl @@ -0,0 +1,115 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Return the proper image name. +If image tag and digest are not defined, termination fallbacks to chart appVersion. +{{ include "common.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" .Values.global "chart" .Chart ) }} +*/}} +{{- define "common.images.image" -}} +{{- $registryName := default .imageRoot.registry ((.global).imageRegistry) -}} +{{- $repositoryName := .imageRoot.repository -}} +{{- $separator := ":" -}} +{{- $termination := .imageRoot.tag | toString -}} + +{{- if not .imageRoot.tag }} + {{- if .chart }} + {{- $termination = .chart.AppVersion | toString -}} + {{- end -}} +{{- end -}} +{{- if .imageRoot.digest }} + {{- $separator = "@" -}} + {{- $termination = .imageRoot.digest | toString -}} +{{- end -}} +{{- if $registryName }} + {{- printf "%s/%s%s%s" $registryName $repositoryName $separator $termination -}} +{{- else -}} + {{- printf "%s%s%s" $repositoryName $separator $termination -}} +{{- end -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead) +{{ include "common.images.pullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global) }} +*/}} +{{- define "common.images.pullSecrets" -}} + {{- $pullSecrets := list }} + + {{- range ((.global).imagePullSecrets) -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end }} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) -}} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names evaluating values as templates +{{ include "common.images.renderPullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $) }} +*/}} +{{- define "common.images.renderPullSecrets" -}} + {{- $pullSecrets := list }} + {{- $context := .context }} + + {{- range (($context.Values.global).imagePullSecrets) -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) -}} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper image version (ingores image revision/prerelease info & fallbacks to chart appVersion) +{{ include "common.images.version" ( dict "imageRoot" .Values.path.to.the.image "chart" .Chart ) }} +*/}} +{{- define "common.images.version" -}} +{{- $imageTag := .imageRoot.tag | toString -}} +{{/* regexp from https://github.com/Masterminds/semver/blob/23f51de38a0866c5ef0bfc42b3f735c73107b700/version.go#L41-L44 */}} +{{- if regexMatch `^([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?$` $imageTag -}} + {{- $version := semver $imageTag -}} + {{- printf "%d.%d.%d" $version.Major $version.Minor $version.Patch -}} +{{- else -}} + {{- print .chart.AppVersion -}} +{{- end -}} +{{- end -}} + diff --git a/backing-services/gitea/charts/valkey/charts/common/templates/_ingress.tpl b/backing-services/gitea/charts/valkey/charts/common/templates/_ingress.tpl new file mode 100644 index 0000000..2d0dbf1 --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/templates/_ingress.tpl @@ -0,0 +1,41 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Generate backend entry that is compatible with all Kubernetes API versions. + +Usage: +{{ include "common.ingress.backend" (dict "serviceName" "backendName" "servicePort" "backendPort" "context" $) }} + +Params: + - serviceName - String. Name of an existing service backend + - servicePort - String/Int. Port name (or number) of the service. It will be translated to different yaml depending if it is a string or an integer. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.ingress.backend" -}} +service: + name: {{ .serviceName }} + port: + {{- if typeIs "string" .servicePort }} + name: {{ .servicePort }} + {{- else if or (typeIs "int" .servicePort) (typeIs "float64" .servicePort) }} + number: {{ .servicePort | int }} + {{- end }} +{{- end -}} + +{{/* +Return true if cert-manager required annotations for TLS signed +certificates are set in the Ingress annotations +Ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations +Usage: +{{ include "common.ingress.certManagerRequest" ( dict "annotations" .Values.path.to.the.ingress.annotations ) }} +*/}} +{{- define "common.ingress.certManagerRequest" -}} +{{ if or (hasKey .annotations "cert-manager.io/cluster-issuer") (hasKey .annotations "cert-manager.io/issuer") (hasKey .annotations "kubernetes.io/tls-acme") }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey/charts/common/templates/_labels.tpl b/backing-services/gitea/charts/valkey/charts/common/templates/_labels.tpl new file mode 100644 index 0000000..0a0cc54 --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/templates/_labels.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Kubernetes standard labels +{{ include "common.labels.standard" (dict "customLabels" .Values.commonLabels "context" $) -}} +*/}} +{{- define "common.labels.standard" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{- $default := dict "app.kubernetes.io/name" (include "common.names.name" .context) "helm.sh/chart" (include "common.names.chart" .context) "app.kubernetes.io/instance" .context.Release.Name "app.kubernetes.io/managed-by" .context.Release.Service -}} +{{- with .context.Chart.AppVersion -}} +{{- $_ := set $default "app.kubernetes.io/version" . -}} +{{- end -}} +{{ template "common.tplvalues.merge" (dict "values" (list .customLabels $default) "context" .context) }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +helm.sh/chart: {{ include "common.names.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Chart.AppVersion }} +app.kubernetes.io/version: {{ . | quote }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Labels used on immutable fields such as deploy.spec.selector.matchLabels or svc.spec.selector +{{ include "common.labels.matchLabels" (dict "customLabels" .Values.podLabels "context" $) -}} + +We don't want to loop over custom labels appending them to the selector +since it's very likely that it will break deployments, services, etc. +However, it's important to overwrite the standard labels if the user +overwrote them on metadata.labels fields. +*/}} +{{- define "common.labels.matchLabels" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{ merge (pick (include "common.tplvalues.render" (dict "value" .customLabels "context" .context) | fromYaml) "app.kubernetes.io/name" "app.kubernetes.io/instance") (dict "app.kubernetes.io/name" (include "common.names.name" .context) "app.kubernetes.io/instance" .context.Release.Name ) | toYaml }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey/charts/common/templates/_names.tpl b/backing-services/gitea/charts/valkey/charts/common/templates/_names.tpl new file mode 100644 index 0000000..d5d0ae4 --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/templates/_names.tpl @@ -0,0 +1,72 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "common.names.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "common.names.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "common.names.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- $releaseName := regexReplaceAll "(-?[^a-z\\d\\-])+-?" (lower .Release.Name) "-" -}} +{{- if contains $name $releaseName -}} +{{- $releaseName | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" $releaseName $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified dependency name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +Usage: +{{ include "common.names.dependency.fullname" (dict "chartName" "dependency-chart-name" "chartValues" .Values.dependency-chart "context" $) }} +*/}} +{{- define "common.names.dependency.fullname" -}} +{{- if .chartValues.fullnameOverride -}} +{{- .chartValues.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .chartName .chartValues.nameOverride -}} +{{- if contains $name .context.Release.Name -}} +{{- .context.Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .context.Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts. +*/}} +{{- define "common.names.namespace" -}} +{{- default .Release.Namespace .Values.namespaceOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a fully qualified app name adding the installation's namespace. +*/}} +{{- define "common.names.fullname.namespace" -}} +{{- printf "%s-%s" (include "common.names.fullname" .) (include "common.names.namespace" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey/charts/common/templates/_resources.tpl b/backing-services/gitea/charts/valkey/charts/common/templates/_resources.tpl new file mode 100644 index 0000000..d8a43e1 --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/templates/_resources.tpl @@ -0,0 +1,50 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a resource request/limit object based on a given preset. +These presets are for basic testing and not meant to be used in production +{{ include "common.resources.preset" (dict "type" "nano") -}} +*/}} +{{- define "common.resources.preset" -}} +{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} +{{- $presets := dict + "nano" (dict + "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "2Gi") + ) + "micro" (dict + "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "2Gi") + ) + "small" (dict + "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "2Gi") + ) + "medium" (dict + "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "2Gi") + ) + "large" (dict + "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "2Gi") + ) + "xlarge" (dict + "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "2Gi") + ) + "2xlarge" (dict + "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "2Gi") + ) + }} +{{- if hasKey $presets .type -}} +{{- index $presets .type | toYaml -}} +{{- else -}} +{{- printf "ERROR: Preset key '%s' invalid. Allowed values are %s" .type (join "," (keys $presets)) | fail -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey/charts/common/templates/_secrets.tpl b/backing-services/gitea/charts/valkey/charts/common/templates/_secrets.tpl new file mode 100644 index 0000000..7868c00 --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/templates/_secrets.tpl @@ -0,0 +1,192 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Generate secret name. + +Usage: +{{ include "common.secrets.name" (dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $) }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - defaultNameSuffix - String - Optional. It is used only if we have several secrets in the same deployment. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.secrets.name" -}} +{{- $name := (include "common.names.fullname" .context) -}} + +{{- if .defaultNameSuffix -}} +{{- $name = printf "%s-%s" $name .defaultNameSuffix | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- with .existingSecret -}} +{{- if not (typeIs "string" .) -}} +{{- with .name -}} +{{- $name = . -}} +{{- end -}} +{{- else -}} +{{- $name = . -}} +{{- end -}} +{{- end -}} + +{{- printf "%s" $name -}} +{{- end -}} + +{{/* +Generate secret key. + +Usage: +{{ include "common.secrets.key" (dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName") }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - key - String - Required. Name of the key in the secret. +*/}} +{{- define "common.secrets.key" -}} +{{- $key := .key -}} + +{{- if .existingSecret -}} + {{- if not (typeIs "string" .existingSecret) -}} + {{- if .existingSecret.keyMapping -}} + {{- $key = index .existingSecret.keyMapping $.key -}} + {{- end -}} + {{- end }} +{{- end -}} + +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Generate secret password or retrieve one if already created. + +Usage: +{{ include "common.secrets.passwords.manage" (dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "honorProvidedValues" false "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - providedValues - List - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - length - int - Optional - Length of the generated random password. + - strong - Boolean - Optional - Whether to add symbols to the generated random password. + - chartName - String - Optional - Name of the chart used when said chart is deployed as a subchart. + - context - Context - Required - Parent context. + - failOnNew - Boolean - Optional - Default to true. If set to false, skip errors adding new keys to existing secrets. + - skipB64enc - Boolean - Optional - Default to false. If set to true, no the secret will not be base64 encrypted. + - skipQuote - Boolean - Optional - Default to false. If set to true, no quotes will be added around the secret. + - honorProvidedValues - Boolean - Optional - Default to false. If set to true, the values in providedValues have higher priority than an existing secret +The order in which this function returns a secret password: + 1. Password provided via the values.yaml if honorProvidedValues = true + (If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned) + 2. Already existing 'Secret' resource + (If a 'Secret' resource is found under the name provided to the 'secret' parameter to this function and that 'Secret' resource contains a key with the name passed as the 'key' parameter to this function then the value of this existing secret password will be returned) + 3. Password provided via the values.yaml if honorProvidedValues = false + (If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned) + 4. Randomly generated secret password + (A new random secret password with the length specified in the 'length' parameter will be generated and returned) + +*/}} +{{- define "common.secrets.passwords.manage" -}} + +{{- $password := "" }} +{{- $subchart := "" }} +{{- $chartName := default "" .chartName }} +{{- $passwordLength := default 10 .length }} +{{- $providedPasswordKey := include "common.utils.getKeyFromList" (dict "keys" .providedValues "context" $.context) }} +{{- $providedPasswordValue := include "common.utils.getValueFromKey" (dict "key" $providedPasswordKey "context" $.context) }} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data }} +{{- if $secretData }} + {{- if hasKey $secretData .key }} + {{- $password = index $secretData .key | b64dec }} + {{- else if not (eq .failOnNew false) }} + {{- printf "\nPASSWORDS ERROR: The secret \"%s\" does not contain the key \"%s\"\n" .secret .key | fail -}} + {{- end -}} +{{- end }} + +{{- if and $providedPasswordValue .honorProvidedValues }} + {{- $password = tpl ($providedPasswordValue | toString) .context }} +{{- end }} + +{{- if not $password }} + {{- if $providedPasswordValue }} + {{- $password = tpl ($providedPasswordValue | toString) .context }} + {{- else }} + {{- if .context.Values.enabled }} + {{- $subchart = $chartName }} + {{- end -}} + + {{- if not (eq .failOnNew false) }} + {{- $requiredPassword := dict "valueKey" $providedPasswordKey "secret" .secret "field" .key "subchart" $subchart "context" $.context -}} + {{- $requiredPasswordError := include "common.validations.values.single.empty" $requiredPassword -}} + {{- $passwordValidationErrors := list $requiredPasswordError -}} + {{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" $passwordValidationErrors "context" $.context) -}} + {{- end }} + + {{- if .strong }} + {{- $subStr := list (lower (randAlpha 1)) (randNumeric 1) (upper (randAlpha 1)) | join "_" }} + {{- $password = randAscii $passwordLength }} + {{- $password = regexReplaceAllLiteral "\\W" $password "@" | substr 5 $passwordLength }} + {{- $password = printf "%s%s" $subStr $password | toString | shuffle }} + {{- else }} + {{- $password = randAlphaNum $passwordLength }} + {{- end }} + {{- end -}} +{{- end -}} +{{- if not .skipB64enc }} +{{- $password = $password | b64enc }} +{{- end -}} +{{- if .skipQuote -}} +{{- printf "%s" $password -}} +{{- else -}} +{{- printf "%s" $password | quote -}} +{{- end -}} +{{- end -}} + +{{/* +Reuses the value from an existing secret, otherwise sets its value to a default value. + +Usage: +{{ include "common.secrets.lookup" (dict "secret" "secret-name" "key" "keyName" "defaultValue" .Values.myValue "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - defaultValue - String - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - context - Context - Required - Parent context. + +*/}} +{{- define "common.secrets.lookup" -}} +{{- $value := "" -}} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data -}} +{{- if and $secretData (hasKey $secretData .key) -}} + {{- $value = index $secretData .key -}} +{{- else if .defaultValue -}} + {{- $value = .defaultValue | toString | b64enc -}} +{{- end -}} +{{- if $value -}} +{{- printf "%s" $value -}} +{{- end -}} +{{- end -}} + +{{/* +Returns whether a previous generated secret already exists + +Usage: +{{ include "common.secrets.exists" (dict "secret" "secret-name" "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - context - Context - Required - Parent context. +*/}} +{{- define "common.secrets.exists" -}} +{{- $secret := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret) }} +{{- if $secret }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey/charts/common/templates/_storage.tpl b/backing-services/gitea/charts/valkey/charts/common/templates/_storage.tpl new file mode 100644 index 0000000..aa75856 --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/templates/_storage.tpl @@ -0,0 +1,21 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the proper Storage Class +{{ include "common.storage.class" ( dict "persistence" .Values.path.to.the.persistence "global" $) }} +*/}} +{{- define "common.storage.class" -}} +{{- $storageClass := (.global).storageClass | default .persistence.storageClass | default (.global).defaultStorageClass | default "" -}} +{{- if $storageClass -}} + {{- if (eq "-" $storageClass) -}} + {{- printf "storageClassName: \"\"" -}} + {{- else -}} + {{- printf "storageClassName: %s" $storageClass -}} + {{- end -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey/charts/common/templates/_tplvalues.tpl b/backing-services/gitea/charts/valkey/charts/common/templates/_tplvalues.tpl new file mode 100644 index 0000000..a04f4c1 --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/templates/_tplvalues.tpl @@ -0,0 +1,52 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Renders a value that contains template perhaps with scope if the scope is present. +Usage: +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ ) }} +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ "scope" $app ) }} +*/}} +{{- define "common.tplvalues.render" -}} +{{- $value := typeIs "string" .value | ternary .value (.value | toYaml) }} +{{- if contains "{{" (toJson .value) }} + {{- if .scope }} + {{- tpl (cat "{{- with $.RelativeScope -}}" $value "{{- end }}") (merge (dict "RelativeScope" .scope) .context) }} + {{- else }} + {{- tpl $value .context }} + {{- end }} +{{- else }} + {{- $value }} +{{- end }} +{{- end -}} + +{{/* +Merge a list of values that contains template after rendering them. +Merge precedence is consistent with http://masterminds.github.io/sprig/dicts.html#merge-mustmerge +Usage: +{{ include "common.tplvalues.merge" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }} +*/}} +{{- define "common.tplvalues.merge" -}} +{{- $dst := dict -}} +{{- range .values -}} +{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | merge $dst -}} +{{- end -}} +{{ $dst | toYaml }} +{{- end -}} + +{{/* +Merge a list of values that contains template after rendering them. +Merge precedence is consistent with https://masterminds.github.io/sprig/dicts.html#mergeoverwrite-mustmergeoverwrite +Usage: +{{ include "common.tplvalues.merge-overwrite" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }} +*/}} +{{- define "common.tplvalues.merge-overwrite" -}} +{{- $dst := dict -}} +{{- range .values -}} +{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | mergeOverwrite $dst -}} +{{- end -}} +{{ $dst | toYaml }} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey/charts/common/templates/_utils.tpl b/backing-services/gitea/charts/valkey/charts/common/templates/_utils.tpl new file mode 100644 index 0000000..d53c74a --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/templates/_utils.tpl @@ -0,0 +1,77 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Print instructions to get a secret value. +Usage: +{{ include "common.utils.secret.getvalue" (dict "secret" "secret-name" "field" "secret-value-field" "context" $) }} +*/}} +{{- define "common.utils.secret.getvalue" -}} +{{- $varname := include "common.utils.fieldToEnvVar" . -}} +export {{ $varname }}=$(kubectl get secret --namespace {{ include "common.names.namespace" .context | quote }} {{ .secret }} -o jsonpath="{.data.{{ .field }}}" | base64 -d) +{{- end -}} + +{{/* +Build env var name given a field +Usage: +{{ include "common.utils.fieldToEnvVar" dict "field" "my-password" }} +*/}} +{{- define "common.utils.fieldToEnvVar" -}} + {{- $fieldNameSplit := splitList "-" .field -}} + {{- $upperCaseFieldNameSplit := list -}} + + {{- range $fieldNameSplit -}} + {{- $upperCaseFieldNameSplit = append $upperCaseFieldNameSplit ( upper . ) -}} + {{- end -}} + + {{ join "_" $upperCaseFieldNameSplit }} +{{- end -}} + +{{/* +Gets a value from .Values given +Usage: +{{ include "common.utils.getValueFromKey" (dict "key" "path.to.key" "context" $) }} +*/}} +{{- define "common.utils.getValueFromKey" -}} +{{- $splitKey := splitList "." .key -}} +{{- $value := "" -}} +{{- $latestObj := $.context.Values -}} +{{- range $splitKey -}} + {{- if not $latestObj -}} + {{- printf "please review the entire path of '%s' exists in values" $.key | fail -}} + {{- end -}} + {{- $value = ( index $latestObj . ) -}} + {{- $latestObj = $value -}} +{{- end -}} +{{- printf "%v" (default "" $value) -}} +{{- end -}} + +{{/* +Returns first .Values key with a defined value or first of the list if all non-defined +Usage: +{{ include "common.utils.getKeyFromList" (dict "keys" (list "path.to.key1" "path.to.key2") "context" $) }} +*/}} +{{- define "common.utils.getKeyFromList" -}} +{{- $key := first .keys -}} +{{- $reverseKeys := reverse .keys }} +{{- range $reverseKeys }} + {{- $value := include "common.utils.getValueFromKey" (dict "key" . "context" $.context ) }} + {{- if $value -}} + {{- $key = . }} + {{- end -}} +{{- end -}} +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Checksum a template at "path" containing a *single* resource (ConfigMap,Secret) for use in pod annotations, excluding the metadata (see #18376). +Usage: +{{ include "common.utils.checksumTemplate" (dict "path" "/configmap.yaml" "context" $) }} +*/}} +{{- define "common.utils.checksumTemplate" -}} +{{- $obj := include (print .context.Template.BasePath .path) .context | fromYaml -}} +{{ omit $obj "apiVersion" "kind" "metadata" | toYaml | sha256sum }} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey/charts/common/templates/_warnings.tpl b/backing-services/gitea/charts/valkey/charts/common/templates/_warnings.tpl new file mode 100644 index 0000000..62c44df --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/templates/_warnings.tpl @@ -0,0 +1,109 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Warning about using rolling tag. +Usage: +{{ include "common.warnings.rollingTag" .Values.path.to.the.imageRoot }} +*/}} +{{- define "common.warnings.rollingTag" -}} + +{{- if and (contains "bitnami/" .repository) (not (.tag | toString | regexFind "-r\\d+$|sha256:")) }} +WARNING: Rolling tag detected ({{ .repository }}:{{ .tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. ++info https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-understand-rolling-tags-containers-index.html +{{- end }} +{{- end -}} + +{{/* +Warning about replaced images from the original. +Usage: +{{ include "common.warnings.modifiedImages" (dict "images" (list .Values.path.to.the.imageRoot) "context" $) }} +*/}} +{{- define "common.warnings.modifiedImages" -}} +{{- $affectedImages := list -}} +{{- $printMessage := false -}} +{{- $originalImages := .context.Chart.Annotations.images -}} +{{- range .images -}} + {{- $fullImageName := printf (printf "%s/%s:%s" .registry .repository .tag) -}} + {{- if not (contains $fullImageName $originalImages) }} + {{- $affectedImages = append $affectedImages (printf "%s/%s:%s" .registry .repository .tag) -}} + {{- $printMessage = true -}} + {{- end -}} +{{- end -}} +{{- if $printMessage }} + +⚠ SECURITY WARNING: Original containers have been substituted. This Helm chart was designed, tested, and validated on multiple platforms using a specific set of Bitnami and Tanzu Application Catalog containers. Substituting other containers is likely to cause degraded security and performance, broken chart features, and missing environment variables. + +Substituted images detected: +{{- range $affectedImages }} + - {{ . }} +{{- end }} +{{- end -}} +{{- end -}} + +{{/* +Warning about not setting the resource object in all deployments. +Usage: +{{ include "common.warnings.resources" (dict "sections" (list "path1" "path2") context $) }} +Example: +{{- include "common.warnings.resources" (dict "sections" (list "csiProvider.provider" "server" "volumePermissions" "") "context" $) }} +The list in the example assumes that the following values exist: + - csiProvider.provider.resources + - server.resources + - volumePermissions.resources + - resources +*/}} +{{- define "common.warnings.resources" -}} +{{- $values := .context.Values -}} +{{- $printMessage := false -}} +{{ $affectedSections := list -}} +{{- range .sections -}} + {{- if eq . "" -}} + {{/* Case where the resources section is at the root (one main deployment in the chart) */}} + {{- if not (index $values "resources") -}} + {{- $affectedSections = append $affectedSections "resources" -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Case where the are multiple resources sections (more than one main deployment in the chart) */}} + {{- $keys := split "." . -}} + {{/* We iterate through the different levels until arriving to the resource section. Example: a.b.c.resources */}} + {{- $section := $values -}} + {{- range $keys -}} + {{- $section = index $section . -}} + {{- end -}} + {{- if not (index $section "resources") -}} + {{/* If the section has enabled=false or replicaCount=0, do not include it */}} + {{- if and (hasKey $section "enabled") -}} + {{- if index $section "enabled" -}} + {{/* enabled=true */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else if and (hasKey $section "replicaCount") -}} + {{/* We need a casting to int because number 0 is not treated as an int by default */}} + {{- if (gt (index $section "replicaCount" | int) 0) -}} + {{/* replicaCount > 0 */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Default case, add it to the affected sections */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- if $printMessage }} + +WARNING: There are "resources" sections in the chart not set. Using "resourcesPreset" is not recommended for production. For production installations, please set the following values according to your workload needs: +{{- range $affectedSections }} + - {{ . }} +{{- end }} ++info https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +{{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey/charts/common/templates/validations/_cassandra.tpl b/backing-services/gitea/charts/valkey/charts/common/templates/validations/_cassandra.tpl new file mode 100644 index 0000000..f8fd213 --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/templates/validations/_cassandra.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.cassandra.values.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.cassandra.dbUser.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.dbUser.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled cassandra. + +Usage: +{{ include "common.cassandra.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.cassandra.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.cassandra.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key dbUser + +Usage: +{{ include "common.cassandra.values.key.dbUser" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.key.dbUser" -}} + {{- if .subchart -}} + cassandra.dbUser + {{- else -}} + dbUser + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey/charts/common/templates/validations/_mariadb.tpl b/backing-services/gitea/charts/valkey/charts/common/templates/validations/_mariadb.tpl new file mode 100644 index 0000000..6ea8c0f --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/templates/validations/_mariadb.tpl @@ -0,0 +1,108 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MariaDB required passwords are not empty. + +Usage: +{{ include "common.validations.values.mariadb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MariaDB values are stored, e.g: "mysql-passwords-secret" + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mariadb.passwords" -}} + {{- $existingSecret := include "common.mariadb.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mariadb.values.enabled" . -}} + {{- $architecture := include "common.mariadb.values.architecture" . -}} + {{- $authPrefix := include "common.mariadb.values.key.auth" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mariadb-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- if not (empty $valueUsername) -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mariadb-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replication") -}} + {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mariadb-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mariadb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mariadb. + +Usage: +{{ include "common.mariadb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mariadb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mariadb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mariadb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mariadb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.key.auth" -}} + {{- if .subchart -}} + mariadb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey/charts/common/templates/validations/_mongodb.tpl b/backing-services/gitea/charts/valkey/charts/common/templates/validations/_mongodb.tpl new file mode 100644 index 0000000..e678a6d --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/templates/validations/_mongodb.tpl @@ -0,0 +1,67 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mongodb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDb is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mongodb. + +Usage: +{{ include "common.mongodb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mongodb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mongodb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mongodb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.key.auth" -}} + {{- if .subchart -}} + mongodb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mongodb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey/charts/common/templates/validations/_mysql.tpl b/backing-services/gitea/charts/valkey/charts/common/templates/validations/_mysql.tpl new file mode 100644 index 0000000..fbb65c3 --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/templates/validations/_mysql.tpl @@ -0,0 +1,67 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mysql.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mysql. + +Usage: +{{ include "common.mysql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mysql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mysql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mysql.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mysql.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.key.auth" -}} + {{- if .subchart -}} + mysql.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey/charts/common/templates/validations/_postgresql.tpl b/backing-services/gitea/charts/valkey/charts/common/templates/validations/_postgresql.tpl new file mode 100644 index 0000000..51d4716 --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/templates/validations/_postgresql.tpl @@ -0,0 +1,105 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to decide whether evaluate global values. + +Usage: +{{ include "common.postgresql.values.use.global" (dict "key" "key-of-global" "context" $) }} +Params: + - key - String - Required. Field to be evaluated within global, e.g: "existingSecret" +*/}} +{{- define "common.postgresql.values.use.global" -}} + {{- if .context.Values.global -}} + {{- if .context.Values.global.postgresql -}} + {{- index .context.Values.global.postgresql .key | quote -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.postgresql.values.existingSecret" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.existingSecret" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "existingSecret" "context" .context) -}} + + {{- if .subchart -}} + {{- default (.context.Values.postgresql.existingSecret | quote) $globalValue -}} + {{- else -}} + {{- default (.context.Values.existingSecret | quote) $globalValue -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled postgresql. + +Usage: +{{ include "common.postgresql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key postgressPassword. + +Usage: +{{ include "common.postgresql.values.key.postgressPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.postgressPassword" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "postgresqlUsername" "context" .context) -}} + + {{- if not $globalValue -}} + {{- if .subchart -}} + postgresql.postgresqlPassword + {{- else -}} + postgresqlPassword + {{- end -}} + {{- else -}} + global.postgresql.postgresqlPassword + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled.replication. + +Usage: +{{ include "common.postgresql.values.enabled.replication" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.enabled.replication" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.replication.enabled -}} + {{- else -}} + {{- printf "%v" .context.Values.replication.enabled -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key replication.password. + +Usage: +{{ include "common.postgresql.values.key.replicationPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.replicationPassword" -}} + {{- if .subchart -}} + postgresql.replication.password + {{- else -}} + replication.password + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey/charts/common/templates/validations/_redis.tpl b/backing-services/gitea/charts/valkey/charts/common/templates/validations/_redis.tpl new file mode 100644 index 0000000..9fedfef --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/templates/validations/_redis.tpl @@ -0,0 +1,48 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for enabled redis. + +Usage: +{{ include "common.redis.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.redis.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.redis.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right prefix path for the values + +Usage: +{{ include "common.redis.values.key.prefix" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false +*/}} +{{- define "common.redis.values.keys.prefix" -}} + {{- if .subchart -}}redis.{{- else -}}{{- end -}} +{{- end -}} + +{{/* +Checks whether the redis chart's includes the standarizations (version >= 14) + +Usage: +{{ include "common.redis.values.standarized.version" (dict "context" $) }} +*/}} +{{- define "common.redis.values.standarized.version" -}} + + {{- $standarizedAuth := printf "%s%s" (include "common.redis.values.keys.prefix" .) "auth" -}} + {{- $standarizedAuthValues := include "common.utils.getValueFromKey" (dict "key" $standarizedAuth "context" .context) }} + + {{- if $standarizedAuthValues -}} + {{- true -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey/charts/common/templates/validations/_validations.tpl b/backing-services/gitea/charts/valkey/charts/common/templates/validations/_validations.tpl new file mode 100644 index 0000000..7cdee61 --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/templates/validations/_validations.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate values must not be empty. + +Usage: +{{- $validateValueConf00 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-01") -}} +{{ include "common.validations.values.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" +*/}} +{{- define "common.validations.values.multiple.empty" -}} + {{- range .required -}} + {{- include "common.validations.values.single.empty" (dict "valueKey" .valueKey "secret" .secret "field" .field "context" $.context) -}} + {{- end -}} +{{- end -}} + +{{/* +Validate a value must not be empty. + +Usage: +{{ include "common.validations.value.empty" (dict "valueKey" "mariadb.password" "secret" "secretName" "field" "my-password" "subchart" "subchart" "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" + - subchart - String - Optional - Name of the subchart that the validated password is part of. +*/}} +{{- define "common.validations.values.single.empty" -}} + {{- $value := include "common.utils.getValueFromKey" (dict "key" .valueKey "context" .context) }} + {{- $subchart := ternary "" (printf "%s." .subchart) (empty .subchart) }} + + {{- if not $value -}} + {{- $varname := "my-value" -}} + {{- $getCurrentValue := "" -}} + {{- if and .secret .field -}} + {{- $varname = include "common.utils.fieldToEnvVar" . -}} + {{- $getCurrentValue = printf " To get the current value:\n\n %s\n" (include "common.utils.secret.getvalue" .) -}} + {{- end -}} + {{- printf "\n '%s' must not be empty, please add '--set %s%s=$%s' to the command.%s" .valueKey $subchart .valueKey $varname $getCurrentValue -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey/charts/common/values.yaml b/backing-services/gitea/charts/valkey/charts/common/values.yaml new file mode 100644 index 0000000..de2cac5 --- /dev/null +++ b/backing-services/gitea/charts/valkey/charts/common/values.yaml @@ -0,0 +1,8 @@ +# Copyright Broadcom, Inc. All Rights Reserved. +# SPDX-License-Identifier: APACHE-2.0 + +## bitnami/common +## It is required by CI/CD tools and processes. +## @skip exampleValue +## +exampleValue: common-chart diff --git a/backing-services/gitea/charts/valkey/templates/NOTES.txt b/backing-services/gitea/charts/valkey/templates/NOTES.txt new file mode 100644 index 0000000..5193c6c --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/NOTES.txt @@ -0,0 +1,216 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +⚠ WARNING: Since August 28th, 2025, only a limited subset of images/charts are available for free. + Subscribe to Bitnami Secure Images to receive continued support and security updates. + More info at https://bitnami.com and https://github.com/bitnami/containers/issues/83267 + +** Please be patient while the chart is being deployed ** + +{{- if .Values.diagnosticMode.enabled }} +The chart has been deployed in diagnostic mode. All probes have been disabled and the command has been overwritten with: + + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 4 }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 4 }} + +Get the list of pods by executing: + + kubectl get pods --namespace {{ include "common.names.namespace" . }} -l app.kubernetes.io/instance={{ .Release.Name }} + +Access the pod you want to debug by executing + + kubectl exec --namespace {{ include "common.names.namespace" . }} -ti -- bash + +In order to replicate the container startup scripts execute this command: + +For Valkey: + + /opt/bitnami/scripts/valkey/entrypoint.sh /opt/bitnami/scripts/valkey/run.sh + +{{- if .Values.sentinel.enabled }} + +For Valkey Sentinel: + + /opt/bitnami/scripts/valkey-sentinel/entrypoint.sh /opt/bitnami/scripts/valkey-sentinel/run.sh + +{{- end }} +{{- else }} + +{{- if contains .Values.primary.service.type "LoadBalancer" }} +{{- if not .Values.auth.enabled }} +{{ if and (not .Values.networkPolicy.enabled) (.Values.networkPolicy.allowExternal) }} + +------------------------------------------------------------------------------- + WARNING + + By specifying "primary.service.type=LoadBalancer" and "auth.enabled=false" you have + most likely exposed the Valkey service externally without any authentication + mechanism. + + For security reasons, we strongly suggest that you switch to "ClusterIP" or + "NodePort". As alternative, you can also switch to "auth.enabled=true" + providing a valid password on "password" parameter. + +------------------------------------------------------------------------------- +{{- end }} +{{- end }} +{{- end }} + +{{- if and .Values.auth.usePasswordFiles (not .Values.auth.usePasswordFileFromSecret) (or (empty .Values.primary.initContainers) (empty .Values.replica.initContainers)) }} + +------------------------------------------------------------------------------- + WARNING + + By specifying ".Values.auth.usePasswordFiles=true" and ".Values.auth.usePasswordFileFromSecret=false" + Valkey is expecting that the password is mounted as a file in each pod + (by default in /opt/bitnami/valkey/secrets/valkey-password) + + Ensure that you specify the respective initContainers in + both .Values.primary.initContainers and .Values.replica.initContainers + in order to populate the contents of this file. + +------------------------------------------------------------------------------- +{{- end }} + +{{- if eq .Values.architecture "replication" }} +{{- if .Values.sentinel.enabled }} + +Valkey can be accessed via port {{ .Values.sentinel.service.ports.valkey }} on the following DNS name from within your cluster: + + {{ template "common.names.fullname" . }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }} for read only operations + +For read/write operations, first access the Valkey Sentinel cluster, which is available in port {{ .Values.sentinel.service.ports.sentinel }} using the same domain name above. + +{{- else }} + +Valkey can be accessed on the following DNS names from within your cluster: + + {{ printf "%s-primary.%s.svc.%s" (include "common.names.fullname" .) (include "common.names.namespace" . ) .Values.clusterDomain }} for read/write operations (port {{ .Values.primary.service.ports.valkey }}) + {{ printf "%s-replicas.%s.svc.%s" (include "common.names.fullname" .) (include "common.names.namespace" . ) .Values.clusterDomain }} for read-only operations (port {{ .Values.replica.service.ports.valkey }}) + +{{- end }} +{{- else }} + +Valkey can be accessed via port {{ .Values.primary.service.ports.valkey }} on the following DNS name from within your cluster: + + {{ template "common.names.fullname" . }}-primary.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }} + +{{- end }} + +{{ if .Values.auth.enabled }} + +To get your password run: + + export VALKEY_PASSWORD=$(kubectl get secret --namespace {{ include "common.names.namespace" . }} {{ include "valkey.secretName" . }} -o jsonpath="{.data.{{ include "valkey.secretPasswordKey" . }}}" | base64 -d) + +{{- end }} + +To connect to your Valkey server: + +1. Run a Valkey pod that you can use as a client: + + kubectl run --namespace {{ include "common.names.namespace" . }} valkey-client --restart='Never' {{ if .Values.auth.enabled }} --env VALKEY_PASSWORD=$VALKEY_PASSWORD {{ end }} --image {{ template "valkey.image" . }} --command -- sleep infinity + +{{- if .Values.tls.enabled }} + + Copy your TLS certificates to the pod: + + kubectl cp --namespace {{ include "common.names.namespace" . }} /path/to/client.cert valkey-client:/tmp/client.cert + kubectl cp --namespace {{ include "common.names.namespace" . }} /path/to/client.key valkey-client:/tmp/client.key + kubectl cp --namespace {{ include "common.names.namespace" . }} /path/to/CA.cert valkey-client:/tmp/CA.cert + +{{- end }} + + Use the following command to attach to the pod: + + kubectl exec --tty -i valkey-client \ + {{- if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }}--labels="{{ template "common.names.fullname" . }}-client=true" \{{- end }} + --namespace {{ include "common.names.namespace" . }} -- bash + +2. Connect using the Valkey CLI: + +{{- if eq .Values.architecture "replication" }} + {{- if .Values.sentinel.enabled }} + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$VALKEY_PASSWORD" {{ end }}valkey-cli -h {{ template "common.names.fullname" . }} -p {{ .Values.sentinel.service.ports.valkey }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} # Read only operations + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$VALKEY_PASSWORD" {{ end }}valkey-cli -h {{ template "common.names.fullname" . }} -p {{ .Values.sentinel.service.ports.sentinel }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} # Sentinel access + {{- else }} + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$VALKEY_PASSWORD" {{ end }}valkey-cli -h {{ printf "%s-primary" (include "common.names.fullname" .) }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$VALKEY_PASSWORD" {{ end }}valkey-cli -h {{ printf "%s-replicas" (include "common.names.fullname" .) }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + {{- end }} +{{- else }} + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$VALKEY_PASSWORD" {{ end }}valkey-cli -h {{ template "common.names.fullname" . }}-primary{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} +{{- end }} + +{{- if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }} + +Note: Since NetworkPolicy is enabled, only pods with label {{ template "common.names.fullname" . }}-client=true" will be able to connect to valkey. + +{{- else }} + +To connect to your database from outside the cluster execute the following commands: + +{{- if and (eq .Values.architecture "replication") .Values.sentinel.enabled }} +{{- if contains "NodePort" .Values.sentinel.service.type }} + + export NODE_IP=$(kubectl get nodes --namespace {{ include "common.names.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get --namespace {{ include "common.names.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "common.names.fullname" . }}) + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$VALKEY_PASSWORD" {{ end }}valkey-cli -h $NODE_IP -p $NODE_PORT {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- else if contains "LoadBalancer" .Values.sentinel.service.type }} + + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + Watch the status with: 'kubectl get svc --namespace {{ include "common.names.namespace" . }} -w {{ template "common.names.fullname" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ include "common.names.namespace" . }} {{ template "common.names.fullname" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$VALKEY_PASSWORD" {{ end }}valkey-cli -h $SERVICE_IP -p {{ .Values.sentinel.service.ports.valkey }} {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- else if contains "ClusterIP" .Values.sentinel.service.type }} + + kubectl port-forward --namespace {{ include "common.names.namespace" . }} svc/{{ template "common.names.fullname" . }} {{ .Values.sentinel.service.ports.valkey }}:{{ .Values.sentinel.service.ports.valkey }} & + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$VALKEY_PASSWORD" {{ end }}valkey-cli -h 127.0.0.1 -p {{ .Values.sentinel.service.ports.valkey }} {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- end }} +{{- else }} +{{- if contains "NodePort" .Values.primary.service.type }} + + export NODE_IP=$(kubectl get nodes --namespace {{ include "common.names.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get --namespace {{ include "common.names.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ printf "%s-primary" (include "common.names.fullname" .) }}) + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$VALKEY_PASSWORD" {{ end }}valkey-cli -h $NODE_IP -p $NODE_PORT {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- else if contains "LoadBalancer" .Values.primary.service.type }} + + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + Watch the status with: 'kubectl get svc --namespace {{ include "common.names.namespace" . }} -w {{ template "common.names.fullname" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ include "common.names.namespace" . }} {{ printf "%s-primary" (include "common.names.fullname" .) }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$VALKEY_PASSWORD" {{ end }}valkey-cli -h $SERVICE_IP -p {{ .Values.primary.service.ports.valkey }} {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- else if contains "ClusterIP" .Values.primary.service.type }} + + kubectl port-forward --namespace {{ include "common.names.namespace" . }} svc/{{ printf "%s-primary" (include "common.names.fullname" .) }} {{ .Values.primary.service.ports.valkey }}:{{ .Values.primary.service.ports.valkey }} & + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$VALKEY_PASSWORD" {{ end }}valkey-cli -h 127.0.0.1 -p {{ .Values.primary.service.ports.valkey }} {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- end }} +{{- end }} + +{{- end }} +{{- end }} +{{- include "valkey.checkRollingTags" . }} +{{- include "valkey.validateValues" . }} + +{{- if and (eq .Values.architecture "replication") .Values.sentinel.enabled (eq .Values.sentinel.service.type "NodePort") (not .Release.IsUpgrade ) }} +{{- if $.Values.sentinel.service.nodePorts.sentinel }} +No need to upgrade, ports and nodeports have been set from values +{{- else }} +#!#!#!#!#!#!#!# IMPORTANT #!#!#!#!#!#!#!# +YOU NEED TO PERFORM AN UPGRADE FOR THE SERVICES AND WORKLOAD TO BE CREATED +{{- end }} +{{- end }} +{{- $resourceSections := list "metrics" "replica" "sentinel" "volumePermissions" }} +{{- if not (and (eq .Values.architecture "replication") .Values.sentinel.enabled) }} + {{- $resourceSections = append $resourceSections "primary" -}} +{{- end }} +{{- include "common.warnings.resources" (dict "sections" $resourceSections "context" $) }} +{{- include "common.warnings.modifiedImages" (dict "images" (list .Values.image .Values.sentinel.image .Values.metrics.image .Values.volumePermissions.image .Values.kubectl.image) "context" $) }} +{{- include "common.errors.insecureImages" (dict "images" (list .Values.image .Values.sentinel.image .Values.metrics.image .Values.volumePermissions.image .Values.kubectl.image) "context" $) }} diff --git a/backing-services/gitea/charts/valkey/templates/_helpers.tpl b/backing-services/gitea/charts/valkey/templates/_helpers.tpl new file mode 100644 index 0000000..7822fad --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/_helpers.tpl @@ -0,0 +1,277 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the proper Valkey image name +*/}} +{{- define "valkey.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper Valkey Sentinel image name +*/}} +{{- define "valkey.sentinel.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.sentinel.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper image name (for the metrics image) +*/}} +{{- define "valkey.metrics.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.metrics.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper image name (for the init container volume-permissions image) +*/}} +{{- define "valkey.volumePermissions.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.volumePermissions.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return kubectl image +*/}} +{{- define "valkey.kubectl.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.kubectl.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "valkey.imagePullSecrets" -}} +{{- include "common.images.renderPullSecrets" (dict "images" (list .Values.image .Values.sentinel.image .Values.metrics.image .Values.volumePermissions.image) "context" $) -}} +{{- end -}} + +{{/* +Return true if a TLS secret object should be created +*/}} +{{- define "valkey.createTlsSecret" -}} +{{- if and .Values.tls.enabled .Values.tls.autoGenerated (not .Values.tls.existingSecret) }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the secret containing Valkey TLS certificates +*/}} +{{- define "valkey.tlsSecretName" -}} +{{- if .Values.tls.existingSecret -}} + {{- printf "%s" (tpl .Values.tls.existingSecret $) -}} +{{- else -}} + {{- printf "%s-crt" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the cert file. +*/}} +{{- define "valkey.tlsCert" -}} +{{- if (include "valkey.createTlsSecret" . ) -}} + {{- printf "/opt/bitnami/valkey/certs/%s" "tls.crt" -}} +{{- else -}} + {{- required "Certificate filename is required when TLS in enabled" .Values.tls.certFilename | printf "/opt/bitnami/valkey/certs/%s" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the cert key file. +*/}} +{{- define "valkey.tlsCertKey" -}} +{{- if (include "valkey.createTlsSecret" . ) -}} + {{- printf "/opt/bitnami/valkey/certs/%s" "tls.key" -}} +{{- else -}} + {{- required "Certificate Key filename is required when TLS in enabled" .Values.tls.certKeyFilename | printf "/opt/bitnami/valkey/certs/%s" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the CA cert file. +*/}} +{{- define "valkey.tlsCACert" -}} +{{- if (include "valkey.createTlsSecret" . ) -}} + {{- printf "/opt/bitnami/valkey/certs/%s" "ca.crt" -}} +{{- else -}} + {{- required "Certificate CA filename is required when TLS in enabled" .Values.tls.certCAFilename | printf "/opt/bitnami/valkey/certs/%s" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the DH params file. +*/}} +{{- define "valkey.tlsDHParams" -}} +{{- if .Values.tls.dhParamsFilename -}} +{{- printf "/opt/bitnami/valkey/certs/%s" .Values.tls.dhParamsFilename -}} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the shared service account to use +*/}} +{{- define "valkey.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "common.names.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the primary service account to use +*/}} +{{- define "valkey.primaryServiceAccountName" -}} +{{- if .Values.primary.serviceAccount.create -}} + {{ default (printf "%s-primary" (include "common.names.fullname" .)) .Values.primary.serviceAccount.name }} +{{- else -}} + {{- if .Values.serviceAccount.create -}} + {{ template "valkey.serviceAccountName" . }} + {{- else -}} + {{ default "default" .Values.primary.serviceAccount.name }} + {{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the replicas service account to use +*/}} +{{- define "valkey.replicaServiceAccountName" -}} +{{- if .Values.replica.serviceAccount.create -}} + {{ default (printf "%s-replica" (include "common.names.fullname" .)) .Values.replica.serviceAccount.name }} +{{- else -}} + {{- if .Values.serviceAccount.create -}} + {{ template "valkey.serviceAccountName" . }} + {{- else -}} + {{ default "default" .Values.replica.serviceAccount.name }} + {{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Return the configuration configmap name +*/}} +{{- define "valkey.configmapName" -}} +{{- if .Values.existingConfigmap -}} + {{- print (tpl .Values.existingConfigmap $) -}} +{{- else -}} + {{- printf "%s-configuration" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a configmap object should be created +*/}} +{{- define "valkey.createConfigmap" -}} +{{- if empty .Values.existingConfigmap }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Get the password secret. +*/}} +{{- define "valkey.secretName" -}} +{{- if .Values.auth.existingSecret -}} +{{- print (tpl .Values.auth.existingSecret $) -}} +{{- else -}} +{{- print (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Get the password key to be retrieved from Valkey secret. +*/}} +{{- define "valkey.secretPasswordKey" -}} +{{- if and .Values.auth.existingSecret .Values.auth.existingSecretPasswordKey -}} +{{- print (tpl .Values.auth.existingSecretPasswordKey $) -}} +{{- else -}} +{{- print "valkey-password" -}} +{{- end -}} +{{- end -}} + +{{/* Check if there are rolling tags in the images */}} +{{- define "valkey.checkRollingTags" -}} +{{- include "common.warnings.rollingTag" .Values.image }} +{{- include "common.warnings.rollingTag" .Values.sentinel.image }} +{{- include "common.warnings.rollingTag" .Values.metrics.image }} +{{- include "common.warnings.rollingTag" .Values.volumePermissions.image }} +{{- end -}} + +{{/* +Compile all warnings into a single message, and call fail. +*/}} +{{- define "valkey.validateValues" -}} +{{- $messages := list -}} +{{- $messages := append $messages (include "valkey.validateValues.architecture" .) -}} +{{- $messages := append $messages (include "valkey.validateValues.podSecurityPolicy.create" .) -}} +{{- $messages := append $messages (include "valkey.validateValues.tls" .) -}} +{{- $messages := append $messages (include "valkey.validateValues.createPrimary" .) -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}} +{{- end -}} +{{- end -}} + +{{/* Validate values of Valkey - must provide a valid architecture */}} +{{- define "valkey.validateValues.architecture" -}} +{{- if and (ne .Values.architecture "standalone") (ne .Values.architecture "replication") -}} +valkey: architecture + Invalid architecture selected. Valid values are "standalone" and + "replication". Please set a valid architecture (--set architecture="xxxx") +{{- end -}} +{{- if and .Values.sentinel.enabled (not (eq .Values.architecture "replication")) }} +valkey: architecture + Using valkey sentinel on standalone mode is not supported. + To deploy valkey sentinel, please select the "replication" mode + (--set "architecture=replication,sentinel.enabled=true") +{{- end -}} +{{- end -}} + +{{/* Validate values of Valkey - PodSecurityPolicy create */}} +{{- define "valkey.validateValues.podSecurityPolicy.create" -}} +{{- if and .Values.podSecurityPolicy.create (not .Values.podSecurityPolicy.enabled) }} +valkey: podSecurityPolicy.create + In order to create PodSecurityPolicy, you also need to enable + podSecurityPolicy.enabled field +{{- end -}} +{{- end -}} + +{{/* Validate values of Valkey - TLS enabled */}} +{{- define "valkey.validateValues.tls" -}} +{{- if and .Values.tls.enabled (not .Values.tls.autoGenerated) (not .Values.tls.existingSecret) }} +valkey: tls.enabled + In order to enable TLS, you also need to provide + an existing secret containing the TLS certificates or + enable auto-generated certificates. +{{- end -}} +{{- end -}} + +{{/* Validate values of Valkey - primary service enabled */}} +{{- define "valkey.validateValues.createPrimary" -}} +{{- if and .Values.sentinel.service.createPrimary (or (not .Values.rbac.create) (not .Values.replica.automountServiceAccountToken) (not .Values.serviceAccount.create)) }} +valkey: sentinel.service.createPrimary + In order to redirect requests only to the primary pod via the service, you also need to + create rbac and serviceAccount. In addition, you need to enable + replica.automountServiceAccountToken. +{{- end -}} +{{- end -}} + +{{/* Define the suffix utilized for external-dns */}} +{{- define "valkey.externalDNS.suffix" -}} +{{ printf "%s.%s" (include "common.names.fullname" .) .Values.useExternalDNS.suffix }} +{{- end -}} + +{{/* Compile all annotations utilized for external-dns */}} +{{- define "valkey.externalDNS.annotations" -}} +{{- if and .Values.useExternalDNS.enabled .Values.useExternalDNS.annotationKey }} +{{ .Values.useExternalDNS.annotationKey }}hostname: {{ include "valkey.externalDNS.suffix" . }} +{{- range $key, $val := .Values.useExternalDNS.additionalAnnotations }} +{{ $.Values.useExternalDNS.annotationKey }}{{ $key }}: {{ $val | quote }} +{{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/configmap.yaml b/backing-services/gitea/charts/valkey/templates/configmap.yaml new file mode 100644 index 0000000..ec37c7e --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/configmap.yaml @@ -0,0 +1,65 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "valkey.createConfigmap" .) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-configuration" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: valkey + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + valkey.conf: |- + # User-supplied common configuration: + {{- if .Values.commonConfiguration }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonConfiguration "context" $ ) | nindent 4 }} + {{- end }} + # End of common configuration + primary.conf: |- + dir {{ .Values.primary.persistence.path }} + # User-supplied primary configuration: + {{- if .Values.primary.configuration }} + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.configuration "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.primary.disableCommands }} + {{- range .Values.primary.disableCommands }} + rename-command {{ . }} "" + {{- end }} + {{- end }} + # End of primary configuration + replica.conf: |- + dir {{ .Values.replica.persistence.path }} + # User-supplied replica configuration: + {{- if .Values.replica.configuration }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.configuration "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.replica.disableCommands }} + {{- range .Values.replica.disableCommands }} + rename-command {{ . }} "" + {{- end }} + {{- end }} + # End of replica configuration + {{- if .Values.sentinel.enabled }} + sentinel.conf: |- + dir "/tmp" + port {{ .Values.sentinel.containerPorts.sentinel }} + sentinel monitor {{ .Values.sentinel.primarySet }} {{ template "common.names.fullname" . }}-node-0.{{ template "common.names.fullname" . }}-headless.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }} {{ .Values.sentinel.service.ports.valkey }} {{ .Values.sentinel.quorum }} + sentinel down-after-milliseconds {{ .Values.sentinel.primarySet }} {{ .Values.sentinel.downAfterMilliseconds }} + sentinel failover-timeout {{ .Values.sentinel.primarySet }} {{ .Values.sentinel.failoverTimeout }} + sentinel parallel-syncs {{ .Values.sentinel.primarySet }} {{ .Values.sentinel.parallelSyncs }} + {{- if .Values.sentinel.service.createPrimary}} + sentinel client-reconfig-script {{ .Values.sentinel.primarySet }} /opt/bitnami/scripts/start-scripts/push-primary-label.sh + {{- end }} + # User-supplied sentinel configuration: + {{- if .Values.sentinel.configuration }} + {{- include "common.tplvalues.render" ( dict "value" .Values.sentinel.configuration "context" $ ) | nindent 4 }} + {{- end }} + # End of sentinel configuration + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/extra-list.yaml b/backing-services/gitea/charts/valkey/templates/extra-list.yaml new file mode 100644 index 0000000..329f5c6 --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/extra-list.yaml @@ -0,0 +1,9 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/headless-svc.yaml b/backing-services/gitea/charts/valkey/templates/headless-svc.yaml new file mode 100644 index 0000000..16be9aa --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/headless-svc.yaml @@ -0,0 +1,36 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-headless" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: valkey + {{- if or .Values.sentinel.service.headless.annotations .Values.commonAnnotations (include "valkey.externalDNS.annotations" .) }} + annotations: + {{- if or .Values.sentinel.service.headless.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.sentinel.service.headless.annotations .Values.commonAnnotations ) "context" . ) }} + {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} + {{- include "valkey.externalDNS.annotations" . | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + {{- if .Values.sentinel.enabled }} + publishNotReadyAddresses: true + {{- end }} + ports: + - name: tcp-redis + port: {{ if .Values.sentinel.enabled }}{{ .Values.replica.containerPorts.valkey }}{{ else }} {{ .Values.primary.containerPorts.valkey }}{{ end }} + targetPort: redis + {{- if .Values.sentinel.enabled }} + - name: tcp-sentinel + port: {{ .Values.sentinel.containerPorts.sentinel }} + targetPort: valkey-sentinel + {{- end }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} diff --git a/backing-services/gitea/charts/valkey/templates/health-configmap.yaml b/backing-services/gitea/charts/valkey/templates/health-configmap.yaml new file mode 100644 index 0000000..4a8886c --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/health-configmap.yaml @@ -0,0 +1,194 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-health" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + ping_readiness_local.sh: |- + #!/bin/bash + + [[ -f $VALKEY_PASSWORD_FILE ]] && export VALKEY_PASSWORD="$(< "${VALKEY_PASSWORD_FILE}")" + [[ -n "$VALKEY_PASSWORD" ]] && export REDISCLI_AUTH="$VALKEY_PASSWORD" + response=$( + timeout -s 15 $1 \ + valkey-cli \ + -h localhost \ + {{- if .Values.tls.enabled }} + -p $VALKEY_TLS_PORT \ + --tls \ + --cacert {{ template "valkey.tlsCACert" . }} \ + {{- if .Values.tls.authClients }} + --cert {{ template "valkey.tlsCert" . }} \ + --key {{ template "valkey.tlsCertKey" . }} \ + {{- end }} + {{- else }} + -p $VALKEY_PORT \ + {{- end }} + ping + ) + if [ "$?" -eq "124" ]; then + echo "Timed out" + exit 1 + fi + if [ "$response" != "PONG" ]; then + echo "$response" + exit 1 + fi + ping_liveness_local.sh: |- + #!/bin/bash + + [[ -f $VALKEY_PASSWORD_FILE ]] && export VALKEY_PASSWORD="$(< "${VALKEY_PASSWORD_FILE}")" + [[ -n "$VALKEY_PASSWORD" ]] && export REDISCLI_AUTH="$VALKEY_PASSWORD" + response=$( + timeout -s 15 $1 \ + valkey-cli \ + -h localhost \ + {{- if .Values.tls.enabled }} + -p $VALKEY_TLS_PORT \ + --tls \ + --cacert {{ template "valkey.tlsCACert" . }} \ + {{- if .Values.tls.authClients }} + --cert {{ template "valkey.tlsCert" . }} \ + --key {{ template "valkey.tlsCertKey" . }} \ + {{- end }} + {{- else }} + -p $VALKEY_PORT \ + {{- end }} + ping + ) + if [ "$?" -eq "124" ]; then + echo "Timed out" + exit 1 + fi + responseFirstWord=$(echo $response | head -n1 | awk '{print $1;}') + if [ "$response" != "PONG" ] && [ "$responseFirstWord" != "LOADING" ] && [ "$responseFirstWord" != "MASTERDOWN" ]; then + echo "$response" + exit 1 + fi +{{- if .Values.sentinel.enabled }} + ping_sentinel.sh: |- + #!/bin/bash + + {{- if .Values.auth.sentinel }} + [[ -f $VALKEY_PASSWORD_FILE ]] && export VALKEY_PASSWORD="$(< "${VALKEY_PASSWORD_FILE}")" + [[ -n "$VALKEY_PASSWORD" ]] && export REDISCLI_AUTH="$VALKEY_PASSWORD" + {{- end }} + response=$( + timeout -s 15 $1 \ + valkey-cli \ + -h localhost \ + {{- if .Values.tls.enabled }} + -p $VALKEY_SENTINEL_TLS_PORT_NUMBER \ + --tls \ + --cacert "$VALKEY_SENTINEL_TLS_CA_FILE" \ + {{- if .Values.tls.authClients }} + --cert "$VALKEY_SENTINEL_TLS_CERT_FILE" \ + --key "$VALKEY_SENTINEL_TLS_KEY_FILE" \ + {{- end }} + {{- else }} + -p $VALKEY_SENTINEL_PORT \ + {{- end }} + ping + ) + if [ "$?" -eq "124" ]; then + echo "Timed out" + exit 1 + fi + if [ "$response" != "PONG" ]; then + echo "$response" + exit 1 + fi + parse_sentinels.awk: |- + /ip/ {FOUND_IP=1} + /port/ {FOUND_PORT=1} + /runid/ {FOUND_RUNID=1} + !/ip|port|runid/ { + if (FOUND_IP==1) { + IP=$1; FOUND_IP=0; + } + else if (FOUND_PORT==1) { + PORT=$1; + FOUND_PORT=0; + } else if (FOUND_RUNID==1) { + printf "\nsentinel known-sentinel {{ .Values.sentinel.primarySet }} %s %s %s", IP, PORT, $0; FOUND_RUNID=0; + } + } +{{- end }} + ping_readiness_primary.sh: |- + #!/bin/bash + + [[ -f $VALKEY_PRIMARY_PASSWORD_FILE ]] && export VALKEY_PRIMARY_PASSWORD="$(< "${VALKEY_PRIMARY_PASSWORD_FILE}")" + [[ -n "$VALKEY_PRIMARY_PASSWORD" ]] && export REDISCLI_AUTH="$VALKEY_PRIMARY_PASSWORD" + response=$( + timeout -s 15 $1 \ + valkey-cli \ + -h $VALKEY_PRIMARY_HOST \ + -p $VALKEY_PRIMARY_PORT_NUMBER \ + {{- if .Values.tls.enabled }} + --tls \ + --cacert {{ template "valkey.tlsCACert" . }} \ + {{- if .Values.tls.authClients }} + --cert {{ template "valkey.tlsCert" . }} \ + --key {{ template "valkey.tlsCertKey" . }} \ + {{- end }} + {{- end }} + ping + ) + if [ "$?" -eq "124" ]; then + echo "Timed out" + exit 1 + fi + if [ "$response" != "PONG" ]; then + echo "$response" + exit 1 + fi + ping_liveness_primary.sh: |- + #!/bin/bash + + [[ -f $VALKEY_PRIMARY_PASSWORD_FILE ]] && export VALKEY_PRIMARY_PASSWORD="$(< "${VALKEY_PRIMARY_PASSWORD_FILE}")" + [[ -n "$VALKEY_PRIMARY_PASSWORD" ]] && export REDISCLI_AUTH="$VALKEY_PRIMARY_PASSWORD" + response=$( + timeout -s 15 $1 \ + valkey-cli \ + -h $VALKEY_PRIMARY_HOST \ + -p $VALKEY_PRIMARY_PORT_NUMBER \ + {{- if .Values.tls.enabled }} + --tls \ + --cacert {{ template "valkey.tlsCACert" . }} \ + {{- if .Values.tls.authClients }} + --cert {{ template "valkey.tlsCert" . }} \ + --key {{ template "valkey.tlsCertKey" . }} \ + {{- end }} + {{- end }} + ping + ) + if [ "$?" -eq "124" ]; then + echo "Timed out" + exit 1 + fi + responseFirstWord=$(echo $response | head -n1 | awk '{print $1;}') + if [ "$response" != "PONG" ] && [ "$responseFirstWord" != "LOADING" ]; then + echo "$response" + exit 1 + fi + ping_readiness_local_and_primary.sh: |- + script_dir="$(dirname "$0")" + exit_status=0 + "$script_dir/ping_readiness_local.sh" $1 || exit_status=$? + "$script_dir/ping_readiness_primary.sh" $1 || exit_status=$? + exit $exit_status + ping_liveness_local_and_primary.sh: |- + script_dir="$(dirname "$0")" + exit_status=0 + "$script_dir/ping_liveness_local.sh" $1 || exit_status=$? + "$script_dir/ping_liveness_primary.sh" $1 || exit_status=$? + exit $exit_status diff --git a/backing-services/gitea/charts/valkey/templates/metrics-svc.yaml b/backing-services/gitea/charts/valkey/templates/metrics-svc.yaml new file mode 100644 index 0000000..8472183 --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/metrics-svc.yaml @@ -0,0 +1,45 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.service.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-metrics" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: metrics + app.kubernetes.io/part-of: valkey + {{- if or .Values.metrics.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.metrics.service.type }} + {{- if and .Values.metrics.service.clusterIP (eq .Values.metrics.service.type "ClusterIP") }} + clusterIP: {{ .Values.metrics.service.clusterIP }} + {{- end }} + {{- if eq .Values.metrics.service.type "LoadBalancer" }} + externalTrafficPolicy: {{ .Values.metrics.service.externalTrafficPolicy }} + {{- end }} + {{- if and (eq .Values.metrics.service.type "LoadBalancer") .Values.metrics.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.metrics.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.metrics.service.type "LoadBalancer") .Values.metrics.service.loadBalancerClass }} + loadBalancerClass: {{ .Values.metrics.service.loadBalancerClass }} + {{- end }} + {{- if and (eq .Values.metrics.service.type "LoadBalancer") .Values.metrics.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{- toYaml .Values.metrics.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + ports: + - name: http-metrics + port: {{ .Values.metrics.service.ports.http }} + protocol: TCP + targetPort: metrics + {{- if .Values.metrics.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/networkpolicy.yaml b/backing-services/gitea/charts/valkey/templates/networkpolicy.yaml new file mode 100644 index 0000000..56a73c1 --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/networkpolicy.yaml @@ -0,0 +1,109 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ include "common.capabilities.networkPolicy.apiVersion" . }} +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: valkey + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + policyTypes: + - Ingress + - Egress + {{- if .Values.networkPolicy.allowExternalEgress }} + egress: + - {} + {{- else }} + egress: + {{- if eq .Values.architecture "replication" }} + # Allow dns resolution + - ports: + - port: 53 + protocol: UDP + # Allow outbound connections to other cluster pods + - ports: + - port: {{ .Values.primary.containerPorts.valkey }} + {{- if .Values.sentinel.enabled }} + - port: {{ .Values.sentinel.containerPorts.sentinel }} + {{- end }} + to: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }} + {{- end }} + {{- if .Values.networkPolicy.extraEgress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.networkPolicy.extraEgress "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} + ingress: + # Allow inbound connections + - ports: + - port: {{ .Values.primary.containerPorts.valkey }} + {{- if .Values.sentinel.enabled }} + - port: {{ .Values.sentinel.containerPorts.sentinel }} + {{- end }} + {{- if not .Values.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: + {{ template "common.names.fullname" . }}-client: "true" + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }} + {{- if or .Values.networkPolicy.ingressNSMatchLabels .Values.networkPolicy.ingressNSPodMatchLabels }} + - namespaceSelector: + matchLabels: + {{- if .Values.networkPolicy.ingressNSMatchLabels }} + {{- range $key, $value := .Values.networkPolicy.ingressNSMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{ else }} + {} + {{- end }} + {{- if .Values.networkPolicy.ingressNSPodMatchLabels }} + podSelector: + matchLabels: + {{- range $key, $value := .Values.networkPolicy.ingressNSPodMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.metrics.enabled }} + # Allow prometheus scrapes for metrics + - ports: + - port: {{ .Values.metrics.containerPorts.http }} + {{- if not .Values.networkPolicy.metrics.allowExternal }} + from: + {{- if or .Values.networkPolicy.metrics.ingressNSMatchLabels .Values.networkPolicy.metrics.ingressNSPodMatchLabels }} + - namespaceSelector: + matchLabels: + {{- if .Values.networkPolicy.metrics.ingressNSMatchLabels }} + {{- range $key, $value := .Values.networkPolicy.metrics.ingressNSMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{ else }} + {} + {{- end }} + {{- if .Values.networkPolicy.metrics.ingressNSPodMatchLabels }} + podSelector: + matchLabels: + {{- range $key, $value := .Values.networkPolicy.metrics.ingressNSPodMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.networkPolicy.extraIngress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.networkPolicy.extraIngress "context" $ ) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/podmonitor.yaml b/backing-services/gitea/charts/valkey/templates/podmonitor.yaml new file mode 100644 index 0000000..1e7d414 --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/podmonitor.yaml @@ -0,0 +1,82 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.podMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ default (include "common.names.namespace" .) .Values.metrics.podMonitor.namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: valkey + {{- if .Values.metrics.podMonitor.additionalLabels }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.podMonitor.additionalLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + podMetricsEndpoints: + - port: {{ .Values.metrics.podMonitor.port }} + {{- if .Values.metrics.podMonitor.interval }} + interval: {{ .Values.metrics.podMonitor.interval }} + {{- end }} + {{- if .Values.metrics.podMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.metrics.podMonitor.scrapeTimeout }} + {{- end }} + {{- if .Values.metrics.podMonitor.honorLabels }} + honorLabels: {{ .Values.metrics.podMonitor.honorLabels }} + {{- end }} + {{- with .Values.metrics.podMonitor.relabelings }} + relabelings: {{- toYaml . | nindent 6 }} + {{- end }} + {{- if .Values.metrics.podMonitor.metricRelabelings }} + metricRelabelings: {{- toYaml .Values.metrics.podMonitor.metricRelabelings | nindent 6 }} + {{- end }} + {{- range .Values.metrics.podMonitor.additionalEndpoints }} + - port: {{ .port }} + {{- if .interval }} + interval: {{ .interval }} + {{- end }} + {{- if .path }} + path: {{ .path }} + {{- end }} + {{- if .honorLabels }} + honorLabels: {{ .honorLabels }} + {{- end }} + {{- with .relabelings }} + relabelings: {{- toYaml . | nindent 6 }} + {{- end }} + {{- if .metricRelabelings }} + metricRelabelings: {{- toYaml .metricRelabelings | nindent 6 }} + {{- end }} + {{- if .scrapeTimeout }} + scrapeTimeout: {{ .scrapeTimeout }} + {{- end }} + {{- if .params }} + params: + {{- range $key, $value := .params }} + {{ $key }}: + {{- range $value }} + - {{ . | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.podTargetLabels }} + podTargetLabels: {{- toYaml .Values.metrics.podMonitor.podTargetLabels | nindent 4 }} + {{- end }} + {{- with .Values.metrics.podMonitor.sampleLimit -}} + sampleLimit: {{ . }} + {{- end }} + {{- with .Values.metrics.podMonitor.targetLimit -}} + targetLimit: {{ . }} + {{- end }} + namespaceSelector: + matchNames: + - {{ include "common.names.namespace" . | quote }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/primary/application.yaml b/backing-services/gitea/charts/valkey/templates/primary/application.yaml new file mode 100644 index 0000000..337b8a4 --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/primary/application.yaml @@ -0,0 +1,520 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if or (eq .Values.primary.kind "DaemonSet") (gt (int64 .Values.primary.replicaCount) 0) -}} +{{- if or (not (eq .Values.architecture "replication")) (not .Values.sentinel.enabled) }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: {{ .Values.primary.kind }} +metadata: + name: {{ printf "%s-primary" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: primary + app.kubernetes.io/part-of: valkey + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if not (eq .Values.primary.kind "DaemonSet") }} + replicas: {{ .Values.primary.replicaCount }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: primary + {{- if (eq .Values.primary.kind "StatefulSet") }} + serviceName: {{ printf "%s-headless" (include "common.names.fullname" .) }} + {{- end }} + {{- if .Values.primary.updateStrategy }} + {{- if (eq .Values.primary.kind "Deployment") }} + strategy: {{- toYaml .Values.primary.updateStrategy | nindent 4 }} + {{- else }} + updateStrategy: {{- toYaml .Values.primary.updateStrategy | nindent 4 }} + {{- end }} + {{- if .Values.primary.minReadySeconds }} + minReadySeconds: {{ .Values.primary.minReadySeconds }} + {{- end }} + {{- end }} + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: primary + {{- if and .Values.metrics.enabled .Values.metrics.podLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.podLabels "context" $ ) | nindent 8 }} + {{- end }} + annotations: + {{- if (include "valkey.createConfigmap" .) }} + checksum/configmap: {{ pick ( include (print $.Template.BasePath "/configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + {{- end }} + checksum/health: {{ pick ( include (print $.Template.BasePath "/health-configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + checksum/scripts: {{ pick ( include (print $.Template.BasePath "/scripts-configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + checksum/secret: {{ pick ( include (print $.Template.BasePath "/secret.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + {{- if .Values.primary.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.podAnnotations "context" $ ) | nindent 8 }} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.podAnnotations "context" $ ) | nindent 8 }} + {{- end }} + spec: + {{- include "valkey.imagePullSecrets" . | nindent 6 }} + {{- if .Values.primary.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.primary.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.primary.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.primary.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + serviceAccountName: {{ template "valkey.primaryServiceAccountName" . }} + automountServiceAccountToken: {{ .Values.primary.automountServiceAccountToken }} + {{- if .Values.primary.priorityClassName }} + priorityClassName: {{ .Values.primary.priorityClassName | quote }} + {{- end }} + {{- if .Values.primary.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.primary.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.primary.podAffinityPreset "component" "primary" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.primary.podAntiAffinityPreset "component" "primary" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.primary.nodeAffinityPreset.type "key" .Values.primary.nodeAffinityPreset.key "values" .Values.primary.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.primary.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.primary.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.primary.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.primary.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.primary.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.primary.topologySpreadConstraints "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.primary.shareProcessNamespace }} + shareProcessNamespace: {{ .Values.primary.shareProcessNamespace }} + {{- end }} + {{- if .Values.primary.schedulerName }} + schedulerName: {{ .Values.primary.schedulerName | quote }} + {{- end }} + {{- if .Values.primary.dnsPolicy }} + dnsPolicy: {{ .Values.primary.dnsPolicy }} + {{- end }} + {{- if .Values.primary.dnsConfig }} + dnsConfig: {{- include "common.tplvalues.render" (dict "value" .Values.primary.dnsConfig "context" $) | nindent 8 }} + {{- end }} + enableServiceLinks: {{ .Values.primary.enableServiceLinks }} + terminationGracePeriodSeconds: {{ .Values.primary.terminationGracePeriodSeconds }} + {{- $needsVolumePermissions := and .Values.volumePermissions.enabled .Values.primary.persistence.enabled .Values.primary.podSecurityContext.enabled .Values.primary.containerSecurityContext.enabled }} + {{- if or .Values.primary.initContainers $needsVolumePermissions }} + initContainers: + {{- if .Values.primary.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if $needsVolumePermissions }} + - name: volume-permissions + image: {{ include "valkey.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + - -ec + - | + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + chown -R `id -u`:`id -G | cut -d " " -f2` {{ .Values.primary.persistence.path }} + {{- else }} + chown -R {{ .Values.primary.containerSecurityContext.runAsUser }}:{{ .Values.primary.podSecurityContext.fsGroup }} {{ .Values.primary.persistence.path }} + {{- end }} + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.containerSecurityContext "runAsUser" | toYaml | nindent 12 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.containerSecurityContext | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- else if ne .Values.volumePermissions.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.volumePermissions.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: valkey-data + mountPath: {{ .Values.primary.persistence.path }} + {{- if .Values.primary.persistence.subPath }} + subPath: {{ .Values.primary.persistence.subPath }} + {{- else if .Values.primary.persistence.subPathExpr }} + subPathExpr: {{ .Values.primary.persistence.subPathExpr }} + {{- end }} + {{- end }} + {{- end }} + containers: + - name: valkey + image: {{ template "valkey.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.primary.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.primary.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.primary.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.primary.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.primary.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.primary.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.primary.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.primary.args "context" $) | nindent 12 }} + {{- else }} + args: + - -c + - /opt/bitnami/scripts/start-scripts/start-primary.sh + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + - name: VALKEY_REPLICATION_MODE + value: primary + - name: ALLOW_EMPTY_PASSWORD + value: {{ ternary "no" "yes" .Values.auth.enabled | quote }} + {{- if .Values.auth.enabled }} + {{- if .Values.auth.usePasswordFiles }} + - name: VALKEY_PASSWORD_FILE + value: "/opt/bitnami/valkey/secrets/valkey-password" + {{- else }} + - name: VALKEY_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "valkey.secretName" . }} + key: {{ template "valkey.secretPasswordKey" . }} + {{- end }} + {{- end }} + - name: VALKEY_TLS_ENABLED + value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} + {{- if .Values.tls.enabled }} + - name: VALKEY_TLS_PORT + value: {{ .Values.primary.containerPorts.valkey | quote }} + - name: VALKEY_TLS_AUTH_CLIENTS + value: {{ ternary "yes" "no" .Values.tls.authClients | quote }} + - name: VALKEY_TLS_CERT_FILE + value: {{ template "valkey.tlsCert" . }} + - name: VALKEY_TLS_KEY_FILE + value: {{ template "valkey.tlsCertKey" . }} + - name: VALKEY_TLS_CA_FILE + value: {{ template "valkey.tlsCACert" . }} + {{- if .Values.tls.dhParamsFilename }} + - name: VALKEY_TLS_DH_PARAMS_FILE + value: {{ template "valkey.tlsDHParams" . }} + {{- end }} + {{- else }} + - name: VALKEY_PORT + value: {{ .Values.primary.containerPorts.valkey | quote }} + {{- end }} + {{- if .Values.primary.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.primary.extraEnvVarsCM .Values.primary.extraEnvVarsSecret }} + envFrom: + {{- if .Values.primary.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.primary.extraEnvVarsCM }} + {{- end }} + {{- if .Values.primary.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.primary.extraEnvVarsSecret }} + {{- end }} + {{- end }} + ports: + - name: redis + containerPort: {{ .Values.primary.containerPorts.valkey }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.primary.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.primary.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.primary.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.primary.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: redis + {{- end }} + {{- if .Values.primary.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.primary.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.primary.livenessProbe.enabled }} + livenessProbe: + initialDelaySeconds: {{ .Values.primary.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.primary.livenessProbe.periodSeconds }} + # One second longer than command timeout should prevent generation of zombie processes. + timeoutSeconds: {{ add1 .Values.primary.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.primary.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.primary.livenessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_liveness_local.sh {{ .Values.primary.livenessProbe.timeoutSeconds }} + {{- end }} + {{- if .Values.primary.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.primary.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.primary.readinessProbe.enabled }} + readinessProbe: + initialDelaySeconds: {{ .Values.primary.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.primary.readinessProbe.periodSeconds }} + timeoutSeconds: {{ add1 .Values.primary.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.primary.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.primary.readinessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_readiness_local.sh {{ .Values.primary.readinessProbe.timeoutSeconds }} + {{- end }} + {{- end }} + {{- if .Values.primary.resources }} + resources: {{- toYaml .Values.primary.resources | nindent 12 }} + {{- else if ne .Values.primary.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.primary.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: start-scripts + mountPath: /opt/bitnami/scripts/start-scripts + - name: health + mountPath: /health + {{- if and .Values.auth.enabled .Values.auth.usePasswordFiles }} + - name: valkey-password + mountPath: /opt/bitnami/valkey/secrets/ + {{- end }} + - name: valkey-data + mountPath: {{ .Values.primary.persistence.path }} + {{- if .Values.primary.persistence.subPath }} + subPath: {{ .Values.primary.persistence.subPath }} + {{- else if .Values.primary.persistence.subPathExpr }} + subPathExpr: {{ .Values.primary.persistence.subPathExpr }} + {{- end }} + - name: config + mountPath: /opt/bitnami/valkey/mounted-etc + - name: empty-dir + mountPath: /opt/bitnami/valkey/etc/ + subPath: app-conf-dir + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if .Values.tls.enabled }} + - name: valkey-certificates + mountPath: /opt/bitnami/valkey/certs + readOnly: true + {{- end }} + {{- if .Values.primary.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ include "valkey.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.metrics.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.metrics.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.metrics.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -c + - | + {{- if and .Values.auth.enabled .Values.auth.usePasswordFiles }} + export REDIS_PASSWORD="$(< $REDIS_PASSWORD_FILE)" + {{- end }} + redis_exporter{{- range $key, $value := .Values.metrics.extraArgs }} --{{ $key }}={{ $value }}{{- end }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- end }} + env: + - name: REDIS_ALIAS + value: {{ template "common.names.fullname" . }} + - name: REDIS_EXPORTER_WEB_LISTEN_ADDRESS + value: {{ printf ":%v" .Values.metrics.containerPorts.http }} + {{- if .Values.auth.enabled }} + - name: REDIS_USER + value: default + {{- if .Values.auth.usePasswordFiles }} + - name: REDIS_PASSWORD_FILE + value: "/secrets/valkey-password" + {{- else }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "valkey.secretName" . }} + key: {{ template "valkey.secretPasswordKey" . }} + {{- end }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: REDIS_ADDR + value: valkeys://{{ .Values.metrics.valkeyTargetHost }}:{{ .Values.primary.containerPorts.valkey }} + {{- if .Values.tls.authClients }} + - name: REDIS_EXPORTER_TLS_CLIENT_KEY_FILE + value: {{ template "valkey.tlsCertKey" . }} + - name: REDIS_EXPORTER_TLS_CLIENT_CERT_FILE + value: {{ template "valkey.tlsCert" . }} + {{- end }} + - name: REDIS_EXPORTER_TLS_CA_CERT_FILE + value: {{ template "valkey.tlsCACert" . }} + {{- end }} + {{- if .Values.metrics.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + ports: + - name: metrics + containerPort: {{ .Values.metrics.containerPorts.http }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- else if ne .Values.metrics.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.metrics.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: app-tmp-dir + {{- if and .Values.auth.enabled .Values.auth.usePasswordFiles }} + - name: valkey-password + mountPath: /secrets/ + {{- end }} + {{- if .Values.tls.enabled }} + - name: valkey-certificates + mountPath: /opt/bitnami/valkey/certs + readOnly: true + {{- end }} + {{- if .Values.metrics.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.primary.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: start-scripts + configMap: + name: {{ printf "%s-scripts" (include "common.names.fullname" .) }} + defaultMode: 0755 + - name: health + configMap: + name: {{ printf "%s-health" (include "common.names.fullname" .) }} + defaultMode: 0755 + {{- if and .Values.auth.enabled .Values.auth.usePasswordFiles }} + - name: valkey-password + {{ if .Values.auth.usePasswordFileFromSecret }} + secret: + secretName: {{ template "valkey.secretName" . }} + items: + - key: {{ template "valkey.secretPasswordKey" . }} + path: valkey-password + {{- else }} + emptyDir: {} + {{- end }} + {{- end }} + - name: config + configMap: + name: {{ include "valkey.configmapName" . }} + - name: empty-dir + {{- if or .Values.primary.persistence.medium .Values.primary.persistence.sizeLimit }} + emptyDir: + {{- if .Values.primary.persistence.medium }} + medium: {{ .Values.primary.persistence.medium | quote }} + {{- end }} + {{- if .Values.primary.persistence.sizeLimit }} + sizeLimit: {{ .Values.primary.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- if .Values.tls.enabled }} + - name: valkey-certificates + secret: + secretName: {{ include "valkey.tlsSecretName" . }} + defaultMode: 256 + {{- end }} + {{- if .Values.primary.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if .Values.metrics.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if or (not .Values.primary.persistence.enabled) (eq .Values.primary.kind "DaemonSet") }} + - name: valkey-data + {{- if or .Values.primary.persistence.medium .Values.primary.persistence.sizeLimit }} + emptyDir: + {{- if .Values.primary.persistence.medium }} + medium: {{ .Values.primary.persistence.medium | quote }} + {{- end }} + {{- if .Values.primary.persistence.sizeLimit }} + sizeLimit: {{ .Values.primary.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- else if .Values.primary.persistence.existingClaim }} + - name: valkey-data + persistentVolumeClaim: + claimName: {{ printf "%s" (tpl .Values.primary.persistence.existingClaim .) }} + {{- else if (eq .Values.primary.kind "Deployment") }} + - name: valkey-data + persistentVolumeClaim: + claimName: {{ printf "valkey-data-%s-primary" (include "common.names.fullname" .) }} + {{- else }} + {{- if .Values.primary.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.primary.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.primary.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: valkey-data + {{- $claimLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.persistence.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.matchLabels" ( dict "customLabels" $claimLabels "context" $ ) | nindent 10 }} + app.kubernetes.io/component: primary + {{- if .Values.primary.persistence.annotations }} + annotations: {{- toYaml .Values.primary.persistence.annotations | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.primary.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.primary.persistence.size | quote }} + {{- if .Values.primary.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.primary.persistence.selector "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.primary.persistence.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.primary.persistence.dataSource "context" $) | nindent 10 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" .Values.primary.persistence "global" .Values.global) | nindent 8 }} + {{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/primary/pdb.yaml b/backing-services/gitea/charts/valkey/templates/primary/pdb.yaml new file mode 100644 index 0000000..948344b --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/primary/pdb.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- $pdb := coalesce .Values.pdb .Values.primary.pdb }} +{{- if and $pdb.create (gt (int64 .Values.primary.replicaCount) 0) (or (not (eq .Values.architecture "replication")) (not .Values.sentinel.enabled)) }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ printf "%s-primary" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: primary + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if $pdb.minAvailable }} + minAvailable: {{ $pdb.minAvailable }} + {{- end }} + {{- if or $pdb.maxUnavailable (not $pdb.minAvailable)}} + maxUnavailable: {{ $pdb.maxUnavailable | default 1 }} + {{- end }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: primary +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/primary/psp.yaml b/backing-services/gitea/charts/valkey/templates/primary/psp.yaml new file mode 100644 index 0000000..8d9df8d --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/primary/psp.yaml @@ -0,0 +1,48 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (include "common.capabilities.psp.supported" .) .Values.podSecurityPolicy.create }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ printf "%s-primary" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: valkey + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + allowPrivilegeEscalation: false + fsGroup: + rule: 'MustRunAs' + ranges: + - min: {{ .Values.primary.podSecurityContext.fsGroup }} + max: {{ .Values.primary.podSecurityContext.fsGroup }} + hostIPC: false + hostNetwork: false + hostPID: false + privileged: false + readOnlyRootFilesystem: false + requiredDropCapabilities: + - ALL + runAsUser: + rule: 'MustRunAs' + ranges: + - min: {{ .Values.primary.containerSecurityContext.runAsUser }} + max: {{ .Values.primary.containerSecurityContext.runAsUser }} + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + - min: {{ .Values.primary.containerSecurityContext.runAsUser }} + max: {{ .Values.primary.containerSecurityContext.runAsUser }} + volumes: + - 'configMap' + - 'secret' + - 'emptyDir' + - 'persistentVolumeClaim' +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/primary/pvc.yaml b/backing-services/gitea/charts/valkey/templates/primary/pvc.yaml new file mode 100644 index 0000000..df17fab --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/primary/pvc.yaml @@ -0,0 +1,34 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "standalone") (eq .Values.primary.kind "Deployment") (.Values.primary.persistence.enabled) (not .Values.primary.persistence.existingClaim) }} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ printf "valkey-data-%s-primary" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.persistence.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: primary + app.kubernetes.io/part-of: valkey + {{- if .Values.primary.persistence.annotations }} + annotations: {{- toYaml .Values.primary.persistence.annotations | nindent 4 }} + {{- end }} +spec: + accessModes: + {{- range .Values.primary.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.primary.persistence.size | quote }} + {{- if .Values.primary.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.primary.persistence.selector "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.primary.persistence.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.primary.persistence.dataSource "context" $) | nindent 4 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" .Values.primary.persistence "global" .Values.global) | nindent 2 }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/primary/service.yaml b/backing-services/gitea/charts/valkey/templates/primary/service.yaml new file mode 100644 index 0000000..a0ab69e --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/primary/service.yaml @@ -0,0 +1,61 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (not .Values.sentinel.enabled) (gt (int64 .Values.primary.replicaCount) 0) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-primary" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: primary + app.kubernetes.io/part-of: valkey + {{- if or .Values.primary.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.primary.service.type }} + {{- if or (eq .Values.primary.service.type "LoadBalancer") (eq .Values.primary.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.primary.service.externalTrafficPolicy | quote }} + {{- end }} + internalTrafficPolicy: {{ .Values.primary.service.internalTrafficPolicy }} + {{- if and (eq .Values.primary.service.type "LoadBalancer") (not (empty .Values.primary.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.primary.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.primary.service.type "LoadBalancer") .Values.primary.service.loadBalancerClass }} + loadBalancerClass: {{ .Values.primary.service.loadBalancerClass }} + {{- end }} + {{- if and (eq .Values.primary.service.type "LoadBalancer") (not (empty .Values.primary.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ toYaml .Values.primary.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + {{- if and .Values.primary.service.clusterIP (eq .Values.primary.service.type "ClusterIP") }} + clusterIP: {{ .Values.primary.service.clusterIP }} + {{- end }} + {{- if .Values.primary.service.sessionAffinity }} + sessionAffinity: {{ .Values.primary.service.sessionAffinity }} + {{- end }} + {{- if .Values.primary.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.primary.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.primary.service.externalIPs }} + externalIPs: {{- include "common.tplvalues.render" (dict "value" .Values.primary.service.externalIPs "context" $) | nindent 4 }} + {{- end }} + ports: + - name: tcp-redis + port: {{ .Values.primary.service.ports.valkey }} + targetPort: redis + {{- if and (or (eq .Values.primary.service.type "NodePort") (eq .Values.primary.service.type "LoadBalancer")) .Values.primary.service.nodePorts.valkey}} + nodePort: {{ .Values.primary.service.nodePorts.valkey}} + {{- else if eq .Values.primary.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.primary.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: primary +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/primary/serviceaccount.yaml b/backing-services/gitea/charts/valkey/templates/primary/serviceaccount.yaml new file mode 100644 index 0000000..5fe059f --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/primary/serviceaccount.yaml @@ -0,0 +1,19 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.primary.serviceAccount.create (or (not (eq .Values.architecture "replication")) (not .Values.sentinel.enabled)) }} +apiVersion: v1 +kind: ServiceAccount +automountServiceAccountToken: {{ .Values.primary.serviceAccount.automountServiceAccountToken }} +metadata: + name: {{ template "valkey.primaryServiceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: valkey + {{- if or .Values.primary.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/prometheusrule.yaml b/backing-services/gitea/charts/valkey/templates/prometheusrule.yaml new file mode 100644 index 0000000..c7b320b --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/prometheusrule.yaml @@ -0,0 +1,24 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ default (include "common.names.namespace" .) .Values.metrics.prometheusRule.namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: valkey + {{- if .Values.metrics.prometheusRule.additionalLabels }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.prometheusRule.additionalLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + groups: + - name: {{ include "common.names.fullname" . }} + rules: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.prometheusRule.rules "context" $ ) | nindent 8 }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/replicas/application.yaml b/backing-services/gitea/charts/valkey/templates/replicas/application.yaml new file mode 100644 index 0000000..ab444d7 --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/replicas/application.yaml @@ -0,0 +1,535 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replication") (not .Values.sentinel.enabled) }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: {{ .Values.replica.kind }} +metadata: + name: {{ printf "%s-replicas" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: replica + app.kubernetes.io/part-of: valkey + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if and (not (eq .Values.replica.kind "DaemonSet")) (not .Values.replica.autoscaling.enabled) }} + replicas: {{ .Values.replica.replicaCount }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.replica.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: replica + {{- if (eq .Values.replica.kind "StatefulSet") }} + serviceName: {{ printf "%s-headless" (include "common.names.fullname" .) }} + {{- end }} + {{- if .Values.replica.updateStrategy }} + updateStrategy: {{- toYaml .Values.replica.updateStrategy | nindent 4 }} + {{- end }} + {{- if .Values.replica.minReadySeconds }} + minReadySeconds: {{ .Values.replica.minReadySeconds }} + {{- end }} + {{- if .Values.replica.podManagementPolicy }} + podManagementPolicy: {{ .Values.replica.podManagementPolicy | quote }} + {{- end }} + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: replica + {{- if and .Values.metrics.enabled .Values.metrics.podLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.podLabels "context" $ ) | nindent 8 }} + {{- end }} + annotations: + {{- if (include "valkey.createConfigmap" .) }} + checksum/configmap: {{ pick ( include (print $.Template.BasePath "/configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + {{- end }} + checksum/health: {{ pick ( include (print $.Template.BasePath "/health-configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + checksum/scripts: {{ pick ( include (print $.Template.BasePath "/scripts-configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + checksum/secret: {{ pick ( include (print $.Template.BasePath "/secret.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + {{- if .Values.replica.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.podAnnotations "context" $ ) | nindent 8 }} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.podAnnotations "context" $ ) | nindent 8 }} + {{- end }} + spec: + {{- include "valkey.imagePullSecrets" . | nindent 6 }} + {{- if .Values.replica.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.replica.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.replica.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + serviceAccountName: {{ template "valkey.replicaServiceAccountName" . }} + automountServiceAccountToken: {{ .Values.replica.automountServiceAccountToken }} + {{- if .Values.replica.priorityClassName }} + priorityClassName: {{ .Values.replica.priorityClassName | quote }} + {{- end }} + {{- if .Values.replica.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.replica.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.replica.podAffinityPreset "component" "replica" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.replica.podAntiAffinityPreset "component" "replica" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.replica.nodeAffinityPreset.type "key" .Values.replica.nodeAffinityPreset.key "values" .Values.replica.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.replica.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.replica.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.replica.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.replica.topologySpreadConstraints "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.shareProcessNamespace }} + shareProcessNamespace: {{ .Values.replica.shareProcessNamespace }} + {{- end }} + {{- if .Values.replica.schedulerName }} + schedulerName: {{ .Values.replica.schedulerName | quote }} + {{- end }} + {{- if .Values.replica.dnsPolicy }} + dnsPolicy: {{ .Values.replica.dnsPolicy }} + {{- end }} + {{- if .Values.replica.dnsConfig }} + dnsConfig: {{- include "common.tplvalues.render" (dict "value" .Values.replica.dnsConfig "context" $) | nindent 8 }} + {{- end }} + enableServiceLinks: {{ .Values.replica.enableServiceLinks }} + terminationGracePeriodSeconds: {{ .Values.replica.terminationGracePeriodSeconds }} + {{- $needsVolumePermissions := and .Values.volumePermissions.enabled .Values.replica.persistence.enabled .Values.replica.podSecurityContext.enabled .Values.replica.containerSecurityContext.enabled }} + {{- if or .Values.replica.initContainers $needsVolumePermissions }} + initContainers: + {{- if .Values.replica.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if $needsVolumePermissions }} + - name: volume-permissions + image: {{ include "valkey.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + - -ec + - | + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + chown -R `id -u`:`id -G | cut -d " " -f2` {{ .Values.replica.persistence.path }} + {{- else }} + chown -R {{ .Values.replica.containerSecurityContext.runAsUser }}:{{ .Values.replica.podSecurityContext.fsGroup }} {{ .Values.replica.persistence.path }} + {{- end }} + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.containerSecurityContext "runAsUser" | toYaml | nindent 12 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.containerSecurityContext | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- else if ne .Values.volumePermissions.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.volumePermissions.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: valkey-data + mountPath: {{ .Values.replica.persistence.path }} + {{- if .Values.replica.persistence.subPath }} + subPath: {{ .Values.replica.persistence.subPath }} + {{- else if .Values.replica.persistence.subPathExpr }} + subPathExpr: {{ .Values.replica.persistence.subPathExpr }} + {{- end }} + {{- end }} + {{- end }} + containers: + - name: valkey + image: {{ template "valkey.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.replica.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.replica.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.replica.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.replica.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.replica.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.replica.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.replica.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.replica.args "context" $) | nindent 12 }} + {{- else }} + args: + - -c + - /opt/bitnami/scripts/start-scripts/start-replica.sh + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + - name: VALKEY_REPLICATION_MODE + value: replica + - name: VALKEY_PRIMARY_HOST + {{- if .Values.replica.externalPrimary.enabled }} + value: {{ .Values.replica.externalPrimary.host | quote }} + {{- else if and (eq (int64 .Values.primary.replicaCount) 1) (eq .Values.primary.kind "StatefulSet") }} + value: {{ template "common.names.fullname" . }}-primary-0.{{ template "common.names.fullname" . }}-headless.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }} + {{- else }} + value: {{ template "common.names.fullname" . }}-primary.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }} + {{- end }} + - name: VALKEY_PRIMARY_PORT_NUMBER + {{- if .Values.replica.externalPrimary.enabled }} + value: {{ .Values.replica.externalPrimary.port | quote }} + {{- else }} + value: {{ .Values.primary.containerPorts.valkey | quote }} + {{- end }} + - name: ALLOW_EMPTY_PASSWORD + value: {{ ternary "no" "yes" .Values.auth.enabled | quote }} + {{- if .Values.auth.enabled }} + {{- if .Values.auth.usePasswordFiles }} + - name: VALKEY_PASSWORD_FILE + value: "/opt/bitnami/valkey/secrets/valkey-password" + - name: VALKEY_PRIMARY_PASSWORD_FILE + value: "/opt/bitnami/valkey/secrets/valkey-password" + {{- else }} + - name: VALKEY_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "valkey.secretName" . }} + key: {{ template "valkey.secretPasswordKey" . }} + - name: VALKEY_PRIMARY_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "valkey.secretName" . }} + key: {{ template "valkey.secretPasswordKey" . }} + {{- end }} + {{- end }} + - name: VALKEY_TLS_ENABLED + value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} + {{- if .Values.tls.enabled }} + - name: VALKEY_TLS_PORT + value: {{ .Values.replica.containerPorts.valkey | quote }} + - name: VALKEY_TLS_AUTH_CLIENTS + value: {{ ternary "yes" "no" .Values.tls.authClients | quote }} + - name: VALKEY_TLS_CERT_FILE + value: {{ template "valkey.tlsCert" . }} + - name: VALKEY_TLS_KEY_FILE + value: {{ template "valkey.tlsCertKey" . }} + - name: VALKEY_TLS_CA_FILE + value: {{ template "valkey.tlsCACert" . }} + {{- if .Values.tls.dhParamsFilename }} + - name: VALKEY_TLS_DH_PARAMS_FILE + value: {{ template "valkey.tlsDHParams" . }} + {{- end }} + {{- else }} + - name: VALKEY_PORT + value: {{ .Values.replica.containerPorts.valkey | quote }} + {{- end }} + {{- if .Values.replica.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.replica.extraEnvVarsCM .Values.replica.extraEnvVarsSecret }} + envFrom: + {{- if .Values.replica.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.replica.extraEnvVarsCM }} + {{- end }} + {{- if .Values.replica.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.replica.extraEnvVarsSecret }} + {{- end }} + {{- end }} + ports: + - name: redis + containerPort: {{ .Values.replica.containerPorts.valkey }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.replica.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.replica.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.replica.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.replica.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: redis + {{- end }} + {{- if .Values.replica.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.replica.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.replica.livenessProbe.enabled }} + livenessProbe: + initialDelaySeconds: {{ .Values.replica.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.replica.livenessProbe.periodSeconds }} + timeoutSeconds: {{ add1 .Values.replica.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.replica.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.replica.livenessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_liveness_local_and_primary.sh {{ .Values.replica.livenessProbe.timeoutSeconds }} + {{- end }} + {{- if .Values.replica.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.replica.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.replica.readinessProbe.enabled }} + readinessProbe: + initialDelaySeconds: {{ .Values.replica.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.replica.readinessProbe.periodSeconds }} + timeoutSeconds: {{ add1 .Values.replica.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.replica.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.replica.readinessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_readiness_local_and_primary.sh {{ .Values.replica.readinessProbe.timeoutSeconds }} + {{- end }} + {{- end }} + {{- if .Values.replica.resources }} + resources: {{- toYaml .Values.replica.resources | nindent 12 }} + {{- else if ne .Values.replica.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.replica.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: start-scripts + mountPath: /opt/bitnami/scripts/start-scripts + - name: health + mountPath: /health + {{- if and .Values.auth.enabled .Values.auth.usePasswordFiles }} + - name: valkey-password + mountPath: /opt/bitnami/valkey/secrets/ + {{- end }} + - name: valkey-data + mountPath: /data + {{- if .Values.replica.persistence.subPath }} + subPath: {{ .Values.replica.persistence.subPath }} + {{- else if .Values.replica.persistence.subPathExpr }} + subPathExpr: {{ .Values.replica.persistence.subPathExpr }} + {{- end }} + - name: config + mountPath: /opt/bitnami/valkey/mounted-etc + - name: empty-dir + mountPath: /opt/bitnami/valkey/etc + subPath: app-conf-dir + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if .Values.tls.enabled }} + - name: valkey-certificates + mountPath: /opt/bitnami/valkey/certs + readOnly: true + {{- end }} + {{- if .Values.replica.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ include "valkey.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.metrics.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.metrics.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.metrics.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -c + - | + {{- if and .Values.auth.enabled .Values.auth.usePasswordFiles }} + export REDIS_PASSWORD="$(< $REDIS_PASSWORD_FILE)" + {{- end }} + redis_exporter{{- range $key, $value := .Values.metrics.extraArgs }} --{{ $key }}={{ $value }}{{- end }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- end }} + env: + - name: REDIS_ALIAS + value: {{ template "common.names.fullname" . }} + - name: REDIS_EXPORTER_WEB_LISTEN_ADDRESS + value: {{ printf ":%v" .Values.metrics.containerPorts.http }} + {{- if .Values.auth.enabled }} + - name: REDIS_USER + value: default + {{- if .Values.auth.usePasswordFiles }} + - name: REDIS_PASSWORD_FILE + value: "/secrets/valkey-password" + {{- else }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "valkey.secretName" . }} + key: {{ template "valkey.secretPasswordKey" . }} + {{- end }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: REDIS_ADDR + value: valkeys://{{ .Values.metrics.valkeyTargetHost }}:{{ .Values.replica.containerPorts.valkey }} + {{- if .Values.tls.authClients }} + - name: REDIS_EXPORTER_TLS_CLIENT_KEY_FILE + value: {{ template "valkey.tlsCertKey" . }} + - name: REDIS_EXPORTER_TLS_CLIENT_CERT_FILE + value: {{ template "valkey.tlsCert" . }} + {{- end }} + - name: REDIS_EXPORTER_TLS_CA_CERT_FILE + value: {{ template "valkey.tlsCACert" . }} + {{- end }} + {{- if .Values.metrics.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + ports: + - name: metrics + containerPort: {{ .Values.metrics.containerPorts.http }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- else if ne .Values.metrics.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.metrics.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if and .Values.auth.enabled .Values.auth.usePasswordFiles }} + - name: valkey-password + mountPath: /secrets/ + {{- end }} + {{- if .Values.tls.enabled }} + - name: valkey-certificates + mountPath: /opt/bitnami/valkey/certs + readOnly: true + {{- end }} + {{- if .Values.metrics.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.replica.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: start-scripts + configMap: + name: {{ printf "%s-scripts" (include "common.names.fullname" .) }} + defaultMode: 0755 + - name: health + configMap: + name: {{ printf "%s-health" (include "common.names.fullname" .) }} + defaultMode: 0755 + {{- if and .Values.auth.enabled .Values.auth.usePasswordFiles }} + - name: valkey-password + {{ if .Values.auth.usePasswordFileFromSecret }} + secret: + secretName: {{ template "valkey.secretName" . }} + items: + - key: {{ template "valkey.secretPasswordKey" . }} + path: valkey-password + {{- else }} + emptyDir: {} + {{- end }} + {{- end }} + - name: config + configMap: + name: {{ include "valkey.configmapName" . }} + - name: empty-dir + {{- if or .Values.replica.persistence.medium .Values.replica.persistence.sizeLimit }} + emptyDir: + {{- if .Values.replica.persistence.medium }} + medium: {{ .Values.replica.persistence.medium | quote }} + {{- end }} + {{- if .Values.replica.persistence.sizeLimit }} + sizeLimit: {{ .Values.replica.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- if .Values.tls.enabled }} + - name: valkey-certificates + secret: + secretName: {{ include "valkey.tlsSecretName" . }} + defaultMode: 256 + {{- end }} + {{- if .Values.replica.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if .Values.metrics.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if or (not .Values.replica.persistence.enabled) (not (eq .Values.replica.kind "StatefulSet")) }} + - name: valkey-data + {{- if or .Values.replica.persistence.medium .Values.replica.persistence.sizeLimit }} + emptyDir: + {{- if .Values.replica.persistence.medium }} + medium: {{ .Values.replica.persistence.medium | quote }} + {{- end }} + {{- if .Values.replica.persistence.sizeLimit }} + sizeLimit: {{ .Values.replica.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- else if .Values.replica.persistence.existingClaim }} + - name: valkey-data + persistentVolumeClaim: + claimName: {{ printf "%s" (tpl .Values.replica.persistence.existingClaim .) }} + {{- else }} + {{- if .Values.replica.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.replica.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.replica.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: valkey-data + {{- $claimLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.persistence.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.matchLabels" ( dict "customLabels" $claimLabels "context" $ ) | nindent 10 }} + app.kubernetes.io/component: replica + {{- if .Values.replica.persistence.annotations }} + annotations: {{- toYaml .Values.replica.persistence.annotations | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.replica.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.replica.persistence.size | quote }} + {{- if .Values.replica.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.replica.persistence.selector "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.replica.persistence.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.replica.persistence.dataSource "context" $) | nindent 10 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" .Values.replica.persistence "global" .Values.global) | nindent 8 }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/replicas/hpa.yaml b/backing-services/gitea/charts/valkey/templates/replicas/hpa.yaml new file mode 100644 index 0000000..ef0489e --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/replicas/hpa.yaml @@ -0,0 +1,42 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.replica.autoscaling.hpa.enabled (not .Values.sentinel.enabled) }} +apiVersion: {{ include "common.capabilities.hpa.apiVersion" ( dict "context" $ ) }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ printf "%s-replicas" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: replica + app.kubernetes.io/part-of: valkey + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + scaleTargetRef: + apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} + kind: StatefulSet + name: {{ printf "%s-replicas" (include "common.names.fullname" .) }} + minReplicas: {{ .Values.replica.autoscaling.hpa.minReplicas }} + maxReplicas: {{ .Values.replica.autoscaling.hpa.maxReplicas }} + metrics: + {{- if .Values.replica.autoscaling.hpa.targetCPU }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.replica.autoscaling.hpa.targetCPU }} + {{- end }} + {{- if .Values.replica.autoscaling.hpa.targetMemory }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.replica.autoscaling.hpa.targetMemory }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/replicas/pdb.yaml b/backing-services/gitea/charts/valkey/templates/replicas/pdb.yaml new file mode 100644 index 0000000..d7b777b --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/replicas/pdb.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- $pdb := coalesce .Values.pdb .Values.replica.pdb }} +{{- if and (eq .Values.architecture "replication") (not .Values.sentinel.enabled) $pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ printf "%s-replicas" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: replica + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if $pdb.minAvailable }} + minAvailable: {{ $pdb.minAvailable }} + {{- end }} + {{- if or $pdb.maxUnavailable (not $pdb.minAvailable) }} + maxUnavailable: {{ $pdb.maxUnavailable | default 1 }} + {{- end }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: replica +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/replicas/service.yaml b/backing-services/gitea/charts/valkey/templates/replicas/service.yaml new file mode 100644 index 0000000..8bf2d7f --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/replicas/service.yaml @@ -0,0 +1,58 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replication") (not .Values.sentinel.enabled) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-replicas" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: replica + app.kubernetes.io/part-of: valkey + {{- if or .Values.replica.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.replica.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.replica.service.type }} + {{- if or (eq .Values.replica.service.type "LoadBalancer") (eq .Values.replica.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.replica.service.externalTrafficPolicy | quote }} + {{- end }} + internalTrafficPolicy: {{ .Values.replica.service.internalTrafficPolicy }} + {{- if and (eq .Values.replica.service.type "LoadBalancer") (not (empty .Values.replica.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.replica.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.replica.service.type "LoadBalancer") .Values.replica.service.loadBalancerClass }} + loadBalancerClass: {{ .Values.replica.service.loadBalancerClass }} + {{- end }} + {{- if and (eq .Values.replica.service.type "LoadBalancer") (not (empty .Values.replica.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ toYaml .Values.replica.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + {{- if and .Values.replica.service.clusterIP (eq .Values.replica.service.type "ClusterIP") }} + clusterIP: {{ .Values.replica.service.clusterIP }} + {{- end }} + {{- if .Values.replica.service.sessionAffinity }} + sessionAffinity: {{ .Values.replica.service.sessionAffinity }} + {{- end }} + {{- if .Values.replica.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.replica.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + ports: + - name: tcp-redis + port: {{ .Values.replica.service.ports.valkey }} + targetPort: redis + {{- if and (or (eq .Values.replica.service.type "NodePort") (eq .Values.replica.service.type "LoadBalancer")) .Values.replica.service.nodePorts.valkey}} + nodePort: {{ .Values.replica.service.nodePorts.valkey}} + {{- else if eq .Values.replica.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.replica.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.replica.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: replica +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/replicas/serviceaccount.yaml b/backing-services/gitea/charts/valkey/templates/replicas/serviceaccount.yaml new file mode 100644 index 0000000..5693ff0 --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/replicas/serviceaccount.yaml @@ -0,0 +1,19 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.replica.serviceAccount.create (eq .Values.architecture "replication") (not .Values.sentinel.enabled) }} +apiVersion: v1 +kind: ServiceAccount +automountServiceAccountToken: {{ .Values.replica.serviceAccount.automountServiceAccountToken }} +metadata: + name: {{ template "valkey.replicaServiceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: valkey + {{- if or .Values.replica.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.replica.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/replicas/vpa.yaml b/backing-services/gitea/charts/valkey/templates/replicas/vpa.yaml new file mode 100644 index 0000000..702a350 --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/replicas/vpa.yaml @@ -0,0 +1,45 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (include "common.capabilities.apiVersions.has" ( dict "version" "autoscaling.k8s.io/v1/VerticalPodAutoscaler" "context" . )) .Values.replica.autoscaling.vpa.enabled (not .Values.sentinel.enabled) }} +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: replica + app.kubernetes.io/part-of: valkey + {{- if or .Values.replica.autoscaling.vpa.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.replica.autoscaling.vpa.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + resourcePolicy: + containerPolicies: + - containerName: valkey + {{- with .Values.replica.autoscaling.vpa.controlledResources }} + controlledResources: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.replica.autoscaling.vpa.maxAllowed }} + maxAllowed: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.replica.autoscaling.vpa.minAllowed }} + minAllowed: + {{- toYaml . | nindent 8 }} + {{- end }} + targetRef: + apiVersion: apps/v1 + kind: {{ .Values.replica.kind }} + name: {{ printf "%s-replicas" (include "common.names.fullname" .) }} + {{- if .Values.replica.autoscaling.vpa.updatePolicy }} + updatePolicy: + {{- with .Values.replica.autoscaling.vpa.updatePolicy.updateMode }} + updateMode: {{ . }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/role.yaml b/backing-services/gitea/charts/valkey/templates/role.yaml new file mode 100644 index 0000000..a04929a --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/role.yaml @@ -0,0 +1,35 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.rbac.create }} +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: Role +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: valkey + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: + {{- if and (include "common.capabilities.psp.supported" .) .Values.podSecurityPolicy.enabled }} + - apiGroups: + - 'policy' + resources: + - 'podsecuritypolicies' + verbs: + - 'use' + resourceNames: [{{ printf "%s-primary" (include "common.names.fullname" .) }}] + {{- end }} + {{- if and .Values.sentinel.enabled .Values.sentinel.service.createPrimary}} + - apiGroups: [""] + resources: ["pods"] + verbs: ["list", "patch"] + {{- end -}} + {{- if .Values.rbac.rules }} + {{- include "common.tplvalues.render" ( dict "value" .Values.rbac.rules "context" $ ) | nindent 2 }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/rolebinding.yaml b/backing-services/gitea/charts/valkey/templates/rolebinding.yaml new file mode 100644 index 0000000..1e434e9 --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/rolebinding.yaml @@ -0,0 +1,24 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.rbac.create }} +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: RoleBinding +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: valkey + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "common.names.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "valkey.serviceAccountName" . }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/scripts-configmap.yaml b/backing-services/gitea/charts/valkey/templates/scripts-configmap.yaml new file mode 100644 index 0000000..934d588 --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/scripts-configmap.yaml @@ -0,0 +1,792 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-scripts" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: valkey + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: +{{- if and (eq .Values.architecture "replication") .Values.sentinel.enabled }} + start-node.sh: | + #!/bin/bash + + . /opt/bitnami/scripts/libos.sh + . /opt/bitnami/scripts/liblog.sh + . /opt/bitnami/scripts/libvalidations.sh + + get_port() { + hostname="$1" + type="$2" + + port_var=$(echo "${hostname^^}_SERVICE_PORT_$type" | sed "s/-/_/g") + port=${!port_var} + + if [ -z "$port" ]; then + case $type in + "SENTINEL") + echo {{ .Values.sentinel.containerPorts.sentinel }} + ;; + "VALKEY") + echo {{ .Values.primary.containerPorts.valkey }} + ;; + esac + else + echo $port + fi + } + + get_full_hostname() { + hostname="$1" + + {{- if .Values.useExternalDNS.enabled }} + full_hostname="${hostname}.{{- include "valkey.externalDNS.suffix" . }}" + {{- else if eq .Values.sentinel.service.type "NodePort" }} + full_hostname="${hostname}.{{- include "common.names.namespace" . }}" + {{- else }} + full_hostname="${hostname}.${HEADLESS_SERVICE}" + {{- end }} + + {{- if .Values.useHostnames }} + echo "${full_hostname}" + {{- else }} + retry_count=0 + until getent hosts "${full_hostname}" | awk '{ print $1; exit }' | grep .; do + if [[ $retry_count -lt {{ .Values.nameResolutionThreshold }} ]]; then + sleep {{ .Values.nameResolutionTimeout }} + else + error "IP address for ${full_hostname} not found" + exit 1 + fi + ((retry_count++)) + done + {{- end }} + } + + VALKEYPORT=$(get_port "$HOSTNAME" "VALKEY") + + HEADLESS_SERVICE="{{ template "common.names.fullname" . }}-headless.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}" + + if [ -n "$VALKEY_EXTERNAL_PRIMARY_HOST" ]; then + VALKEY_SERVICE="$VALKEY_EXTERNAL_PRIMARY_HOST" + else + VALKEY_SERVICE="{{ template "common.names.fullname" . }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}" + fi + + SENTINEL_SERVICE_PORT=$(get_port "{{ include "common.names.fullname" . }}" "SENTINEL") + validate_quorum() { + if is_boolean_yes "$VALKEY_TLS_ENABLED"; then + quorum_info_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$VALKEY_PASSWORD" {{ end }}valkey-cli -h $VALKEY_SERVICE -p $SENTINEL_SERVICE_PORT --tls --cert ${VALKEY_TLS_CERT_FILE} --key ${VALKEY_TLS_KEY_FILE} --cacert ${VALKEY_TLS_CA_FILE} sentinel primary {{ .Values.sentinel.primarySet }}" + else + quorum_info_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$VALKEY_PASSWORD" {{ end }}valkey-cli -h $VALKEY_SERVICE -p $SENTINEL_SERVICE_PORT sentinel primary {{ .Values.sentinel.primarySet }}" + fi + info "about to run the command: $quorum_info_command" + eval $quorum_info_command | grep -Fq "s_down" + } + + trigger_manual_failover() { + if is_boolean_yes "$VALKEY_TLS_ENABLED"; then + failover_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$VALKEY_PASSWORD" {{ end }}valkey-cli -h $VALKEY_SERVICE -p $SENTINEL_SERVICE_PORT --tls --cert ${VALKEY_TLS_CERT_FILE} --key ${VALKEY_TLS_KEY_FILE} --cacert ${VALKEY_TLS_CA_FILE} sentinel failover {{ .Values.sentinel.primarySet }}" + else + failover_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$VALKEY_PASSWORD" {{ end }}valkey-cli -h $VALKEY_SERVICE -p $SENTINEL_SERVICE_PORT sentinel failover {{ .Values.sentinel.primarySet }}" + fi + + info "about to run the command: $failover_command" + eval $failover_command + } + + get_sentinel_primary_info() { + if is_boolean_yes "$VALKEY_TLS_ENABLED"; then + sentinel_info_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$VALKEY_PASSWORD" {{ end }}timeout {{ .Values.sentinel.getPrimaryTimeout }} valkey-cli -h $VALKEY_SERVICE -p $SENTINEL_SERVICE_PORT --tls --cert ${VALKEY_TLS_CERT_FILE} --key ${VALKEY_TLS_KEY_FILE} --cacert ${VALKEY_TLS_CA_FILE} sentinel get-primary-addr-by-name {{ .Values.sentinel.primarySet }}" + else + sentinel_info_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$VALKEY_PASSWORD" {{ end }}timeout {{ .Values.sentinel.getPrimaryTimeout }} valkey-cli -h $VALKEY_SERVICE -p $SENTINEL_SERVICE_PORT sentinel get-primary-addr-by-name {{ .Values.sentinel.primarySet }}" + fi + + info "about to run the command: $sentinel_info_command" + retry_while "eval $sentinel_info_command" 2 5 + } + + {{- if and .Values.replica.containerSecurityContext.runAsUser (eq (.Values.replica.containerSecurityContext.runAsUser | int) 0) }} + useradd valkey + chown -R valkey {{ .Values.replica.persistence.path }} + {{- end }} + + [[ -f $VALKEY_PASSWORD_FILE ]] && export VALKEY_PASSWORD="$(< "${VALKEY_PASSWORD_FILE}")" + [[ -f $VALKEY_PRIMARY_PASSWORD_FILE ]] && export VALKEY_PRIMARY_PASSWORD="$(< "${VALKEY_PRIMARY_PASSWORD_FILE}")" + + # check if there is a primary + primary_in_persisted_conf="$(get_full_hostname "$HOSTNAME")" + primary_port_in_persisted_conf="$VALKEY_PRIMARY_PORT_NUMBER" + primary_in_sentinel="$(get_sentinel_primary_info)" + valkeyRetVal=$? + + if [[ -f /opt/bitnami/valkey-sentinel/etc/sentinel.conf ]]; then + primary_in_persisted_conf="$(awk '/monitor/ {print $4}' /opt/bitnami/valkey-sentinel/etc/sentinel.conf)" + primary_port_in_persisted_conf="$(awk '/monitor/ {print $5}' /opt/bitnami/valkey-sentinel/etc/sentinel.conf)" + info "Found previous primary ${primary_in_persisted_conf}:${primary_port_in_persisted_conf} in /opt/bitnami/valkey-sentinel/etc/sentinel.conf" + debug "$(cat /opt/bitnami/valkey-sentinel/etc/sentinel.conf | grep monitor)" + fi + + if [[ $valkeyRetVal -ne 0 ]]; then + if [[ "$primary_in_persisted_conf" == "$(get_full_hostname "$HOSTNAME")" ]]; then + # Case 1: No active sentinel and in previous sentinel.conf we were the primary --> PRIMARY + info "Configuring the node as primary" + export VALKEY_REPLICATION_MODE="primary" + else + # Case 2: No active sentinel and in previous sentinel.conf we were not primary --> REPLICA + info "Configuring the node as replica" + export VALKEY_REPLICATION_MODE="replica" + VALKEY_PRIMARY_HOST=${primary_in_persisted_conf} + VALKEY_PRIMARY_PORT_NUMBER=${primary_port_in_persisted_conf} + fi + else + # Fetches current primary's host and port + VALKEY_SENTINEL_INFO=($(get_sentinel_primary_info)) + info "Current primary: VALKEY_SENTINEL_INFO=(${VALKEY_SENTINEL_INFO[0]},${VALKEY_SENTINEL_INFO[1]})" + VALKEY_PRIMARY_HOST=${VALKEY_SENTINEL_INFO[0]} + VALKEY_PRIMARY_PORT_NUMBER=${VALKEY_SENTINEL_INFO[1]} + + if [[ "$VALKEY_PRIMARY_HOST" == "$(get_full_hostname "$HOSTNAME")" ]]; then + # Case 3: Active sentinel and primary it is this node --> PRIMARY + info "Configuring the node as primary" + export VALKEY_REPLICATION_MODE="primary" + else + # Case 4: Active sentinel and primary is not this node --> REPLICA + info "Configuring the node as replica" + export VALKEY_REPLICATION_MODE="replica" + + {{- if and .Values.sentinel.automateClusterRecovery (le (int .Values.sentinel.downAfterMilliseconds) 2000) }} + retry_count=1 + while validate_quorum + do + info "sleeping, waiting for Valkey primary to come up" + sleep 1s + if ! ((retry_count % 11)); then + info "Trying to manually failover" + failover_result=$(trigger_manual_failover) + + debug "Failover result: $failover_result" + fi + + ((retry_count+=1)) + done + info "Valkey primary is up now" + {{- end }} + fi + fi + + if [[ -n "$VALKEY_EXTERNAL_PRIMARY_HOST" ]]; then + VALKEY_PRIMARY_HOST="$VALKEY_EXTERNAL_PRIMARY_HOST" + VALKEY_PRIMARY_PORT_NUMBER="${VALKEY_EXTERNAL_PRIMARY_PORT}" + fi + + if [[ -f /opt/bitnami/valkey/mounted-etc/replica.conf ]];then + cp /opt/bitnami/valkey/mounted-etc/replica.conf /opt/bitnami/valkey/etc/replica.conf + fi + + if [[ -f /opt/bitnami/valkey/mounted-etc/valkey.conf ]];then + cp /opt/bitnami/valkey/mounted-etc/valkey.conf /opt/bitnami/valkey/etc/valkey.conf + fi + + echo "" >> /opt/bitnami/valkey/etc/replica.conf + echo "replica-announce-port $VALKEYPORT" >> /opt/bitnami/valkey/etc/replica.conf + echo "replica-announce-ip $(get_full_hostname "$HOSTNAME")" >> /opt/bitnami/valkey/etc/replica.conf + + {{- if .Values.tls.enabled }} + ARGS=("--port" "0") + ARGS+=("--tls-port" "${VALKEY_TLS_PORT}") + ARGS+=("--tls-cert-file" "${VALKEY_TLS_CERT_FILE}") + ARGS+=("--tls-key-file" "${VALKEY_TLS_KEY_FILE}") + ARGS+=("--tls-ca-cert-file" "${VALKEY_TLS_CA_FILE}") + ARGS+=("--tls-auth-clients" "${VALKEY_TLS_AUTH_CLIENTS}") + ARGS+=("--tls-replication" "yes") + {{- if .Values.tls.dhParamsFilename }} + ARGS+=("--tls-dh-params-file" "${VALKEY_TLS_DH_PARAMS_FILE}") + {{- end }} + {{- else }} + ARGS=("--port" "${VALKEY_PORT}") + {{- end }} + + if [[ "$VALKEY_REPLICATION_MODE" = "replica" ]]; then + ARGS+=("--replicaof" "${VALKEY_PRIMARY_HOST}" "${VALKEY_PRIMARY_PORT_NUMBER}") + fi + + {{- if .Values.auth.enabled }} + ARGS+=("--requirepass" "${VALKEY_PASSWORD}") + ARGS+=("--primaryauth" "${VALKEY_PRIMARY_PASSWORD}") + {{- else }} + ARGS+=("--protected-mode" "no") + {{- end }} + ARGS+=("--include" "/opt/bitnami/valkey/etc/replica.conf") + ARGS+=("--include" "/opt/bitnami/valkey/etc/valkey.conf") + {{- if .Values.replica.extraFlags }} + {{- range .Values.replica.extraFlags }} + ARGS+=({{ . | quote }}) + {{- end }} + {{- end }} + + {{- if .Values.replica.preExecCmds }} + {{- .Values.replica.preExecCmds | nindent 4 }} + {{- end }} + + {{- if .Values.replica.command }} + exec {{ .Values.replica.command }} "${ARGS[@]}" + {{- else }} + exec valkey-server "${ARGS[@]}" + {{- end }} + + start-sentinel.sh: | + #!/bin/bash + + . /opt/bitnami/scripts/libos.sh + . /opt/bitnami/scripts/libvalidations.sh + . /opt/bitnami/scripts/libfile.sh + + HEADLESS_SERVICE="{{ template "common.names.fullname" . }}-headless.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}" + VALKEY_SERVICE="{{ template "common.names.fullname" . }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}" + + get_port() { + hostname="$1" + type="$2" + + port_var=$(echo "${hostname^^}_SERVICE_PORT_$type" | sed "s/-/_/g") + port=${!port_var} + + if [ -z "$port" ]; then + case $type in + "SENTINEL") + echo {{ .Values.sentinel.containerPorts.sentinel }} + ;; + "VALKEY") + echo {{ .Values.primary.containerPorts.valkey }} + ;; + esac + else + echo $port + fi + } + + get_full_hostname() { + hostname="$1" + + {{- if .Values.useExternalDNS.enabled }} + full_hostname="${hostname}.{{- include "valkey.externalDNS.suffix" . }}" + {{- else if eq .Values.sentinel.service.type "NodePort" }} + full_hostname="${hostname}.{{- include "common.names.namespace" . }}" + {{- else }} + full_hostname="${hostname}.${HEADLESS_SERVICE}" + {{- end }} + + {{- if .Values.useHostnames }} + echo "${full_hostname}" + {{- else }} + retry_count=0 + until getent hosts "${full_hostname}" | awk '{ print $1; exit }' | grep .; do + if [[ $retry_count -lt {{ .Values.nameResolutionThreshold }} ]]; then + sleep {{ .Values.nameResolutionTimeout }} + else + error "IP address for ${full_hostname} not found" + exit 1 + fi + ((retry_count++)) + done + {{- end }} + } + + SERVPORT=$(get_port "$HOSTNAME" "SENTINEL") + VALKEYPORT=$(get_port "$HOSTNAME" "VALKEY") + SENTINEL_SERVICE_PORT=$(get_port "{{ include "common.names.fullname" . }}" "SENTINEL") + + sentinel_conf_set() { + local -r key="${1:?missing key}" + local value="${2:-}" + + # Sanitize inputs + value="${value//\\/\\\\}" + value="${value//&/\\&}" + value="${value//\?/\\?}" + [[ "$value" = "" ]] && value="\"$value\"" + + replace_in_file "/opt/bitnami/valkey-sentinel/etc/prepare-sentinel.conf" "^#*\s*${key} .*" "${key} ${value}" false + } + sentinel_conf_add() { + echo $'\n'"$@" >> "/opt/bitnami/valkey-sentinel/etc/prepare-sentinel.conf" + } + host_id() { + echo "$1" | openssl sha1 | awk '{print $2}' + } + get_sentinel_primary_info() { + if is_boolean_yes "$VALKEY_SENTINEL_TLS_ENABLED"; then + sentinel_info_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$VALKEY_PASSWORD" {{ end }}timeout {{ .Values.sentinel.getPrimaryTimeout }} valkey-cli -h $VALKEY_SERVICE -p $SENTINEL_SERVICE_PORT --tls --cert ${VALKEY_SENTINEL_TLS_CERT_FILE} --key ${VALKEY_SENTINEL_TLS_KEY_FILE} --cacert ${VALKEY_SENTINEL_TLS_CA_FILE} sentinel get-primary-addr-by-name {{ .Values.sentinel.primarySet }}" + else + sentinel_info_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$VALKEY_PASSWORD" {{ end }}timeout {{ .Values.sentinel.getPrimaryTimeout }} valkey-cli -h $VALKEY_SERVICE -p $SENTINEL_SERVICE_PORT sentinel get-primary-addr-by-name {{ .Values.sentinel.primarySet }}" + fi + info "about to run the command: $sentinel_info_command" + retry_while "eval $sentinel_info_command" 2 5 + } + + [[ -f $VALKEY_PASSWORD_FILE ]] && export VALKEY_PASSWORD="$(< "${VALKEY_PASSWORD_FILE}")" + + primary_in_persisted_conf="$(get_full_hostname "$HOSTNAME")" + + if [[ -f /opt/bitnami/valkey-sentinel/etc/sentinel.conf ]]; then + primary_in_persisted_conf="$(awk '/monitor/ {print $4}' /opt/bitnami/valkey-sentinel/etc/sentinel.conf)" + info "Found previous primary $primary_in_persisted_conf in /opt/bitnami/valkey-sentinel/etc/sentinel.conf" + debug "$(cat /opt/bitnami/valkey-sentinel/etc/sentinel.conf | grep monitor)" + fi + VALKEY_SENTINEL_INFO=($(get_sentinel_primary_info)) + if [ "$?" -eq "0" ]; then + # current primary's host and port obtained from other Sentinel + info "printing VALKEY_SENTINEL_INFO=(${VALKEY_SENTINEL_INFO[0]},${VALKEY_SENTINEL_INFO[1]})" + VALKEY_PRIMARY_HOST=${VALKEY_SENTINEL_INFO[0]} + VALKEY_PRIMARY_PORT_NUMBER=${VALKEY_SENTINEL_INFO[1]} + else + VALKEY_PRIMARY_HOST="$primary_in_persisted_conf" + VALKEY_PRIMARY_PORT_NUMBER="$VALKEYPORT" + fi + if [[ "$VALKEY_PRIMARY_HOST" == "$(get_full_hostname "$HOSTNAME")" ]]; then + export VALKEY_REPLICATION_MODE="primary" + else + export VALKEY_REPLICATION_MODE="replica" + fi + + {{- if .Values.sentinel.service.createPrimary }} + if [[ "${VALKEY_REPLICATION_MODE}" == "primary" ]]; then + # Add isPrimary label to primary node for primary service + echo "${VALKEY_PRIMARY_HOST/.*}" > /etc/shared/current + fi + {{- end }} + + if [[ -n "$VALKEY_EXTERNAL_PRIMARY_HOST" ]]; then + VALKEY_PRIMARY_HOST="$VALKEY_EXTERNAL_PRIMARY_HOST" + VALKEY_PRIMARY_PORT_NUMBER="${VALKEY_EXTERNAL_PRIMARY_PORT}" + fi + + # To prevent incomplete configuration and as the valkey container accesses /opt/bitnami/valkey-sentinel/etc/sentinel.conf + # as well, prepare the new config in `prepare-sentinel.conf` and move it atomically to the ultimate destination when it is complete. + cp /opt/bitnami/valkey-sentinel/mounted-etc/sentinel.conf /opt/bitnami/valkey-sentinel/etc/prepare-sentinel.conf + {{- if .Values.auth.enabled }} + printf "\nsentinel auth-pass %s %s" "{{ .Values.sentinel.primarySet }}" "$VALKEY_PASSWORD" >> /opt/bitnami/valkey-sentinel/etc/prepare-sentinel.conf + {{- if and .Values.auth.enabled .Values.auth.sentinel }} + printf "\nrequirepass %s" "$VALKEY_PASSWORD" >> /opt/bitnami/valkey-sentinel/etc/prepare-sentinel.conf + {{- end }} + {{- end }} + printf "\nsentinel myid %s" "$(host_id "$HOSTNAME")" >> /opt/bitnami/valkey-sentinel/etc/prepare-sentinel.conf + + if [[ -z "$VALKEY_PRIMARY_HOST" ]] || [[ -z "$VALKEY_PRIMARY_PORT_NUMBER" ]] + then + # Prevent incorrect configuration to be written to sentinel.conf + error "Valkey primary host is configured incorrectly (host: $VALKEY_PRIMARY_HOST, port: $VALKEY_PRIMARY_PORT_NUMBER)" + exit 1 + fi + + sentinel_conf_set "sentinel monitor" "{{ .Values.sentinel.primarySet }} "$VALKEY_PRIMARY_HOST" "$VALKEY_PRIMARY_PORT_NUMBER" {{ .Values.sentinel.quorum }}" + + add_known_sentinel() { + hostname="$1" + ip="$2" + + if [[ -n "$hostname" && -n "$ip" && "$hostname" != "$HOSTNAME" ]]; then + sentinel_conf_add "sentinel known-sentinel {{ .Values.sentinel.primarySet }} $(get_full_hostname "$hostname") $(get_port "$hostname" "SENTINEL") $(host_id "$hostname")" + fi + } + add_known_replica() { + hostname="$1" + ip="$2" + + if [[ -n "$ip" && "$(get_full_hostname "$hostname")" != "$VALKEY_PRIMARY_HOST" ]]; then + sentinel_conf_add "sentinel known-replica {{ .Values.sentinel.primarySet }} $(get_full_hostname "$hostname") $(get_port "$hostname" "VALKEY")" + fi + } + + # Add available hosts on the network as known replicas & sentinels + for node in $(seq 0 $(({{ .Values.replica.replicaCount }}-1))); do + hostname="{{ template "common.names.fullname" . }}-node-$node" + ip="$(getent hosts "$hostname.$HEADLESS_SERVICE" | awk '{ print $1 }')" + add_known_sentinel "$hostname" "$ip" + add_known_replica "$hostname" "$ip" + done + + echo "" >> /opt/bitnami/valkey-sentinel/etc/prepare-sentinel.conf + {{- if not (contains "sentinel announce-hostnames" .Values.sentinel.configuration) }} + echo "sentinel announce-hostnames yes" >> /opt/bitnami/valkey-sentinel/etc/prepare-sentinel.conf + {{- end }} + {{- if not (contains "sentinel resolve-hostnames" .Values.sentinel.configuration) }} + echo "sentinel resolve-hostnames yes" >> /opt/bitnami/valkey-sentinel/etc/prepare-sentinel.conf + {{- end }} + {{- if not (contains "sentinel announce-port" .Values.sentinel.configuration) }} + echo "sentinel announce-port $SERVPORT" >> /opt/bitnami/valkey-sentinel/etc/prepare-sentinel.conf + {{- end }} + {{- if not (contains "sentinel announce-ip" .Values.sentinel.configuration) }} + echo "sentinel announce-ip $(get_full_hostname "$HOSTNAME")" >> /opt/bitnami/valkey-sentinel/etc/prepare-sentinel.conf + {{- end }} + + {{- if .Values.tls.enabled }} + ARGS=("--port" "0") + ARGS+=("--tls-port" "${VALKEY_SENTINEL_TLS_PORT_NUMBER}") + ARGS+=("--tls-cert-file" "${VALKEY_SENTINEL_TLS_CERT_FILE}") + ARGS+=("--tls-key-file" "${VALKEY_SENTINEL_TLS_KEY_FILE}") + ARGS+=("--tls-ca-cert-file" "${VALKEY_SENTINEL_TLS_CA_FILE}") + ARGS+=("--tls-replication" "yes") + ARGS+=("--tls-auth-clients" "${VALKEY_SENTINEL_TLS_AUTH_CLIENTS}") + {{- if .Values.tls.dhParamsFilename }} + ARGS+=("--tls-dh-params-file" "${VALKEY_SENTINEL_TLS_DH_PARAMS_FILE}") + {{- end }} + {{- end }} + {{- if .Values.sentinel.preExecCmds }} + {{ .Values.sentinel.preExecCmds | nindent 4 }} + {{- end }} + mv /opt/bitnami/valkey-sentinel/etc/prepare-sentinel.conf /opt/bitnami/valkey-sentinel/etc/sentinel.conf + exec valkey-server /opt/bitnami/valkey-sentinel/etc/sentinel.conf {{- if .Values.tls.enabled }} "${ARGS[@]}" {{- end }} --sentinel + prestop-sentinel.sh: | + #!/bin/bash + + . /opt/bitnami/scripts/libvalidations.sh + . /opt/bitnami/scripts/libos.sh + + HEADLESS_SERVICE="{{ template "common.names.fullname" . }}-headless.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}" + + get_full_hostname() { + hostname="$1" + + {{- if .Values.useExternalDNS.enabled }} + full_hostname="${hostname}.{{- include "valkey.externalDNS.suffix" . }}" + {{- else if eq .Values.sentinel.service.type "NodePort" }} + full_hostname="${hostname}.{{- include "common.names.namespace" . }}" + {{- else }} + full_hostname="${hostname}.${HEADLESS_SERVICE}" + {{- end }} + + {{- if .Values.useHostnames }} + echo "${full_hostname}" + {{- else }} + retry_count=0 + until getent hosts "${full_hostname}" | awk '{ print $1; exit }' | grep .; do + if [[ $retry_count -lt {{ .Values.nameResolutionThreshold }} ]]; then + sleep {{ .Values.nameResolutionTimeout }} + else + error "IP address for ${full_hostname} not found" + exit 1 + fi + ((retry_count++)) + done + {{- end }} + } + + run_sentinel_command() { + if is_boolean_yes "$VALKEY_SENTINEL_TLS_ENABLED"; then + valkey-cli -h "$VALKEY_SERVICE" -p "$VALKEY_SENTINEL_TLS_PORT_NUMBER" --tls --cert "$VALKEY_SENTINEL_TLS_CERT_FILE" --key "$VALKEY_SENTINEL_TLS_KEY_FILE" --cacert "$VALKEY_SENTINEL_TLS_CA_FILE" sentinel "$@" + else + valkey-cli -h "$VALKEY_SERVICE" -p "$VALKEY_SENTINEL_PORT" sentinel "$@" + fi + } + sentinel_failover_finished() { + VALKEY_SENTINEL_INFO=($(run_sentinel_command get-primary-addr-by-name "{{ .Values.sentinel.primarySet }}")) + VALKEY_PRIMARY_HOST="${VALKEY_SENTINEL_INFO[0]}" + [[ "$VALKEY_PRIMARY_HOST" != "$(get_full_hostname $HOSTNAME)" ]] + } + + VALKEY_SERVICE="{{ include "common.names.fullname" . }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}" + + {{ if .Values.auth.sentinel -}} + # valkey-cli automatically consumes credentials from the REDISCLI_AUTH variable + [[ -n "$VALKEY_PASSWORD" ]] && export REDISCLI_AUTH="$VALKEY_PASSWORD" + [[ -f "$VALKEY_PASSWORD_FILE" ]] && export REDISCLI_AUTH="$(< "${VALKEY_PASSWORD_FILE}")" + {{- end }} + + if ! sentinel_failover_finished; then + echo "I am the primary pod and you are stopping me. Starting sentinel failover" + if retry_while "sentinel_failover_finished" "{{ sub .Values.sentinel.terminationGracePeriodSeconds 10 }}" 1; then + echo "Primary has been successfuly failed over to a different pod." + exit 0 + else + echo "Primary failover failed" + exit 1 + fi + else + exit 0 + fi + prestop-valkey.sh: | + #!/bin/bash + + . /opt/bitnami/scripts/libvalidations.sh + . /opt/bitnami/scripts/libos.sh + + run_valkey_command() { + if is_boolean_yes "$VALKEY_TLS_ENABLED"; then + valkey-cli -h 127.0.0.1 -p "$VALKEY_TLS_PORT" --tls --cert "$VALKEY_TLS_CERT_FILE" --key "$VALKEY_TLS_KEY_FILE" --cacert "$VALKEY_TLS_CA_FILE" "$@" + else + valkey-cli -h 127.0.0.1 -p "$VALKEY_PORT" "$@" + fi + } + is_primary() { + VALKEY_ROLE=$(run_valkey_command role | head -1) + [[ "$VALKEY_ROLE" == "master" ]] + } + + HEADLESS_SERVICE="{{ template "common.names.fullname" . }}-headless.{{- include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}" + + get_full_hostname() { + hostname="$1" + + {{- if .Values.useExternalDNS.enabled }} + full_hostname="${hostname}.{{- include "valkey.externalDNS.suffix" . }}" + {{- else if eq .Values.sentinel.service.type "NodePort" }} + full_hostname="${hostname}.{{- include "common.names.namespace" . }}" + {{- else }} + full_hostname="${hostname}.${HEADLESS_SERVICE}" + {{- end }} + + {{- if .Values.useHostnames }} + echo "${full_hostname}" + {{- else }} + retry_count=0 + until getent hosts "${full_hostname}" | awk '{ print $1; exit }' | grep .; do + if [[ $retry_count -lt {{ .Values.nameResolutionThreshold }} ]]; then + sleep {{ .Values.nameResolutionTimeout }} + else + error "IP address for ${full_hostname} not found" + exit 1 + fi + ((retry_count++)) + done + {{- end }} + } + + run_sentinel_command() { + if is_boolean_yes "$VALKEY_SENTINEL_TLS_ENABLED"; then + {{ .Values.auth.sentinel | ternary "" "env -u REDISCLI_AUTH " -}} valkey-cli -h "$VALKEY_SERVICE" -p "$VALKEY_SENTINEL_TLS_PORT_NUMBER" --tls --cert "$VALKEY_SENTINEL_TLS_CERT_FILE" --key "$VALKEY_SENTINEL_TLS_KEY_FILE" --cacert "$VALKEY_SENTINEL_TLS_CA_FILE" sentinel "$@" + else + {{ .Values.auth.sentinel | ternary "" "env -u REDISCLI_AUTH " -}} valkey-cli -h "$VALKEY_SERVICE" -p "$VALKEY_SENTINEL_PORT" sentinel "$@" + fi + } + sentinel_failover_finished() { + VALKEY_SENTINEL_INFO=($(run_sentinel_command get-primary-addr-by-name "{{ .Values.sentinel.primarySet }}")) + VALKEY_PRIMARY_HOST="${VALKEY_SENTINEL_INFO[0]}" + [[ "$VALKEY_PRIMARY_HOST" != "$(get_full_hostname $HOSTNAME)" ]] + } + + VALKEY_SERVICE="{{ include "common.names.fullname" . }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}" + + # valkey-cli automatically consumes credentials from the REDISCLI_AUTH variable + [[ -n "$VALKEY_PASSWORD" ]] && export REDISCLI_AUTH="$VALKEY_PASSWORD" + [[ -f "$VALKEY_PASSWORD_FILE" ]] && export REDISCLI_AUTH="$(< "${VALKEY_PASSWORD_FILE}")" + + + if is_primary && ! sentinel_failover_finished; then + echo "I am the primary pod and you are stopping me. Pausing client connections." + # Pausing client write connections to avoid data loss + run_valkey_command CLIENT PAUSE "{{ mul (add 2 (sub .Values.sentinel.terminationGracePeriodSeconds 10)) 1000 }}" WRITE + + echo "Issuing failover" + # if I am the primary, issue a command to failover once + run_sentinel_command failover "{{ .Values.sentinel.primarySet }}" + + {{- if .Values.sentinel.valkeyShutdownWaitFailover }} + echo "Waiting for sentinel to complete failover for up to {{ sub .Values.sentinel.terminationGracePeriodSeconds 10 }}s" + retry_while "sentinel_failover_finished" "{{ sub .Values.sentinel.terminationGracePeriodSeconds 10 }}" 1 + {{- end }} + else + exit 0 + fi + + {{- if .Values.sentinel.service.createPrimary}} + push-primary-label.sh: | + #!/bin/bash + # https://download.valkey.io/valkey-stable/sentinel.conf + + echo "${6/.*}" > /etc/shared/current + echo "${4/.*}" > /etc/shared/previous + {{- end }} +{{- else }} + start-primary.sh: | + #!/bin/bash + + [[ -f $VALKEY_PASSWORD_FILE ]] && export VALKEY_PASSWORD="$(< "${VALKEY_PASSWORD_FILE}")" + {{- if and .Values.primary.containerSecurityContext.runAsUser (eq (.Values.primary.containerSecurityContext.runAsUser | int) 0) }} + useradd valkey + chown -R valkey {{ .Values.primary.persistence.path }} + {{- end }} + if [[ -f /opt/bitnami/valkey/mounted-etc/primary.conf ]];then + cp /opt/bitnami/valkey/mounted-etc/primary.conf /opt/bitnami/valkey/etc/primary.conf + fi + if [[ -f /opt/bitnami/valkey/mounted-etc/valkey.conf ]];then + cp /opt/bitnami/valkey/mounted-etc/valkey.conf /opt/bitnami/valkey/etc/valkey.conf + fi + {{- if .Values.tls.enabled }} + ARGS=("--port" "0") + ARGS+=("--tls-port" "${VALKEY_TLS_PORT}") + ARGS+=("--tls-cert-file" "${VALKEY_TLS_CERT_FILE}") + ARGS+=("--tls-key-file" "${VALKEY_TLS_KEY_FILE}") + ARGS+=("--tls-ca-cert-file" "${VALKEY_TLS_CA_FILE}") + ARGS+=("--tls-auth-clients" "${VALKEY_TLS_AUTH_CLIENTS}") + {{- if .Values.tls.dhParamsFilename }} + ARGS+=("--tls-dh-params-file" "${VALKEY_TLS_DH_PARAMS_FILE}") + {{- end }} + {{- else }} + ARGS=("--port" "${VALKEY_PORT}") + {{- end }} + {{- if .Values.auth.enabled }} + ARGS+=("--requirepass" "${VALKEY_PASSWORD}") + ARGS+=("--primaryauth" "${VALKEY_PASSWORD}") + {{- else }} + ARGS+=("--protected-mode" "no") + {{- end }} + ARGS+=("--include" "/opt/bitnami/valkey/etc/valkey.conf") + ARGS+=("--include" "/opt/bitnami/valkey/etc/primary.conf") + {{- if .Values.primary.extraFlags }} + {{- range .Values.primary.extraFlags }} + ARGS+=({{ . | quote }}) + {{- end }} + {{- end }} + {{- if .Values.primary.preExecCmds }} + {{ .Values.primary.preExecCmds | nindent 4 }} + {{- end }} + {{- if .Values.primary.command }} + exec {{ .Values.primary.command }} "${ARGS[@]}" + {{- else }} + exec valkey-server "${ARGS[@]}" + {{- end }} + {{- if eq .Values.architecture "replication" }} + start-replica.sh: | + #!/bin/bash + + get_port() { + hostname="$1" + type="$2" + + port_var=$(echo "${hostname^^}_SERVICE_PORT_$type" | sed "s/-/_/g") + port=${!port_var} + + if [ -z "$port" ]; then + case $type in + "SENTINEL") + echo {{ .Values.sentinel.containerPorts.sentinel }} + ;; + "VALKEY") + echo {{ .Values.primary.containerPorts.valkey }} + ;; + esac + else + echo $port + fi + } + + get_full_hostname() { + hostname="$1" + + {{- if .Values.useExternalDNS.enabled }} + full_hostname="${hostname}.{{- include "valkey.externalDNS.suffix" . }}" + {{- else if eq .Values.sentinel.service.type "NodePort" }} + full_hostname="${hostname}.{{- include "common.names.namespace" . }}" + {{- else }} + full_hostname="${hostname}.${HEADLESS_SERVICE}" + {{- end }} + + {{- if .Values.useHostnames }} + echo "${full_hostname}" + {{- else }} + retry_count=0 + until getent hosts "${full_hostname}" | awk '{ print $1; exit }' | grep .; do + if [[ $retry_count -lt {{ .Values.nameResolutionThreshold }} ]]; then + sleep {{ .Values.nameResolutionTimeout }} + else + error "IP address for ${full_hostname} not found" + exit 1 + fi + ((retry_count++)) + done + {{- end }} + } + + VALKEYPORT=$(get_port "$HOSTNAME" "VALKEY") + HEADLESS_SERVICE="{{ template "common.names.fullname" . }}-headless.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}" + + [[ -f $VALKEY_PASSWORD_FILE ]] && export VALKEY_PASSWORD="$(< "${VALKEY_PASSWORD_FILE}")" + [[ -f $VALKEY_PRIMARY_PASSWORD_FILE ]] && export VALKEY_PRIMARY_PASSWORD="$(< "${VALKEY_PRIMARY_PASSWORD_FILE}")" + {{- if and .Values.replica.containerSecurityContext.runAsUser (eq (.Values.replica.containerSecurityContext.runAsUser | int) 0) }} + useradd valkey + chown -R valkey {{ .Values.replica.persistence.path }} + {{- end }} + if [[ -f /opt/bitnami/valkey/mounted-etc/replica.conf ]];then + cp /opt/bitnami/valkey/mounted-etc/replica.conf /opt/bitnami/valkey/etc/replica.conf + fi + if [[ -f /opt/bitnami/valkey/mounted-etc/valkey.conf ]];then + cp /opt/bitnami/valkey/mounted-etc/valkey.conf /opt/bitnami/valkey/etc/valkey.conf + fi + + echo "" >> /opt/bitnami/valkey/etc/replica.conf + echo "replica-announce-port $VALKEYPORT" >> /opt/bitnami/valkey/etc/replica.conf + echo "replica-announce-ip $(get_full_hostname "$HOSTNAME")" >> /opt/bitnami/valkey/etc/replica.conf + + {{- if .Values.tls.enabled }} + ARGS=("--port" "0") + ARGS+=("--tls-port" "${VALKEY_TLS_PORT}") + ARGS+=("--tls-cert-file" "${VALKEY_TLS_CERT_FILE}") + ARGS+=("--tls-key-file" "${VALKEY_TLS_KEY_FILE}") + ARGS+=("--tls-ca-cert-file" "${VALKEY_TLS_CA_FILE}") + ARGS+=("--tls-auth-clients" "${VALKEY_TLS_AUTH_CLIENTS}") + ARGS+=("--tls-replication" "yes") + {{- if .Values.tls.dhParamsFilename }} + ARGS+=("--tls-dh-params-file" "${VALKEY_TLS_DH_PARAMS_FILE}") + {{- end }} + {{- else }} + ARGS=("--port" "${VALKEY_PORT}") + {{- end }} + ARGS+=("--replicaof" "${VALKEY_PRIMARY_HOST}" "${VALKEY_PRIMARY_PORT_NUMBER}") + {{- if .Values.auth.enabled }} + ARGS+=("--requirepass" "${VALKEY_PASSWORD}") + ARGS+=("--primaryauth" "${VALKEY_PRIMARY_PASSWORD}") + {{- else }} + ARGS+=("--protected-mode" "no") + {{- end }} + ARGS+=("--include" "/opt/bitnami/valkey/etc/valkey.conf") + ARGS+=("--include" "/opt/bitnami/valkey/etc/replica.conf") + {{- if .Values.replica.extraFlags }} + {{- range .Values.replica.extraFlags }} + ARGS+=({{ . | quote }}) + {{- end }} + {{- end }} + {{- if .Values.replica.preExecCmds }} + {{ .Values.replica.preExecCmds | nindent 4 }} + {{- end }} + {{- if .Values.replica.command }} + exec {{ .Values.replica.command }} "${ARGS[@]}" + {{- else }} + exec valkey-server "${ARGS[@]}" + {{- end }} + {{- end }} +{{- end }} +--- +{{- if .Values.sentinel.service.createPrimary}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-kubectl-scripts" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + update-primary-label.sh: | + #!/bin/bash + while true; do + while [ ! -f "/etc/shared/current" ]; do + sleep 1 + done + echo "new primary elected, updating label(s)..." + kubectl label pod --field-selector metadata.name="$(< "/etc/shared/current")" isPrimary="true" --overwrite + if [ -f /etc/shared/previous ]; then + kubectl label pod --field-selector metadata.name="$(< "/etc/shared/previous")" isPrimary="false" --overwrite + fi + rm "/etc/shared/current" "/etc/shared/previous" + done +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/secret-svcbind.yaml b/backing-services/gitea/charts/valkey/templates/secret-svcbind.yaml new file mode 100644 index 0000000..5609e04 --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/secret-svcbind.yaml @@ -0,0 +1,38 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.serviceBindings.enabled }} +{{- $host := include "common.names.fullname" . }} +{{- if not .Values.sentinel.enabled }} +{{- $host = printf "%s-primary" (include "common.names.fullname" .) }} +{{- end }} +{{- $port := print .Values.primary.service.ports.valkey }} +{{- if .Values.sentinel.enabled }} +{{- $port = print .Values.sentinel.service.ports.valkey }} +{{- end }} +{{- $password := include "valkey.password" . }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }}-svcbind + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: valkey + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: servicebinding.io/valkey +data: + provider: {{ print "bitnami" | b64enc | quote }} + type: {{ print "valkey" | b64enc | quote }} + host: {{ print $host | b64enc | quote }} + port: {{ print $port | b64enc | quote }} + password: {{ print $password | b64enc | quote }} + {{- if $password }} + uri: {{ printf "valkey://:%s@%s:%s" $password $host $port | b64enc | quote }} + {{- else }} + uri: {{ printf "valkey://%s:%s" $host $port | b64enc | quote }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/secret.yaml b/backing-services/gitea/charts/valkey/templates/secret.yaml new file mode 100644 index 0000000..9145bf5 --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/secret.yaml @@ -0,0 +1,26 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.auth.enabled (not .Values.auth.existingSecret) (or .Values.auth.usePasswordFileFromSecret (not .Values.auth.usePasswordFiles)) -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: valkey + {{- if or .Values.secretAnnotations .Values.commonAnnotations }} + annotations: + {{- if .Values.secretAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.secretAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} +type: Opaque +data: + valkey-password: {{ include "common.secrets.passwords.manage" (dict "secret" (include "common.names.fullname" .) "key" "valkey-password" "providedValues" (list "global.valkey.password" "auth.password") "length" 10 "honorProvidedValues" true "context" $) }} +{{- end -}} diff --git a/backing-services/gitea/charts/valkey/templates/sentinel/hpa.yaml b/backing-services/gitea/charts/valkey/templates/sentinel/hpa.yaml new file mode 100644 index 0000000..1279b42 --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/sentinel/hpa.yaml @@ -0,0 +1,42 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.replica.autoscaling.hpa.enabled .Values.sentinel.enabled }} +apiVersion: {{ include "common.capabilities.hpa.apiVersion" ( dict "context" $ ) }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ printf "%s-node" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: replica + app.kubernetes.io/part-of: valkey + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + scaleTargetRef: + apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} + kind: StatefulSet + name: {{ printf "%s-node" (include "common.names.fullname" .) }} + minReplicas: {{ .Values.replica.autoscaling.hpa.minReplicas }} + maxReplicas: {{ .Values.replica.autoscaling.hpa.maxReplicas }} + metrics: + {{- if .Values.replica.autoscaling.hpa.targetMemory }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.replica.autoscaling.hpa.targetMemory }} + {{- end }} + {{- if .Values.replica.autoscaling.hpa.targetCPU }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.replica.autoscaling.hpa.targetCPU }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/sentinel/node-services.yaml b/backing-services/gitea/charts/valkey/templates/sentinel/node-services.yaml new file mode 100644 index 0000000..2ffeb7c --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/sentinel/node-services.yaml @@ -0,0 +1,68 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replication") .Values.sentinel.enabled (eq .Values.sentinel.service.type "NodePort") (or .Release.IsUpgrade .Values.sentinel.service.nodePorts.valkey ) }} + +{{- range $i := until (int .Values.replica.replicaCount) }} + +{{ $portsmap := (lookup "v1" "ConfigMap" (include "common.names.namespace" $) (printf "%s-%s" ( include "common.names.fullname" $ ) "ports-configmap")).data }} + +{{ $sentinelport := 0}} +{{ $valkeyport := 0}} +{{- if $portsmap }} +{{ $sentinelport = index $portsmap (printf "%s-node-%s-%s" (include "common.names.fullname" $) (toString $i) "sentinel") }} +{{ $valkeyport = index $portsmap (printf "%s-node-%s-%s" (include "common.names.fullname" $) (toString $i) "valkey") }} +{{- else }} +{{- end }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "common.names.fullname" $ }}-node-{{ $i }} + namespace: {{ include "common.names.namespace" $ | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $.Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: node + app.kubernetes.io/part-of: valkey + {{- if or $.Values.commonAnnotations $.Values.sentinel.service.annotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list $.Values.sentinel.service.annotations $.Values.commonAnnotations ) "context" $ ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: NodePort + ports: + - name: sentinel + {{- if $.Values.sentinel.service.nodePorts.sentinel }} + nodePort: {{ (add $.Values.sentinel.service.nodePorts.sentinel $i 1) }} + port: {{ (add $.Values.sentinel.service.nodePorts.sentinel $i 1) }} + {{- else }} + nodePort: {{ $sentinelport }} + port: {{ $sentinelport }} + {{- end }} + protocol: TCP + targetPort: {{ $.Values.sentinel.containerPorts.sentinel }} + - name: valkey + {{- if $.Values.sentinel.service.nodePorts.valkey }} + nodePort: {{ (add $.Values.sentinel.service.nodePorts.valkey $i 1) }} + port: {{ (add $.Values.sentinel.service.nodePorts.valkey $i 1) }} + {{- else }} + nodePort: {{ $valkeyport }} + port: {{ $valkeyport }} + {{- end }} + protocol: TCP + targetPort: {{ $.Values.replica.containerPorts.valkey }} + - name: sentinel-internal + nodePort: null + port: {{ $.Values.sentinel.containerPorts.sentinel }} + protocol: TCP + targetPort: {{ $.Values.sentinel.containerPorts.sentinel }} + - name: valkey-internal + nodePort: null + port: {{ $.Values.replica.containerPorts.valkey }} + protocol: TCP + targetPort: {{ $.Values.replica.containerPorts.valkey }} + selector: + statefulset.kubernetes.io/pod-name: {{ template "common.names.fullname" $ }}-node-{{ $i }} +--- +{{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/sentinel/pdb.yaml b/backing-services/gitea/charts/valkey/templates/sentinel/pdb.yaml new file mode 100644 index 0000000..87bea09 --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/sentinel/pdb.yaml @@ -0,0 +1,27 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} +{{- $pdb := coalesce .Values.pdb .Values.replica.pdb }} +{{- if and (eq .Values.architecture "replication") .Values.sentinel.enabled $pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ printf "%s-node" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: node + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if $pdb.minAvailable }} + minAvailable: {{ $pdb.minAvailable }} + {{- end }} + {{- if or $pdb.maxUnavailable (not $pdb.minAvailable) }} + maxUnavailable: {{ $pdb.maxUnavailable | default 1 }} + {{- end }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: node +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/sentinel/ports-configmap.yaml b/backing-services/gitea/charts/valkey/templates/sentinel/ports-configmap.yaml new file mode 100644 index 0000000..35f95c0 --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/sentinel/ports-configmap.yaml @@ -0,0 +1,103 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replication") .Values.sentinel.enabled (eq .Values.sentinel.service.type "NodePort") (not .Values.sentinel.service.nodePorts.valkey ) }} +{{- /* create a list to keep track of ports we choose to use */}} +{{ $chosenports := (list ) }} + +{{- /* Get list of all used nodeports */}} +{{ $usedports := (list ) }} +{{- range $index, $service := (lookup "v1" "Service" "" "").items }} + {{- range.spec.ports }} + {{- if .nodePort }} + {{- $usedports = (append $usedports .nodePort) }} + {{- end }} + {{- end }} +{{- end }} + +{{- /* +comments that start with # are rendered in the output when you debug, so you can less and search for them +Vars in the comment will be rendered out, so you can check their value this way. +https://helm.sh/docs/chart_best_practices/templates/#comments-yaml-comments-vs-template-comments + +remove the template comments and leave the yaml comments to help debug +*/}} + +{{- /* Sort the list */}} +{{ $usedports = $usedports | sortAlpha }} +#usedports {{ $usedports }} + +{{- /* How many nodeports per service do we want to create, except for the main service which is always two */}} +{{ $numberofPortsPerNodeService := 2 }} + +{{- /* for every nodeport we want, loop though the used ports to get an unused port */}} +{{- range $j := until (int (add (mul (int .Values.replica.replicaCount) $numberofPortsPerNodeService) 2)) }} + {{- /* #j={{ $j }} */}} + {{- $nodeport := (add $j 30000) }} + {{- $nodeportfound := false }} + {{- range $i := $usedports }} + {{- /* #i={{ $i }} + #nodeport={{ $nodeport }} + #usedports={{ $usedports }} */}} + {{- if and (has (toString $nodeport) $usedports) (eq $nodeportfound false) }} + {{- /* nodeport conflicts with in use */}} + {{- $nodeport = (add $nodeport 1) }} + {{- else if and ( has $nodeport $chosenports) (eq $nodeportfound false) }} + {{- /* nodeport already chosen, try another */}} + {{- $nodeport = (add $nodeport 1) }} + {{- else if (eq $nodeportfound false) }} + {{- /* nodeport free to use: not already claimed and not in use */}} + {{- /* select nodeport, and place into usedports */}} + {{- $chosenports = (append $chosenports $nodeport) }} + {{- $nodeportfound = true }} + {{- else }} + {{- /* nodeport has already been chosen and locked in, just work through the rest of the list to get to the next nodeport selection */}} + {{- end }} + {{- end }} + {{- if (eq $nodeportfound false) }} + {{- $chosenports = (append $chosenports $nodeport) }} + {{- end }} + +{{- end }} + +{{- /* print the usedports and chosenports for debugging */}} +#usedports {{ $usedports }} +#chosenports {{ $chosenports }}}} + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "common.names.fullname" . }}-ports-configmap + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: valkey + {{- if .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: +{{ $portsmap := (lookup "v1" "ConfigMap" (include "common.names.namespace" .) (printf "%s-%s" ( include "common.names.fullname" . ) "ports-configmap")).data }} +{{- if $portsmap }} +{{- /* configmap already exists, do not install again */ -}} + {{- range $name, $value := $portsmap }} + "{{ $name }}": "{{ $value }}" + {{- end }} +{{- else }} +{{- /* configmap being set for first time */ -}} + {{- range $index, $port := $chosenports }} + {{- $nodenumber := (floor (div $index 2)) }} + {{- if (eq $index 0) }} + "{{ template "common.names.fullname" $ }}-sentinel": "{{ $port }}" + {{- else if (eq $index 1) }} + "{{ template "common.names.fullname" $ }}-valkey": "{{ $port }}" + {{- else if (eq (mod $index 2) 0) }} + "{{ template "common.names.fullname" $ }}-node-{{ (sub $nodenumber 1) }}-sentinel": "{{ $port }}" + {{- else if (eq (mod $index 2) 1) }} + "{{ template "common.names.fullname" $ }}-node-{{ (sub $nodenumber 1) }}-valkey": "{{ $port }}" + {{- end }} + {{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/sentinel/service.yaml b/backing-services/gitea/charts/valkey/templates/sentinel/service.yaml new file mode 100644 index 0000000..9c25a95 --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/sentinel/service.yaml @@ -0,0 +1,162 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if or .Release.IsUpgrade (ne .Values.sentinel.service.type "NodePort") .Values.sentinel.service.nodePorts.valkey -}} +{{- if and (eq .Values.architecture "replication") .Values.sentinel.enabled }} +{{ $portsmap := (lookup "v1" "ConfigMap" (include "common.names.namespace" .) (printf "%s-%s" ( include "common.names.fullname" . ) "ports-configmap")).data }} + +{{ $sentinelport := 0}} +{{ $valkeyport := 0}} +{{- if $portsmap }} +{{ $sentinelport = index $portsmap (printf "%s-%s" (include "common.names.fullname" $) "sentinel") }} +{{ $valkeyport = index $portsmap (printf "%s-%s" (include "common.names.fullname" $) "valkey") }} +{{- else }} +{{- end }} + +apiVersion: v1 +kind: Service +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: node + app.kubernetes.io/part-of: valkey + {{- if or .Values.sentinel.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.sentinel.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.sentinel.service.type }} + {{- if or (eq .Values.sentinel.service.type "LoadBalancer") (eq .Values.sentinel.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.sentinel.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.sentinel.service.type "LoadBalancer") (not (empty .Values.sentinel.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.sentinel.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.sentinel.service.type "LoadBalancer") .Values.sentinel.service.loadBalancerClass }} + loadBalancerClass: {{ .Values.sentinel.service.loadBalancerClass }} + {{- end }} + {{- if and (eq .Values.sentinel.service.type "LoadBalancer") (not (empty .Values.sentinel.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ toYaml .Values.sentinel.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + {{- if and .Values.sentinel.service.clusterIP (eq .Values.sentinel.service.type "ClusterIP") }} + clusterIP: {{ .Values.sentinel.service.clusterIP }} + {{- end }} + {{- if .Values.sentinel.service.sessionAffinity }} + sessionAffinity: {{ .Values.sentinel.service.sessionAffinity }} + {{- end }} + {{- if .Values.sentinel.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + ports: + - name: tcp-redis + {{- if and (or (eq .Values.sentinel.service.type "NodePort") (eq .Values.sentinel.service.type "LoadBalancer")) .Values.sentinel.service.nodePorts.valkey }} + port: {{ .Values.sentinel.service.nodePorts.valkey }} + {{- else if eq .Values.sentinel.service.type "NodePort" }} + port: {{ $valkeyport }} + {{- else}} + port: {{ .Values.sentinel.service.ports.valkey }} + {{- end }} + targetPort: {{ .Values.replica.containerPorts.valkey }} + {{- if and (or (eq .Values.sentinel.service.type "NodePort") (eq .Values.sentinel.service.type "LoadBalancer")) .Values.sentinel.service.nodePorts.valkey }} + nodePort: {{ .Values.sentinel.service.nodePorts.valkey }} + {{- else if eq .Values.sentinel.service.type "ClusterIP" }} + nodePort: null + {{- else if eq .Values.sentinel.service.type "NodePort" }} + nodePort: {{ $valkeyport }} + {{- end }} + - name: tcp-sentinel + {{- if and (or (eq .Values.sentinel.service.type "NodePort") (eq .Values.sentinel.service.type "LoadBalancer")) .Values.sentinel.service.nodePorts.sentinel }} + port: {{ .Values.sentinel.service.nodePorts.sentinel }} + {{- else if eq .Values.sentinel.service.type "NodePort" }} + port: {{ $sentinelport }} + {{- else }} + port: {{ .Values.sentinel.service.ports.sentinel }} + {{- end }} + targetPort: {{ .Values.sentinel.containerPorts.sentinel }} + {{- if and (or (eq .Values.sentinel.service.type "NodePort") (eq .Values.sentinel.service.type "LoadBalancer")) .Values.sentinel.service.nodePorts.sentinel }} + nodePort: {{ .Values.sentinel.service.nodePorts.sentinel }} + {{- else if eq .Values.sentinel.service.type "ClusterIP" }} + nodePort: null + {{- else if eq .Values.sentinel.service.type "NodePort" }} + nodePort: {{ $sentinelport }} + {{- end }} + {{- if eq .Values.sentinel.service.type "NodePort" }} + - name: sentinel-internal + nodePort: null + port: {{ .Values.sentinel.containerPorts.sentinel }} + protocol: TCP + targetPort: {{ .Values.sentinel.containerPorts.sentinel }} + - name: valkey-internal + nodePort: null + port: {{ .Values.replica.containerPorts.valkey }} + protocol: TCP + targetPort: {{ .Values.replica.containerPorts.valkey }} + {{- end }} + {{- if .Values.sentinel.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.replica.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: node + +{{- if and .Values.sentinel.enabled .Values.sentinel.service.createPrimary}} +--- +apiVersion: v1 +kind: Service +metadata: + name: "{{ template "common.names.fullname" . }}-primary" + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: node + {{- if or .Values.sentinel.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.sentinel.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.sentinel.service.type }} + {{- if or (eq .Values.sentinel.service.type "LoadBalancer") (eq .Values.sentinel.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.sentinel.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.sentinel.service.type "LoadBalancer") (not (empty .Values.sentinel.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.sentinel.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.sentinel.service.type "LoadBalancer") .Values.sentinel.service.loadBalancerClass }} + loadBalancerClass: {{ .Values.sentinel.service.loadBalancerClass }} + {{- end }} + {{- if and (eq .Values.sentinel.service.type "LoadBalancer") (not (empty .Values.sentinel.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ toYaml .Values.sentinel.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + {{- if and .Values.sentinel.service.clusterIP (eq .Values.sentinel.service.type "ClusterIP") }} + clusterIP: {{ .Values.sentinel.service.clusterIP }} + {{- end }} + {{- if .Values.sentinel.service.sessionAffinity }} + sessionAffinity: {{ .Values.sentinel.service.sessionAffinity }} + {{- end }} + {{- if .Values.sentinel.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + ports: + - name: tcp-redis + {{- if and (or (eq .Values.sentinel.service.type "NodePort") (eq .Values.sentinel.service.type "LoadBalancer")) .Values.sentinel.service.nodePorts.valkey }} + port: {{ .Values.sentinel.service.nodePorts.valkey }} + {{- else if eq .Values.sentinel.service.type "NodePort" }} + port: {{ $valkeyport }} + {{- else}} + port: {{ .Values.sentinel.service.ports.valkey }} + {{- end }} + targetPort: {{ .Values.replica.containerPorts.valkey }} + {{- if and (or (eq .Values.sentinel.service.type "NodePort") (eq .Values.sentinel.service.type "LoadBalancer")) .Values.sentinel.service.nodePorts.valkey }} + nodePort: {{ .Values.sentinel.service.nodePorts.valkey }} + {{- else if eq .Values.sentinel.service.type "ClusterIP" }} + nodePort: null + {{- else if eq .Values.sentinel.service.type "NodePort" }} + nodePort: {{ $valkeyport }} + {{- end }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + isPrimary: "true" +{{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/sentinel/statefulset.yaml b/backing-services/gitea/charts/valkey/templates/sentinel/statefulset.yaml new file mode 100644 index 0000000..eeffbfb --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/sentinel/statefulset.yaml @@ -0,0 +1,807 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if or .Release.IsUpgrade (ne .Values.sentinel.service.type "NodePort") .Values.sentinel.service.nodePorts.valkey -}} +{{- if and (eq .Values.architecture "replication") .Values.sentinel.enabled }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ printf "%s-node" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: node + app.kubernetes.io/part-of: valkey + {{- if or .Values.commonAnnotations .Values.sentinel.annotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.sentinel.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.replica.replicaCount }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.replica.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: node + serviceName: {{ printf "%s-headless" (include "common.names.fullname" .) }} + {{- if .Values.replica.updateStrategy }} + updateStrategy: {{- toYaml .Values.replica.updateStrategy | nindent 4 }} + {{- end }} + {{- if .Values.replica.minReadySeconds }} + minReadySeconds: {{ .Values.replica.minReadySeconds }} + {{- end }} + {{- if .Values.replica.podManagementPolicy }} + podManagementPolicy: {{ .Values.replica.podManagementPolicy | quote }} + {{- end }} + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: node + {{- if and .Values.metrics.enabled .Values.metrics.podLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.podLabels "context" $ ) | nindent 8 }} + {{- end }} + annotations: + {{- if (include "valkey.createConfigmap" .) }} + checksum/configmap: {{ pick ( include (print $.Template.BasePath "/configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + {{- end }} + checksum/health: {{ pick ( include (print $.Template.BasePath "/health-configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + checksum/scripts: {{ pick ( include (print $.Template.BasePath "/scripts-configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + checksum/secret: {{ pick ( include (print $.Template.BasePath "/secret.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + {{- if .Values.replica.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.podAnnotations "context" $ ) | nindent 8 }} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.podAnnotations "context" $ ) | nindent 8 }} + {{- end }} + spec: + {{- include "valkey.imagePullSecrets" . | nindent 6 }} + automountServiceAccountToken: {{ .Values.replica.automountServiceAccountToken }} + {{- if .Values.replica.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.replica.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.replica.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + serviceAccountName: {{ template "valkey.serviceAccountName" . }} + {{- if .Values.replica.priorityClassName }} + priorityClassName: {{ .Values.replica.priorityClassName | quote }} + {{- end }} + {{- if .Values.replica.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.replica.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.replica.podAffinityPreset "component" "node" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.replica.podAntiAffinityPreset "component" "node" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.replica.nodeAffinityPreset.type "key" .Values.replica.nodeAffinityPreset.key "values" .Values.replica.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.replica.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.replica.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.replica.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.replica.topologySpreadConstraints "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.shareProcessNamespace }} + shareProcessNamespace: {{ .Values.replica.shareProcessNamespace }} + {{- end }} + {{- if .Values.replica.schedulerName }} + schedulerName: {{ .Values.replica.schedulerName | quote }} + {{- end }} + {{- if .Values.replica.dnsPolicy }} + dnsPolicy: {{ .Values.replica.dnsPolicy }} + {{- end }} + {{- if .Values.replica.dnsConfig }} + dnsConfig: {{- include "common.tplvalues.render" (dict "value" .Values.replica.dnsConfig "context" $) | nindent 8 }} + {{- end }} + enableServiceLinks: {{ .Values.sentinel.enableServiceLinks }} + terminationGracePeriodSeconds: {{ .Values.sentinel.terminationGracePeriodSeconds }} + {{- $needsVolumePermissions := and .Values.volumePermissions.enabled .Values.replica.persistence.enabled .Values.replica.podSecurityContext.enabled .Values.replica.containerSecurityContext.enabled }} + {{- if or .Values.replica.initContainers $needsVolumePermissions }} + initContainers: + {{- if .Values.replica.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if $needsVolumePermissions }} + - name: volume-permissions + image: {{ include "valkey.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + - -ec + - | + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + chown -R `id -u`:`id -G | cut -d " " -f2` {{ .Values.replica.persistence.path }} + {{- else }} + chown -R {{ .Values.replica.containerSecurityContext.runAsUser }}:{{ .Values.replica.podSecurityContext.fsGroup }} {{ .Values.replica.persistence.path }} + {{- end }} + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.containerSecurityContext "runAsUser" | toYaml | nindent 12 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.containerSecurityContext | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- else if ne .Values.volumePermissions.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.volumePermissions.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: valkey-data + mountPath: {{ .Values.replica.persistence.path }} + {{- if .Values.replica.persistence.subPath }} + subPath: {{ .Values.replica.persistence.subPath }} + {{- else if .Values.replica.persistence.subPathExpr }} + subPathExpr: {{ .Values.replica.persistence.subPathExpr }} + {{- end }} + {{- end }} + {{- end }} + containers: + - name: valkey + image: {{ template "valkey.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.replica.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.replica.lifecycleHooks "context" $) | nindent 12 }} + {{- else }} + lifecycle: + preStop: + exec: + command: + - /bin/bash + - -c + - /opt/bitnami/scripts/start-scripts/prestop-valkey.sh + {{- end }} + {{- end }} + {{- if .Values.replica.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.replica.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.replica.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.replica.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.replica.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.replica.args "context" $) | nindent 12 }} + {{- else }} + args: + - -c + - /opt/bitnami/scripts/start-scripts/start-node.sh + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + - name: VALKEY_PRIMARY_PORT_NUMBER + value: {{ .Values.replica.containerPorts.valkey | quote }} + - name: ALLOW_EMPTY_PASSWORD + value: {{ ternary "no" "yes" .Values.auth.enabled | quote }} + {{- if .Values.auth.enabled }} + {{- if .Values.auth.usePasswordFiles }} + - name: VALKEY_PASSWORD_FILE + value: "/opt/bitnami/valkey/secrets/valkey-password" + - name: VALKEY_PRIMARY_PASSWORD_FILE + value: "/opt/bitnami/valkey/secrets/valkey-password" + {{- else }} + - name: VALKEY_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "valkey.secretName" . }} + key: {{ template "valkey.secretPasswordKey" . }} + - name: VALKEY_PRIMARY_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "valkey.secretName" . }} + key: {{ template "valkey.secretPasswordKey" . }} + {{- end }} + {{- end }} + - name: VALKEY_TLS_ENABLED + value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} + {{- if .Values.tls.enabled }} + - name: VALKEY_TLS_PORT + value: {{ .Values.replica.containerPorts.valkey | quote }} + - name: VALKEY_TLS_AUTH_CLIENTS + value: {{ ternary "yes" "no" .Values.tls.authClients | quote }} + - name: VALKEY_TLS_CERT_FILE + value: {{ template "valkey.tlsCert" . }} + - name: VALKEY_TLS_KEY_FILE + value: {{ template "valkey.tlsCertKey" . }} + - name: VALKEY_TLS_CA_FILE + value: {{ template "valkey.tlsCACert" . }} + {{- if .Values.tls.dhParamsFilename }} + - name: VALKEY_TLS_DH_PARAMS_FILE + value: {{ template "valkey.tlsDHParams" . }} + {{- end }} + {{- else }} + - name: VALKEY_PORT + value: {{ .Values.replica.containerPorts.valkey | quote }} + {{- end }} + - name: VALKEY_SENTINEL_TLS_ENABLED + value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} + {{- if .Values.tls.enabled }} + - name: VALKEY_SENTINEL_TLS_PORT_NUMBER + value: {{ .Values.sentinel.containerPorts.sentinel | quote }} + - name: VALKEY_SENTINEL_TLS_AUTH_CLIENTS + value: {{ ternary "yes" "no" .Values.tls.authClients | quote }} + - name: VALKEY_SENTINEL_TLS_CERT_FILE + value: {{ template "valkey.tlsCert" . }} + - name: VALKEY_SENTINEL_TLS_KEY_FILE + value: {{ template "valkey.tlsCertKey" . }} + - name: VALKEY_SENTINEL_TLS_CA_FILE + value: {{ template "valkey.tlsCACert" . }} + {{- if .Values.tls.dhParamsFilename }} + - name: VALKEY_SENTINEL_TLS_DH_PARAMS_FILE + value: {{ template "valkey.tlsDHParams" . }} + {{- end }} + {{- else }} + - name: VALKEY_SENTINEL_PORT + value: {{ .Values.sentinel.containerPorts.sentinel | quote }} + {{- end }} + - name: VALKEY_DATA_DIR + value: {{ .Values.replica.persistence.path }} + {{- if .Values.replica.externalPrimary.enabled }} + - name: VALKEY_EXTERNAL_PRIMARY_HOST + value: {{ .Values.replica.externalPrimary.host | quote }} + - name: VALKEY_EXTERNAL_PRIMARY_PORT + value: {{ .Values.replica.externalPrimary.port | quote }} + {{- end }} + {{- if .Values.replica.extraEnvVars }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.extraEnvVars "context" $ ) | nindent 12 }} + {{- end }} + {{- if or .Values.replica.extraEnvVarsCM .Values.replica.extraEnvVarsSecret }} + envFrom: + {{- if .Values.replica.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.replica.extraEnvVarsCM }} + {{- end }} + {{- if .Values.replica.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.replica.extraEnvVarsSecret }} + {{- end }} + {{- end }} + ports: + - name: valkey + containerPort: {{ .Values.replica.containerPorts.valkey }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.replica.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.replica.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.replica.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.replica.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - sh + - -c + - /health/ping_liveness_local.sh {{ .Values.replica.livenessProbe.timeoutSeconds }} + {{- end }} + {{- if .Values.replica.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.replica.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.replica.livenessProbe.enabled }} + livenessProbe: + initialDelaySeconds: {{ .Values.replica.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.replica.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.replica.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.replica.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.replica.livenessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_liveness_local.sh {{ .Values.replica.livenessProbe.timeoutSeconds }} + {{- end }} + {{- if .Values.replica.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.replica.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.replica.readinessProbe.enabled }} + readinessProbe: + initialDelaySeconds: {{ .Values.replica.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.replica.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.replica.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.replica.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.replica.readinessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_readiness_local.sh {{ .Values.replica.readinessProbe.timeoutSeconds }} + {{- end }} + {{- end }} + {{- if .Values.replica.resources }} + resources: {{- toYaml .Values.replica.resources | nindent 12 }} + {{- else if ne .Values.replica.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.replica.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: start-scripts + mountPath: /opt/bitnami/scripts/start-scripts + - name: health + mountPath: /health + - name: sentinel-data + mountPath: /opt/bitnami/valkey-sentinel/etc + {{- if and .Values.auth.enabled .Values.auth.usePasswordFiles }} + - name: valkey-password + mountPath: /opt/bitnami/valkey/secrets/ + {{- end }} + - name: valkey-data + mountPath: {{ .Values.replica.persistence.path }} + {{- if .Values.replica.persistence.subPath }} + subPath: {{ .Values.replica.persistence.subPath }} + {{- else if .Values.replica.persistence.subPathExpr }} + subPathExpr: {{ .Values.replica.persistence.subPathExpr }} + {{- end }} + - name: config + mountPath: /opt/bitnami/valkey/mounted-etc + - name: empty-dir + mountPath: /opt/bitnami/valkey/etc + subPath: app-conf-dir + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if .Values.tls.enabled }} + - name: valkey-certificates + mountPath: /opt/bitnami/valkey/certs + readOnly: true + {{- end }} + {{- if .Values.replica.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + - name: sentinel + image: {{ template "valkey.sentinel.image" . }} + imagePullPolicy: {{ .Values.sentinel.image.pullPolicy | quote }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.sentinel.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.lifecycleHooks "context" $) | nindent 12 }} + {{- else }} + lifecycle: + preStop: + exec: + command: + - /bin/bash + - -c + - /opt/bitnami/scripts/start-scripts/prestop-sentinel.sh + {{- end }} + {{- end }} + {{- if .Values.sentinel.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.sentinel.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.sentinel.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.sentinel.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.args "context" $) | nindent 12 }} + {{- else }} + args: + - -c + - /opt/bitnami/scripts/start-scripts/start-sentinel.sh + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.sentinel.image.debug .Values.diagnosticMode.enabled) | quote }} + {{- if .Values.auth.enabled }} + {{- if .Values.auth.usePasswordFiles }} + - name: VALKEY_PASSWORD_FILE + value: "/opt/bitnami/valkey/secrets/valkey-password" + {{- else }} + - name: VALKEY_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "valkey.secretName" . }} + key: {{ template "valkey.secretPasswordKey" . }} + {{- end }} + {{- else }} + - name: ALLOW_EMPTY_PASSWORD + value: "yes" + {{- end }} + - name: VALKEY_SENTINEL_TLS_ENABLED + value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} + {{- if .Values.tls.enabled }} + - name: VALKEY_SENTINEL_TLS_PORT_NUMBER + value: {{ .Values.sentinel.containerPorts.sentinel | quote }} + - name: VALKEY_SENTINEL_TLS_AUTH_CLIENTS + value: {{ ternary "yes" "no" .Values.tls.authClients | quote }} + - name: VALKEY_SENTINEL_TLS_CERT_FILE + value: {{ template "valkey.tlsCert" . }} + - name: VALKEY_SENTINEL_TLS_KEY_FILE + value: {{ template "valkey.tlsCertKey" . }} + - name: VALKEY_SENTINEL_TLS_CA_FILE + value: {{ template "valkey.tlsCACert" . }} + {{- if .Values.tls.dhParamsFilename }} + - name: VALKEY_SENTINEL_TLS_DH_PARAMS_FILE + value: {{ template "valkey.tlsDHParams" . }} + {{- end }} + {{- else }} + - name: VALKEY_SENTINEL_PORT + value: {{ .Values.sentinel.containerPorts.sentinel | quote }} + {{- end }} + {{- if .Values.sentinel.externalPrimary.enabled }} + - name: VALKEY_EXTERNAL_PRIMARY_HOST + value: {{ .Values.sentinel.externalPrimary.host | quote }} + - name: VALKEY_EXTERNAL_PRIMARY_PORT + value: {{ .Values.sentinel.externalPrimary.port | quote }} + {{- end }} + {{- if .Values.sentinel.extraEnvVars }} + {{- include "common.tplvalues.render" ( dict "value" .Values.sentinel.extraEnvVars "context" $ ) | nindent 12 }} + {{- end }} + {{- if or .Values.sentinel.extraEnvVarsCM .Values.sentinel.extraEnvVarsSecret }} + envFrom: + {{- if .Values.sentinel.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.sentinel.extraEnvVarsCM }} + {{- end }} + {{- if .Values.sentinel.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.sentinel.extraEnvVarsSecret }} + {{- end }} + {{- end }} + ports: + - name: valkey-sentinel + containerPort: {{ .Values.sentinel.containerPorts.sentinel }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.sentinel.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.sentinel.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.sentinel.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - sh + - -c + - /health/ping_sentinel.sh {{ .Values.sentinel.livenessProbe.timeoutSeconds }} + {{- end }} + {{- if .Values.sentinel.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.sentinel.livenessProbe.enabled }} + livenessProbe: + initialDelaySeconds: {{ .Values.sentinel.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.sentinel.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.sentinel.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.sentinel.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.sentinel.livenessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_sentinel.sh {{ .Values.sentinel.livenessProbe.timeoutSeconds }} + {{- end }} + {{- end }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.sentinel.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.sentinel.readinessProbe.enabled }} + readinessProbe: + initialDelaySeconds: {{ .Values.sentinel.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.sentinel.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.sentinel.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.sentinel.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.sentinel.readinessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_sentinel.sh {{ .Values.sentinel.readinessProbe.timeoutSeconds }} + {{- end }} + {{- end }} + {{- if .Values.sentinel.resources }} + resources: {{- toYaml .Values.sentinel.resources | nindent 12 }} + {{- else if ne .Values.sentinel.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.sentinel.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: start-scripts + mountPath: /opt/bitnami/scripts/start-scripts + - name: health + mountPath: /health + {{- if .Values.sentinel.service.createPrimary}} + - name: kubectl-shared + mountPath: /etc/shared + {{- end }} + - name: sentinel-data + mountPath: /opt/bitnami/valkey-sentinel/etc + {{- if and .Values.auth.enabled .Values.auth.usePasswordFiles }} + - name: valkey-password + mountPath: /opt/bitnami/valkey/secrets/ + {{- end }} + - name: valkey-data + mountPath: {{ .Values.replica.persistence.path }} + {{- if .Values.replica.persistence.subPath }} + subPath: {{ .Values.replica.persistence.subPath }} + {{- else if .Values.replica.persistence.subPathExpr }} + subPathExpr: {{ .Values.replica.persistence.subPathExpr }} + {{- end }} + - name: config + mountPath: /opt/bitnami/valkey-sentinel/mounted-etc + {{- if .Values.tls.enabled }} + - name: valkey-certificates + mountPath: /opt/bitnami/valkey/certs + readOnly: true + {{- end }} + {{- if .Values.sentinel.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.sentinel.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ template "valkey.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.metrics.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.metrics.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -c + - | + {{- if and .Values.auth.enabled .Values.auth.usePasswordFiles }} + export REDIS_PASSWORD="$(< $REDIS_PASSWORD_FILE)" + {{- end }} + redis_exporter{{- range $key, $value := .Values.metrics.extraArgs }} --{{ $key }}={{ $value }}{{- end }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- end }} + env: + - name: REDIS_ALIAS + value: {{ template "common.names.fullname" . }} + - name: REDIS_EXPORTER_WEB_LISTEN_ADDRESS + value: {{ printf ":%v" .Values.metrics.containerPorts.http }} + {{- if .Values.auth.enabled }} + - name: REDIS_USER + value: default + {{- if .Values.auth.usePasswordFiles }} + - name: REDIS_PASSWORD_FILE + value: "/secrets/valkey-password" + {{- else }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "valkey.secretName" . }} + key: {{ template "valkey.secretPasswordKey" . }} + {{- end }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: REDIS_ADDR + value: valkeys://{{ .Values.metrics.valkeyTargetHost }}:{{ .Values.replica.containerPorts.valkey }} + {{- if .Values.tls.authClients }} + - name: REDIS_EXPORTER_TLS_CLIENT_KEY_FILE + value: {{ template "valkey.tlsCertKey" . }} + - name: REDIS_EXPORTER_TLS_CLIENT_CERT_FILE + value: {{ template "valkey.tlsCert" . }} + {{- end }} + - name: REDIS_EXPORTER_TLS_CA_CERT_FILE + value: {{ template "valkey.tlsCACert" . }} + {{- end }} + {{- if .Values.metrics.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + ports: + - name: metrics + containerPort: {{ .Values.metrics.containerPorts.http }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- else if ne .Values.metrics.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.metrics.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if and .Values.auth.enabled .Values.auth.usePasswordFiles }} + - name: valkey-password + mountPath: /secrets/ + {{- end }} + {{- if .Values.tls.enabled }} + - name: valkey-certificates + mountPath: /opt/bitnami/valkey/certs + readOnly: true + {{- end }} + {{- if .Values.metrics.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.sentinel.service.createPrimary }} + - name: kubectl-shared + image: {{ template "valkey.kubectl.image" . }} + imagePullPolicy: {{ .Values.kubectl.image.pullPolicy | quote }} + command: {{- toYaml .Values.kubectl.command | nindent 12 }} + {{- if .Values.kubectl.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.kubectl.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + volumeMounts: + - name: kubectl-shared + mountPath: /etc/shared + - name: kubectl-scripts + mountPath: /opt/bitnami/scripts/kubectl-scripts + {{- if .Values.kubectl.resources }} + resources: {{- toYaml .Values.kubectl.resources | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.replica.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: start-scripts + configMap: + name: {{ printf "%s-scripts" (include "common.names.fullname" .) }} + defaultMode: 0755 + - name: health + configMap: + name: {{ printf "%s-health" (include "common.names.fullname" .) }} + defaultMode: 0755 + {{- if .Values.sentinel.service.createPrimary}} + - name: kubectl-shared + emptyDir: {} + - name: kubectl-scripts + configMap: + name: {{ printf "%s-kubectl-scripts" (include "common.names.fullname" .) }} + defaultMode: 0755 + {{- end }} + {{- if and .Values.auth.enabled .Values.auth.usePasswordFiles }} + - name: valkey-password + {{ if .Values.auth.usePasswordFileFromSecret }} + secret: + secretName: {{ template "valkey.secretName" . }} + items: + - key: {{ template "valkey.secretPasswordKey" . }} + path: valkey-password + {{- else }} + emptyDir: {} + {{- end }} + {{- end }} + - name: config + configMap: + name: {{ include "valkey.configmapName" . }} + {{- if not .Values.sentinel.persistence.enabled }} + - name: sentinel-data + {{- if or .Values.sentinel.persistence.medium .Values.sentinel.persistence.sizeLimit }} + emptyDir: + {{- if .Values.sentinel.persistence.medium }} + medium: {{ .Values.sentinel.persistence.medium | quote }} + {{- end }} + {{- if .Values.sentinel.persistence.sizeLimit }} + sizeLimit: {{ .Values.sentinel.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- end }} + - name: empty-dir + {{- if or .Values.sentinel.persistence.medium .Values.sentinel.persistence.sizeLimit }} + emptyDir: + {{- if .Values.sentinel.persistence.medium }} + medium: {{ .Values.sentinel.persistence.medium | quote }} + {{- end }} + {{- if .Values.sentinel.persistence.sizeLimit }} + sizeLimit: {{ .Values.sentinel.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- if .Values.replica.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if .Values.metrics.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if .Values.sentinel.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.sentinel.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: valkey-certificates + secret: + secretName: {{ include "valkey.tlsSecretName" . }} + defaultMode: 256 + {{- end }} + {{- if not .Values.replica.persistence.enabled }} + - name: valkey-data + {{- if or .Values.replica.persistence.medium .Values.replica.persistence.sizeLimit }} + emptyDir: + {{- if .Values.replica.persistence.medium }} + medium: {{ .Values.replica.persistence.medium | quote }} + {{- end }} + {{- if .Values.replica.persistence.sizeLimit }} + sizeLimit: {{ .Values.replica.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- else if .Values.replica.persistence.existingClaim }} + - name: valkey-data + persistentVolumeClaim: + claimName: {{ printf "%s" (tpl .Values.replica.persistence.existingClaim .) }} + {{- else }} + {{- if .Values.sentinel.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.sentinel.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.sentinel.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: valkey-data + labels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 10 }} + app.kubernetes.io/component: node + {{- if .Values.replica.persistence.annotations }} + annotations: {{- toYaml .Values.replica.persistence.annotations | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.replica.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.replica.persistence.size | quote }} + {{- if .Values.replica.persistence.selector }} + selector: {{- include "common.tplvalues.render" ( dict "value" .Values.replica.persistence.selector "context" $) | nindent 10 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" .Values.replica.persistence "global" .Values.global) | nindent 8 }} + {{- if .Values.sentinel.persistence.enabled }} + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: sentinel-data + {{- $claimLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.sentinel.persistence.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.matchLabels" ( dict "customLabels" $claimLabels "context" $ ) | nindent 10 }} + app.kubernetes.io/component: node + {{- if .Values.sentinel.persistence.annotations }} + annotations: {{- toYaml .Values.sentinel.persistence.annotations | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.sentinel.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.sentinel.persistence.size | quote }} + {{- if .Values.sentinel.persistence.selector }} + selector: {{- include "common.tplvalues.render" ( dict "value" .Values.sentinel.persistence.selector "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.sentinel.persistence.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.persistence.dataSource "context" $) | nindent 10 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" .Values.sentinel.persistence "global" .Values.global) | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/sentinel/vpa.yaml b/backing-services/gitea/charts/valkey/templates/sentinel/vpa.yaml new file mode 100644 index 0000000..6e53acb --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/sentinel/vpa.yaml @@ -0,0 +1,58 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (include "common.capabilities.apiVersions.has" ( dict "version" "autoscaling.k8s.io/v1/VerticalPodAutoscaler" "context" . )) .Values.replica.autoscaling.vpa.enabled .Values.sentinel.enabled }} +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: replica + app.kubernetes.io/part-of: valkey + {{- if or .Values.replica.autoscaling.vpa.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.replica.autoscaling.vpa.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + resourcePolicy: + containerPolicies: + - containerName: valkey + {{- with .Values.replica.autoscaling.vpa.controlledResources }} + controlledResources: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.replica.autoscaling.vpa.maxAllowed }} + maxAllowed: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.replica.autoscaling.vpa.minAllowed }} + minAllowed: + {{- toYaml . | nindent 8 }} + {{- end }} + - containerName: sentinel + {{- with .Values.replica.autoscaling.vpa.controlledResources }} + controlledResources: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.replica.autoscaling.vpa.maxAllowed }} + maxAllowed: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.replica.autoscaling.vpa.minAllowed }} + minAllowed: + {{- toYaml . | nindent 8 }} + {{- end }} + targetRef: + apiVersion: apps/v1 + kind: "StatefulSet" + name: {{ printf "%s-node" (include "common.names.fullname" .) }} + {{- if .Values.replica.autoscaling.vpa.updatePolicy }} + updatePolicy: + {{- with .Values.replica.autoscaling.vpa.updatePolicy.updateMode }} + updateMode: {{ . }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/serviceaccount.yaml b/backing-services/gitea/charts/valkey/templates/serviceaccount.yaml new file mode 100644 index 0000000..f52411d --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/serviceaccount.yaml @@ -0,0 +1,19 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.serviceAccount.create .Values.sentinel.enabled }} +apiVersion: v1 +kind: ServiceAccount +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +metadata: + name: {{ template "valkey.serviceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: valkey + {{- if or .Values.commonAnnotations .Values.serviceAccount.annotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/servicemonitor.yaml b/backing-services/gitea/charts/valkey/templates/servicemonitor.yaml new file mode 100644 index 0000000..cb9008b --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/servicemonitor.yaml @@ -0,0 +1,83 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ default (include "common.names.namespace" .) .Values.metrics.serviceMonitor.namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: valkey + {{- if .Values.metrics.serviceMonitor.additionalLabels }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.serviceMonitor.additionalLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + endpoints: + - port: {{ .Values.metrics.serviceMonitor.port }} + {{- if .Values.metrics.serviceMonitor.interval }} + interval: {{ .Values.metrics.serviceMonitor.interval }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.honorLabels }} + honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }} + {{- end }} + {{- with .Values.metrics.serviceMonitor.relabelings }} + relabelings: {{- toYaml . | nindent 6 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: {{- toYaml .Values.metrics.serviceMonitor.metricRelabelings | nindent 6 }} + {{- end }} + {{- range .Values.metrics.serviceMonitor.additionalEndpoints }} + - port: {{ .port }} + {{- if .interval }} + interval: {{ .interval }} + {{- end }} + {{- if .scrapeTimeout }} + scrapeTimeout: {{ .scrapeTimeout }} + {{- end }} + {{- if .honorLabels }} + honorLabels: {{ .honorLabels }} + {{- end }} + {{- with $.Values.metrics.serviceMonitor.relabelings }} + relabelings: {{- toYaml . | nindent 6 }} + {{- end }} + {{- if .metricRelabelings }} + metricRelabelings: {{- toYaml .metricRelabelings | nindent 6 }} + {{- end }} + {{- if .path }} + path: {{ .path }} + {{- end }} + {{- if .params }} + params: + {{- range $key, $value := .params }} + {{ $key }}: + {{- range $value }} + - {{ . | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.podTargetLabels }} + podTargetLabels: {{- toYaml .Values.metrics.serviceMonitor.podTargetLabels | nindent 4 }} + {{- end }} + {{- with .Values.metrics.serviceMonitor.sampleLimit }} + sampleLimit: {{ . }} + {{- end }} + {{- with .Values.metrics.serviceMonitor.targetLimit }} + targetLimit: {{ . }} + {{- end }} + namespaceSelector: + matchNames: + - {{ include "common.names.namespace" . | quote }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: metrics +{{- end }} diff --git a/backing-services/gitea/charts/valkey/templates/tls-secret.yaml b/backing-services/gitea/charts/valkey/templates/tls-secret.yaml new file mode 100644 index 0000000..5674836 --- /dev/null +++ b/backing-services/gitea/charts/valkey/templates/tls-secret.yaml @@ -0,0 +1,32 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "valkey.createTlsSecret" .) }} +{{- $secretName := printf "%s-crt" (include "common.names.fullname" .) }} +{{- $ca := genCA "valkey-ca" 365 }} +{{- $releaseNamespace := (include "common.names.namespace" .) }} +{{- $clusterDomain := .Values.clusterDomain }} +{{- $fullname := include "common.names.fullname" . }} +{{- $serviceName := include "common.names.fullname" . }} +{{- $headlessServiceName := printf "%s-headless" (include "common.names.fullname" .) }} +{{- $primaryServiceName := printf "%s-primary" (include "common.names.fullname" .) }} +{{- $altNames := list (printf "*.%s.%s.svc.%s" $serviceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $primaryServiceName $releaseNamespace $clusterDomain) (printf "*.%s.%s.svc.%s" $primaryServiceName $releaseNamespace $clusterDomain) (printf "*.%s.%s.svc.%s" $headlessServiceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $headlessServiceName $releaseNamespace $clusterDomain) "127.0.0.1" "localhost" $fullname }} +{{- $cert := genSignedCert $fullname nil $altNames 365 $ca }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: valkey + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.crt" "defaultValue" $cert.Cert "context" $) }} + tls.key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.key" "defaultValue" $cert.Key "context" $) }} + ca.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }} +{{- end }} diff --git a/backing-services/gitea/charts/valkey/values.schema.json b/backing-services/gitea/charts/valkey/values.schema.json new file mode 100644 index 0000000..1e2b65f --- /dev/null +++ b/backing-services/gitea/charts/valkey/values.schema.json @@ -0,0 +1,163 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "architecture": { + "type": "string", + "title": "Valkey architecture", + "form": true, + "description": "Allowed values: `standalone` or `replication`", + "enum": ["standalone", "replication"] + }, + "auth": { + "type": "object", + "title": "Authentication configuration", + "form": true, + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Use password authentication" + }, + "password": { + "type": "string", + "title": "Valkey password", + "form": true, + "description": "Defaults to a random 10-character alphanumeric string if not set", + "hidden": { + "value": false, + "path": "auth/enabled" + } + } + } + }, + "primary": { + "type": "object", + "title": "Primary replicas settings", + "form": true, + "properties": { + "kind": { + "type": "string", + "title": "Workload Kind", + "form": true, + "description": "Allowed values: `Deployment`, `StatefulSet` or `DaemonSet`", + "enum": ["Deployment", "StatefulSet", "DaemonSet"] + }, + "persistence": { + "type": "object", + "title": "Persistence for primary replicas", + "form": true, + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable persistence", + "description": "Enable persistence using Persistent Volume Claims" + }, + "size": { + "type": "string", + "title": "Persistent Volume Size", + "form": true, + "render": "slider", + "sliderMin": 1, + "sliderMax": 100, + "sliderUnit": "Gi", + "hidden": { + "value": false, + "path": "primary/persistence/enabled" + } + } + } + } + } + }, + "replica": { + "type": "object", + "title": "Valkey replicas settings", + "form": true, + "hidden": { + "value": "standalone", + "path": "architecture" + }, + "properties": { + "kind": { + "type": "string", + "title": "Workload Kind", + "form": true, + "description": "Allowed values: `DaemonSet` or `StatefulSet`", + "enum": ["DaemonSet", "StatefulSet"] + }, + "replicaCount": { + "type": "integer", + "form": true, + "title": "Number of Valkey replicas" + }, + "persistence": { + "type": "object", + "title": "Persistence for Valkey replicas", + "form": true, + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable persistence", + "description": "Enable persistence using Persistent Volume Claims" + }, + "size": { + "type": "string", + "title": "Persistent Volume Size", + "form": true, + "render": "slider", + "sliderMin": 1, + "sliderMax": 100, + "sliderUnit": "Gi", + "hidden": { + "value": false, + "path": "replica/persistence/enabled" + } + } + } + } + } + }, + "volumePermissions": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable Init Containers", + "description": "Use an init container to set required folder permissions on the data volume before mounting it in the final destination" + } + } + }, + "metrics": { + "type": "object", + "form": true, + "title": "Prometheus metrics details", + "properties": { + "enabled": { + "type": "boolean", + "title": "Create Prometheus metrics exporter", + "description": "Create a side-car container to expose Prometheus metrics", + "form": true + }, + "serviceMonitor": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Create Prometheus Operator ServiceMonitor", + "description": "Create a ServiceMonitor to track metrics using Prometheus Operator", + "form": true, + "hidden": { + "value": false, + "path": "metrics/enabled" + } + } + } + } + } + } + } +} diff --git a/backing-services/gitea/charts/valkey/values.yaml b/backing-services/gitea/charts/valkey/values.yaml new file mode 100644 index 0000000..6e637be --- /dev/null +++ b/backing-services/gitea/charts/valkey/values.yaml @@ -0,0 +1,2137 @@ +# Copyright Broadcom, Inc. All Rights Reserved. +# SPDX-License-Identifier: APACHE-2.0 + +## @section Global parameters +## 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, imagePullSecrets and storageClass +## + +## @param global.imageRegistry Global Docker image registry +## @param global.imagePullSecrets Global Docker registry secret names as an array +## @param global.defaultStorageClass Global default StorageClass for Persistent Volume(s) +## @param global.storageClass DEPRECATED: use global.defaultStorageClass instead +## @param global.valkey.password Global Valkey password (overrides `auth.password`) +## +global: + imageRegistry: "" + ## E.g. + ## imagePullSecrets: + ## - myRegistryKeySecretName + ## + imagePullSecrets: [] + defaultStorageClass: "" + storageClass: "" + ## Security parameters + ## + security: + ## @param global.security.allowInsecureImages Allows skipping image verification + allowInsecureImages: false + valkey: + password: "" + ## Compatibility adaptations for Kubernetes platforms + ## + compatibility: + ## Compatibility adaptations for Openshift + ## + openshift: + ## @param global.compatibility.openshift.adaptSecurityContext Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) + ## + adaptSecurityContext: auto +## @section Common parameters +## + +## @param kubeVersion Override Kubernetes version +## +kubeVersion: "" +## @param apiVersions Override Kubernetes API versions reported by .Capabilities +## +apiVersions: [] +## @param nameOverride String to partially override common.names.fullname +## +nameOverride: "" +## @param fullnameOverride String to fully override common.names.fullname +## +fullnameOverride: "" +## @param namespaceOverride String to fully override common.names.namespace +## +namespaceOverride: "" +## @param commonLabels Labels to add to all deployed objects +## +commonLabels: {} +## @param commonAnnotations Annotations to add to all deployed objects +## +commonAnnotations: {} +## @param secretAnnotations Annotations to add to secret +## +secretAnnotations: {} +## @param clusterDomain Kubernetes cluster domain name +## +clusterDomain: cluster.local +## @param extraDeploy Array of extra objects to deploy with the release +## +extraDeploy: [] +## @param useHostnames Use hostnames internally when announcing replication. If false, the hostname will be resolved to an IP address +## +useHostnames: true +## @param nameResolutionThreshold Failure threshold for internal hostnames resolution +## +nameResolutionThreshold: 5 +## @param nameResolutionTimeout Timeout seconds between probes for internal hostnames resolution +## +nameResolutionTimeout: 5 +## Enable diagnostic mode in the deployment +## +diagnosticMode: + ## @param diagnosticMode.enabled Enable diagnostic mode (all probes will be disabled and the command will be overridden) + ## + enabled: false + ## @param diagnosticMode.command Command to override all containers in the deployment + ## + command: + - sleep + ## @param diagnosticMode.args Args to override all containers in the deployment + ## + args: + - infinity +## @section Valkey Image parameters +## + +## Bitnami Valkey image +## ref: https://hub.docker.com/r/bitnami/valkey/tags/ +## @param image.registry [default: REGISTRY_NAME] Valkey image registry +## @param image.repository [default: REPOSITORY_NAME/valkey] Valkey image repository +## @skip image.tag Valkey image tag (immutable tags are recommended) +## @param image.digest Valkey image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag +## @param image.pullPolicy Valkey image pull policy +## @param image.pullSecrets Valkey image pull secrets +## @param image.debug Enable image debug mode +## +image: + registry: docker.io + repository: bitnami/valkey + tag: 8.1.3-debian-12-r3 + digest: "" + ## Specify a imagePullPolicy + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Enable debug mode + ## + debug: false +## @section Valkey common configuration parameters +## https://github.com/bitnami/containers/tree/main/bitnami/valkey#configuration +## + +## @param architecture Valkey architecture. Allowed values: `standalone` or `replication` +## +architecture: replication +## Valkey Authentication parameters +## ref: https://github.com/bitnami/containers/tree/main/bitnami/valkey#setting-the-server-password-on-first-run +## +auth: + ## @param auth.enabled Enable password authentication + ## + enabled: true + ## @param auth.sentinel Enable password authentication on sentinels too + ## + sentinel: true + ## @param auth.password Valkey password + ## Defaults to a random 10-character alphanumeric string if not set + ## + password: "" + ## @param auth.existingSecret The name of an existing secret with Valkey credentials + ## NOTE: When it's set, the previous `auth.password` parameter is ignored + ## + existingSecret: "" + ## @param auth.existingSecretPasswordKey Password key to be retrieved from existing secret + ## NOTE: ignored unless `auth.existingSecret` parameter is set + ## + existingSecretPasswordKey: "" + ## @param auth.usePasswordFiles Mount credentials as files instead of using an environment variable + ## + usePasswordFiles: true + ## @param auth.usePasswordFileFromSecret Mount password file from secret + ## + usePasswordFileFromSecret: true +## @param commonConfiguration [string] Common configuration to be added into the ConfigMap +## ref: https://valkey.io/topics/valkey-conf/ +## +commonConfiguration: |- + # Enable AOF https://valkey.io/docs/topics/persistence.html + appendonly yes + # Disable RDB persistence, AOF persistence already enabled. + save "" +## @param existingConfigmap The name of an existing ConfigMap with your custom configuration for Valkey nodes +## +existingConfigmap: "" +## @section Valkey primary configuration parameters +## +primary: + ## @param primary.replicaCount Number of Valkey primary instances to deploy (experimental, requires additional configuration) + ## + replicaCount: 1 + ## @param primary.configuration Configuration for Valkey primary nodes + ## ref: https://valkey.io/topics/config + ## + configuration: "" + ## @param primary.disableCommands Array with Valkey commands to disable on primary nodes + ## Commands will be completely disabled by renaming each to an empty string. + ## ref: https://valkey.io/topics/security#disabling-of-specific-commands + ## + disableCommands: + - FLUSHDB + - FLUSHALL + ## @param primary.command Override default container command (useful when using custom images) + ## + command: [] + ## @param primary.args Override default container args (useful when using custom images) + ## + args: [] + ## @param primary.enableServiceLinks Whether information about services should be injected into pod's environment variable + ## + enableServiceLinks: true + ## @param primary.preExecCmds Additional commands to run prior to starting Valkey primary + ## + preExecCmds: [] + ## @param primary.extraFlags Array with additional command line flags for Valkey primary + ## e.g: + ## extraFlags: + ## - "--maxmemory-policy volatile-ttl" + ## - "--repl-backlog-size 1024mb" + ## + extraFlags: [] + ## @param primary.extraEnvVars Array with extra environment variables to add to Valkey primary nodes + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param primary.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for Valkey primary nodes + ## + extraEnvVarsCM: "" + ## @param primary.extraEnvVarsSecret Name of existing Secret containing extra env vars for Valkey primary nodes + ## + extraEnvVarsSecret: "" + ## @param primary.containerPorts.valkey Container port to open on Valkey primary nodes + ## + containerPorts: + valkey: 6379 + ## Configure extra options for Valkey containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param primary.startupProbe.enabled Enable startupProbe on Valkey primary nodes + ## @param primary.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param primary.startupProbe.periodSeconds Period seconds for startupProbe + ## @param primary.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param primary.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param primary.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param primary.livenessProbe.enabled Enable livenessProbe on Valkey primary nodes + ## @param primary.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param primary.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param primary.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param primary.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param primary.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param primary.readinessProbe.enabled Enable readinessProbe on Valkey primary nodes + ## @param primary.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param primary.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param primary.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param primary.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param primary.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 5 + ## @param primary.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param primary.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param primary.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## Valkey primary resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param primary.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if primary.resources is set (primary.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param primary.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Configure Pods Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param primary.podSecurityContext.enabled Enabled Valkey primary pods' Security Context + ## @param primary.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy + ## @param primary.podSecurityContext.sysctls Set kernel settings using the sysctl interface + ## @param primary.podSecurityContext.supplementalGroups Set filesystem extra groups + ## @param primary.podSecurityContext.fsGroup Set Valkey primary pod's Security Context fsGroup + ## + podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + sysctls: [] + supplementalGroups: [] + fsGroup: 1001 + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param primary.containerSecurityContext.enabled Enabled Valkey primary containers' Security Context + ## @param primary.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param primary.containerSecurityContext.runAsUser Set Valkey primary containers' Security Context runAsUser + ## @param primary.containerSecurityContext.runAsGroup Set Valkey primary containers' Security Context runAsGroup + ## @param primary.containerSecurityContext.runAsNonRoot Set Valkey primary containers' Security Context runAsNonRoot + ## @param primary.containerSecurityContext.allowPrivilegeEscalation Is it possible to escalate Valkey pod(s) privileges + ## @param primary.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context read-only root filesystem + ## @param primary.containerSecurityContext.seccompProfile.type Set Valkey primary containers' Security Context seccompProfile + ## @param primary.containerSecurityContext.capabilities.drop Set Valkey primary containers' Security Context capabilities to drop + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + seccompProfile: + type: RuntimeDefault + capabilities: + drop: ["ALL"] + ## @param primary.kind Use either Deployment, StatefulSet (default) or DaemonSet + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/ + ## + kind: StatefulSet + ## @param primary.schedulerName Alternate scheduler for Valkey primary pods + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param primary.updateStrategy.type Valkey primary statefulset strategy type + ## @skip primary.updateStrategy.rollingUpdate + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## + updateStrategy: + ## StrategyType + ## Can be set to RollingUpdate, OnDelete (statefulset), Recreate (deployment) + ## + type: RollingUpdate + ## @param primary.minReadySeconds How many seconds a pod needs to be ready before killing the next, during update + ## + minReadySeconds: 0 + ## @param primary.priorityClassName Valkey primary pods' priorityClassName + ## + priorityClassName: "" + ## @param primary.automountServiceAccountToken Mount Service Account token in pod + ## + automountServiceAccountToken: false + ## @param primary.hostAliases Valkey primary pods host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param primary.podLabels Extra labels for Valkey primary pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param primary.podAnnotations Annotations for Valkey primary pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param primary.shareProcessNamespace Share a single process namespace between all of the containers in Valkey primary pods + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/share-process-namespace/ + ## + shareProcessNamespace: false + ## @param primary.podAffinityPreset Pod affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param primary.podAntiAffinityPreset Pod anti-affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Node primary.affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param primary.nodeAffinityPreset.type Node affinity preset type. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param primary.nodeAffinityPreset.key Node label key to match. Ignored if `primary.affinity` is set + ## + key: "" + ## @param primary.nodeAffinityPreset.values Node label values to match. Ignored if `primary.affinity` is set + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param primary.affinity Affinity for Valkey primary pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## NOTE: `primary.podAffinityPreset`, `primary.podAntiAffinityPreset`, and `primary.nodeAffinityPreset` will be ignored when it's set + ## + affinity: {} + ## @param primary.nodeSelector Node labels for Valkey primary pods assignment + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: {} + ## @param primary.tolerations Tolerations for Valkey primary pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param primary.topologySpreadConstraints Spread Constraints for Valkey primary pod assignment + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## E.g. + ## topologySpreadConstraints: + ## - maxSkew: 1 + ## topologyKey: node + ## whenUnsatisfiable: DoNotSchedule + ## + topologySpreadConstraints: [] + ## @param primary.dnsPolicy DNS Policy for Valkey primary pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/ + ## E.g. + ## dnsPolicy: ClusterFirst + ## + dnsPolicy: "" + ## @param primary.dnsConfig DNS Configuration for Valkey primary pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/ + ## E.g. + ## dnsConfig: + ## options: + ## - name: ndots + ## value: "4" + ## - name: single-request-reopen + ## + dnsConfig: {} + ## @param primary.lifecycleHooks for the Valkey primary container(s) to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param primary.extraVolumes Optionally specify extra list of additional volumes for the Valkey primary pod(s) + ## + extraVolumes: [] + ## @param primary.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the Valkey primary container(s) + ## + extraVolumeMounts: [] + ## @param primary.sidecars Add additional sidecar containers to the Valkey primary pod(s) + ## e.g: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param primary.initContainers Add additional init containers to the Valkey primary pod(s) + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + ## e.g: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## command: ['sh', '-c', 'echo "hello world"'] + ## + initContainers: [] + ## Persistence parameters + ## ref: https://kubernetes.io/docs/concepts/storage/persistent-volumes/ + ## + persistence: + ## @param primary.persistence.enabled Enable persistence on Valkey primary nodes using Persistent Volume Claims + ## + enabled: true + ## @param primary.persistence.medium Provide a medium for `emptyDir` volumes. + ## + medium: "" + ## @param primary.persistence.sizeLimit Set this to enable a size limit for `emptyDir` volumes. + ## + sizeLimit: "" + ## @param primary.persistence.path The path the volume will be mounted at on Valkey primary containers + ## NOTE: Useful when using different Valkey images + ## + path: /data + ## @param primary.persistence.subPath The subdirectory of the volume to mount on Valkey primary containers + ## NOTE: Useful in dev environments + ## + subPath: "" + ## @param primary.persistence.subPathExpr Used to construct the subPath subdirectory of the volume to mount on Valkey primary containers + ## + subPathExpr: "" + ## @param primary.persistence.storageClass 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 + ## + storageClass: "" + ## @param primary.persistence.accessModes Persistent Volume access modes + ## + accessModes: + - ReadWriteOnce + ## @param primary.persistence.size Persistent Volume size + ## + size: 8Gi + ## @param primary.persistence.annotations Additional custom annotations for the PVC + ## + annotations: {} + ## @param primary.persistence.labels Additional custom labels for the PVC + ## + labels: {} + ## @param primary.persistence.selector Additional labels to match for the PVC + ## e.g: + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## @param primary.persistence.dataSource Custom PVC data source + ## + dataSource: {} + ## @param primary.persistence.existingClaim Use a existing PVC which must be created manually before bound + ## NOTE: requires primary.persistence.enabled: true + ## + existingClaim: "" + ## persistentVolumeClaimRetentionPolicy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention + ## @param primary.persistentVolumeClaimRetentionPolicy.enabled Controls if and how PVCs are deleted during the lifecycle of a StatefulSet + ## @param primary.persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced + ## @param primary.persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted + ## + persistentVolumeClaimRetentionPolicy: + enabled: false + whenScaled: Retain + whenDeleted: Retain + ## Valkey primary service parameters + ## + service: + ## @param primary.service.type Valkey primary service type + ## + type: ClusterIP + ## @param primary.service.ports.valkey Valkey primary service port + ## + ports: + valkey: 6379 + ## @param primary.service.nodePorts.valkey Node port for Valkey primary + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## NOTE: choose port between <30000-32767> + ## + nodePorts: + valkey: "" + ## @param primary.service.externalTrafficPolicy Valkey primary service external traffic policy + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param primary.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param primary.service.internalTrafficPolicy Valkey primary service internal traffic policy (requires Kubernetes v1.22 or greater to be usable) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/ + ## + internalTrafficPolicy: Cluster + ## @param primary.service.clusterIP Valkey primary service Cluster IP + ## + clusterIP: "" + ## @param primary.service.loadBalancerIP Valkey primary service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param primary.service.loadBalancerClass primary service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerClass: "" + ## @param primary.service.loadBalancerSourceRanges Valkey primary service Load Balancer sources + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g. + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param primary.service.externalIPs Valkey primary service External IPs + ## https://kubernetes.io/docs/concepts/services-networking/service/#external-ips + ## e.g. + ## externalIPs: + ## - 10.10.10.1 + ## - 201.22.30.1 + ## + externalIPs: [] + ## @param primary.service.annotations Additional custom annotations for Valkey primary service + ## + annotations: {} + ## @param primary.service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param primary.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## @param primary.terminationGracePeriodSeconds Integer setting the termination grace period for the valkey-primary pods + ## + terminationGracePeriodSeconds: 30 + ## ServiceAccount configuration + ## + serviceAccount: + ## @param primary.serviceAccount.create Specifies whether a ServiceAccount should be created + ## + create: true + ## @param primary.serviceAccount.name The name of the ServiceAccount to use. + ## If not set and create is true, a name is generated using the common.names.fullname template + ## + name: "" + ## @param primary.serviceAccount.automountServiceAccountToken Whether to auto mount the service account token + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server + ## + automountServiceAccountToken: false + ## @param primary.serviceAccount.annotations Additional custom annotations for the ServiceAccount + ## + annotations: {} + ## Pod Disruption Budget configuration + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb + ## @param primary.pdb.create Enable/disable a Pod Disruption Budget creation + ## @param primary.pdb.minAvailable [object] Minimum number/percentage of pods that should remain scheduled + ## @param primary.pdb.maxUnavailable [object] Maximum number/percentage of pods that may be made unavailable. Defaults to `1` if both `primary.pdb.minAvailable` and `primary.pdb.maxUnavailable` are empty. + ## + pdb: + create: true + minAvailable: "" + maxUnavailable: "" + +## @section Valkey replicas configuration parameters +## +replica: + ## @param replica.kind Use either DaemonSet or StatefulSet (default) + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/ + ## + kind: StatefulSet + ## @param replica.replicaCount Number of Valkey replicas to deploy + ## + replicaCount: 3 + ## @param replica.configuration Configuration for Valkey replicas nodes + ## ref: https://valkey.io/topics/config + ## + configuration: "" + ## @param replica.disableCommands Array with Valkey commands to disable on replicas nodes + ## Commands will be completely disabled by renaming each to an empty string. + ## ref: https://valkey.io/topics/security#disabling-of-specific-commands + ## + disableCommands: + - FLUSHDB + - FLUSHALL + ## @param replica.command Override default container command (useful when using custom images) + ## + command: [] + ## @param replica.args Override default container args (useful when using custom images) + ## + args: [] + ## @param replica.enableServiceLinks Whether information about services should be injected into pod's environment variable + ## + enableServiceLinks: true + ## @param replica.preExecCmds Additional commands to run prior to starting Valkey replicas + ## + preExecCmds: [] + ## @param replica.extraFlags Array with additional command line flags for Valkey replicas + ## e.g: + ## extraFlags: + ## - "--maxmemory-policy volatile-ttl" + ## - "--repl-backlog-size 1024mb" + ## + extraFlags: [] + ## @param replica.extraEnvVars Array with extra environment variables to add to Valkey replicas nodes + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param replica.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for Valkey replicas nodes + ## + extraEnvVarsCM: "" + ## @param replica.extraEnvVarsSecret Name of existing Secret containing extra env vars for Valkey replicas nodes + ## + extraEnvVarsSecret: "" + ## @param replica.externalPrimary.enabled Use external primary for bootstrapping + ## @param replica.externalPrimary.host External primary host to bootstrap from + ## @param replica.externalPrimary.port Port for Valkey service external primary host + ## + externalPrimary: + enabled: false + host: "" + port: 6379 + ## @param replica.containerPorts.valkey Container port to open on Valkey replicas nodes + ## + containerPorts: + valkey: 6379 + ## Configure extra options for Valkey containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param replica.startupProbe.enabled Enable startupProbe on Valkey replicas nodes + ## @param replica.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param replica.startupProbe.periodSeconds Period seconds for startupProbe + ## @param replica.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param replica.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param replica.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: true + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 22 + ## @param replica.livenessProbe.enabled Enable livenessProbe on Valkey replicas nodes + ## @param replica.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param replica.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param replica.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param replica.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param replica.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param replica.readinessProbe.enabled Enable readinessProbe on Valkey replicas nodes + ## @param replica.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param replica.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param replica.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param replica.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param replica.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 5 + ## @param replica.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param replica.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param replica.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## Valkey replicas resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param replica.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if replica.resources is set (replica.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param replica.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Configure Pods Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param replica.podSecurityContext.enabled Enabled Valkey replicas pods' Security Context + ## @param replica.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy + ## @param replica.podSecurityContext.sysctls Set kernel settings using the sysctl interface + ## @param replica.podSecurityContext.supplementalGroups Set filesystem extra groups + ## @param replica.podSecurityContext.fsGroup Set Valkey replicas pod's Security Context fsGroup + ## + podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + sysctls: [] + supplementalGroups: [] + fsGroup: 1001 + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param replica.containerSecurityContext.enabled Enabled Valkey replicas containers' Security Context + ## @param replica.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param replica.containerSecurityContext.runAsUser Set Valkey replicas containers' Security Context runAsUser + ## @param replica.containerSecurityContext.runAsGroup Set Valkey replicas containers' Security Context runAsGroup + ## @param replica.containerSecurityContext.runAsNonRoot Set Valkey replicas containers' Security Context runAsNonRoot + ## @param replica.containerSecurityContext.allowPrivilegeEscalation Set Valkey replicas pod's Security Context allowPrivilegeEscalation + ## @param replica.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context read-only root filesystem + ## @param replica.containerSecurityContext.seccompProfile.type Set Valkey replicas containers' Security Context seccompProfile + ## @param replica.containerSecurityContext.capabilities.drop Set Valkey replicas containers' Security Context capabilities to drop + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + seccompProfile: + type: RuntimeDefault + capabilities: + drop: ["ALL"] + ## @param replica.schedulerName Alternate scheduler for Valkey replicas pods + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param replica.updateStrategy.type Valkey replicas statefulset strategy type + ## @skip replica.updateStrategy.rollingUpdate + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## + updateStrategy: + ## StrategyType + ## Can be set to RollingUpdate, OnDelete (statefulset), Recreate (deployment) + ## + type: RollingUpdate + ## @param replica.minReadySeconds How many seconds a pod needs to be ready before killing the next, during update + ## + minReadySeconds: 0 + ## @param replica.priorityClassName Valkey replicas pods' priorityClassName + ## + priorityClassName: "" + ## @param replica.podManagementPolicy podManagementPolicy to manage scaling operation of %%MAIN_CONTAINER_NAME%% pods + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#pod-management-policies + ## + podManagementPolicy: "" + ## @param replica.automountServiceAccountToken Mount Service Account token in pod + ## + automountServiceAccountToken: false + ## @param replica.hostAliases Valkey replicas pods host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param replica.podLabels Extra labels for Valkey replicas pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param replica.podAnnotations Annotations for Valkey replicas pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param replica.shareProcessNamespace Share a single process namespace between all of the containers in Valkey replicas pods + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/share-process-namespace/ + ## + shareProcessNamespace: false + ## @param replica.podAffinityPreset Pod affinity preset. Ignored if `replica.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param replica.podAntiAffinityPreset Pod anti-affinity preset. Ignored if `replica.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param replica.nodeAffinityPreset.type Node affinity preset type. Ignored if `replica.affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param replica.nodeAffinityPreset.key Node label key to match. Ignored if `replica.affinity` is set + ## + key: "" + ## @param replica.nodeAffinityPreset.values Node label values to match. Ignored if `replica.affinity` is set + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param replica.affinity Affinity for Valkey replicas pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## NOTE: `replica.podAffinityPreset`, `replica.podAntiAffinityPreset`, and `replica.nodeAffinityPreset` will be ignored when it's set + ## + affinity: {} + ## @param replica.nodeSelector Node labels for Valkey replicas pods assignment + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: {} + ## @param replica.tolerations Tolerations for Valkey replicas pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param replica.topologySpreadConstraints Spread Constraints for Valkey replicas pod assignment + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## E.g. + ## topologySpreadConstraints: + ## - maxSkew: 1 + ## topologyKey: node + ## whenUnsatisfiable: DoNotSchedule + ## + topologySpreadConstraints: [] + ## @param replica.dnsPolicy DNS Policy for Valkey replica pods + ## ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/ + ## E.g. + ## dnsPolicy: ClusterFirst + ## + dnsPolicy: "" + ## @param replica.dnsConfig DNS Configuration for Valkey replica pods + ## ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/ + ## E.g. + ## dnsConfig: + ## options: + ## - name: ndots + ## value: "4" + ## - name: single-request-reopen + ## + dnsConfig: {} + ## @param replica.lifecycleHooks for the Valkey replica container(s) to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param replica.extraVolumes Optionally specify extra list of additional volumes for the Valkey replicas pod(s) + ## + extraVolumes: [] + ## @param replica.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the Valkey replicas container(s) + ## + extraVolumeMounts: [] + ## @param replica.sidecars Add additional sidecar containers to the Valkey replicas pod(s) + ## e.g: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param replica.initContainers Add additional init containers to the Valkey replicas pod(s) + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + ## e.g: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## command: ['sh', '-c', 'echo "hello world"'] + ## + initContainers: [] + ## Persistence Parameters + ## ref: https://kubernetes.io/docs/concepts/storage/persistent-volumes/ + ## + persistence: + ## @param replica.persistence.enabled Enable persistence on Valkey replicas nodes using Persistent Volume Claims + ## + enabled: true + ## @param replica.persistence.medium Provide a medium for `emptyDir` volumes. + ## + medium: "" + ## @param replica.persistence.sizeLimit Set this to enable a size limit for `emptyDir` volumes. + ## + sizeLimit: "" + ## @param replica.persistence.path The path the volume will be mounted at on Valkey replicas containers + ## NOTE: Useful when using different Valkey images + ## + path: /data + ## @param replica.persistence.subPath The subdirectory of the volume to mount on Valkey replicas containers + ## NOTE: Useful in dev environments + ## + subPath: "" + ## @param replica.persistence.subPathExpr Used to construct the subPath subdirectory of the volume to mount on Valkey replicas containers + ## + subPathExpr: "" + ## @param replica.persistence.storageClass 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 + ## + storageClass: "" + ## @param replica.persistence.accessModes Persistent Volume access modes + ## + accessModes: + - ReadWriteOnce + ## @param replica.persistence.size Persistent Volume size + ## + size: 8Gi + ## @param replica.persistence.annotations Additional custom annotations for the PVC + ## + annotations: {} + ## @param replica.persistence.labels Additional custom labels for the PVC + ## + labels: {} + ## @param replica.persistence.selector Additional labels to match for the PVC + ## e.g: + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## @param replica.persistence.dataSource Custom PVC data source + ## + dataSource: {} + ## @param replica.persistence.existingClaim Use a existing PVC which must be created manually before bound + ## NOTE: requires replica.persistence.enabled: true + ## + existingClaim: "" + ## persistentVolumeClaimRetentionPolicy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention + ## @param replica.persistentVolumeClaimRetentionPolicy.enabled Controls if and how PVCs are deleted during the lifecycle of a StatefulSet + ## @param replica.persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced + ## @param replica.persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted + ## + persistentVolumeClaimRetentionPolicy: + enabled: false + whenScaled: Retain + whenDeleted: Retain + ## Valkey replicas service parameters + ## + service: + ## @param replica.service.type Valkey replicas service type + ## + type: ClusterIP + ## @param replica.service.ports.valkey Valkey replicas service port + ## + ports: + valkey: 6379 + ## @param replica.service.nodePorts.valkey Node port for Valkey replicas + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## NOTE: choose port between <30000-32767> + ## + nodePorts: + valkey: "" + ## @param replica.service.externalTrafficPolicy Valkey replicas service external traffic policy + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param replica.service.internalTrafficPolicy Valkey replicas service internal traffic policy (requires Kubernetes v1.22 or greater to be usable) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/ + ## + internalTrafficPolicy: Cluster + ## @param replica.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param replica.service.clusterIP Valkey replicas service Cluster IP + ## + clusterIP: "" + ## @param replica.service.loadBalancerIP Valkey replicas service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param replica.service.loadBalancerClass replicas service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerClass: "" + ## @param replica.service.loadBalancerSourceRanges Valkey replicas service Load Balancer sources + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g. + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param replica.service.annotations Additional custom annotations for Valkey replicas service + ## + annotations: {} + ## @param replica.service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param replica.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## @param replica.terminationGracePeriodSeconds Integer setting the termination grace period for the valkey-replicas pods + ## + terminationGracePeriodSeconds: 30 + ## @section Autoscaling + ## ref: https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/ + ## + autoscaling: + vpa: + ## @param replica.autoscaling.vpa.enabled Enable VPA + ## + enabled: false + ## @param replica.autoscaling.vpa.annotations Annotations for VPA resource + ## + annotations: {} + ## @param replica.autoscaling.vpa.controlledResources VPA List of resources that the vertical pod autoscaler can control. Defaults to cpu and memory + ## + controlledResources: [] + ## @param replica.autoscaling.vpa.maxAllowed VPA Max allowed resources for the pod + ## cpu: 200m + ## memory: 100Mi + maxAllowed: {} + ## @param replica.autoscaling.vpa.minAllowed VPA Min allowed resources for the pod + ## cpu: 200m + ## memory: 100Mi + minAllowed: {} + ## @section VPA update policy + ## + updatePolicy: + ## @param replica.autoscaling.vpa.updatePolicy.updateMode Autoscaling update policy Specifies whether recommended updates are applied when a Pod is started and whether recommended updates are applied during the life of a Pod + ## Possible values are "Off", "Initial", "Recreate", and "Auto". + ## + updateMode: Auto + hpa: + ## @param replica.autoscaling.hpa.enabled Enable HPA + ## + enabled: false + ## @param replica.autoscaling.hpa.minReplicas Minimum number of replicas + ## + minReplicas: "" + ## @param replica.autoscaling.hpa.maxReplicas Maximum number of replicas + ## + maxReplicas: "" + ## @param replica.autoscaling.hpa.targetCPU Target CPU utilization percentage + ## + targetCPU: "" + ## @param replica.autoscaling.hpa.targetMemory Target Memory utilization percentage + ## + targetMemory: "" + ## ServiceAccount configuration + ## + serviceAccount: + ## @param replica.serviceAccount.create Specifies whether a ServiceAccount should be created + ## + create: true + ## @param replica.serviceAccount.name The name of the ServiceAccount to use. + ## If not set and create is true, a name is generated using the common.names.fullname template + ## + name: "" + ## @param replica.serviceAccount.automountServiceAccountToken Whether to auto mount the service account token + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server + ## + automountServiceAccountToken: false + ## @param replica.serviceAccount.annotations Additional custom annotations for the ServiceAccount + ## + annotations: {} + ## Pod Disruption Budget configuration + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb + ## @param replica.pdb.create Enable/disable a Pod Disruption Budget creation + ## @param replica.pdb.minAvailable [object] Minimum number/percentage of pods that should remain scheduled + ## @param replica.pdb.maxUnavailable [object] Maximum number/percentage of pods that may be made unavailable. Defaults to `1` if both `replica.pdb.minAvailable` and `replica.pdb.maxUnavailable` are empty. + ## + pdb: + create: true + minAvailable: "" + maxUnavailable: "" + +## @section Valkey Sentinel configuration parameters +## + +sentinel: + ## @param sentinel.enabled Use Valkey Sentinel on Valkey pods. + ## IMPORTANT: this will disable the primary and replicas services and + ## create a single Valkey service exposing both the Valkey and Sentinel ports + ## + enabled: false + ## Bitnami Valkey Sentinel image version + ## ref: https://hub.docker.com/r/bitnami/valkey-sentinel/tags/ + ## @param sentinel.image.registry [default: REGISTRY_NAME] Valkey Sentinel image registry + ## @param sentinel.image.repository [default: REPOSITORY_NAME/valkey-sentinel] Valkey Sentinel image repository + ## @skip sentinel.image.tag Valkey Sentinel image tag (immutable tags are recommended) + ## @param sentinel.image.digest Valkey Sentinel image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param sentinel.image.pullPolicy Valkey Sentinel image pull policy + ## @param sentinel.image.pullSecrets Valkey Sentinel image pull secrets + ## @param sentinel.image.debug Enable image debug mode + ## + image: + registry: docker.io + repository: bitnami/valkey-sentinel + tag: 8.1.3-debian-12-r3 + digest: "" + ## Specify a imagePullPolicy + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Enable debug mode + ## + debug: false + ## @param sentinel.annotations Additional custom annotations for Valkey Sentinel resource + ## + annotations: {} + ## @param sentinel.primarySet Primary set name + ## + primarySet: myprimary + ## @param sentinel.quorum Sentinel Quorum + ## + quorum: 2 + ## @param sentinel.getPrimaryTimeout Amount of time to allow before get_sentinel_primary_info() times out. + ## + getPrimaryTimeout: 90 + ## @param sentinel.automateClusterRecovery Automate cluster recovery in cases where the last replica is not considered a good replica and Sentinel won't automatically failover to it. + ## This also prevents any new replica from starting until the last remaining replica is elected as primary to guarantee that it is the one to be elected by Sentinel, and not a newly started replica with no data. + ## NOTE: This feature requires a "downAfterMilliseconds" value less or equal to 2000. + ## + automateClusterRecovery: false + ## @param sentinel.valkeyShutdownWaitFailover Whether the Valkey primary container waits for the failover at shutdown (in addition to the Valkey Sentinel container). + ## + valkeyShutdownWaitFailover: true + ## Sentinel timing restrictions + ## @param sentinel.downAfterMilliseconds Timeout for detecting a Valkey node is down + ## @param sentinel.failoverTimeout Timeout for performing a election failover + ## + downAfterMilliseconds: 60000 + failoverTimeout: 180000 + ## @param sentinel.parallelSyncs Number of replicas that can be reconfigured in parallel to use the new primary after a failover + ## + parallelSyncs: 1 + ## @param sentinel.configuration Configuration for Valkey Sentinel nodes + ## ref: https://valkey.io/topics/sentinel + ## + configuration: "" + ## @param sentinel.command Override default container command (useful when using custom images) + ## + command: [] + ## @param sentinel.args Override default container args (useful when using custom images) + ## + args: [] + ## @param sentinel.enableServiceLinks Whether information about services should be injected into pod's environment variable + ## + enableServiceLinks: true + ## @param sentinel.preExecCmds Additional commands to run prior to starting Valkey Sentinel + ## + preExecCmds: [] + ## @param sentinel.extraEnvVars Array with extra environment variables to add to Valkey Sentinel nodes + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param sentinel.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for Valkey Sentinel nodes + ## + extraEnvVarsCM: "" + ## @param sentinel.extraEnvVarsSecret Name of existing Secret containing extra env vars for Valkey Sentinel nodes + ## + extraEnvVarsSecret: "" + ## @param sentinel.externalPrimary.enabled Use external primary for bootstrapping + ## @param sentinel.externalPrimary.host External primary host to bootstrap from + ## @param sentinel.externalPrimary.port Port for Valkey service external primary host + ## + externalPrimary: + enabled: false + host: "" + port: 6379 + ## @param sentinel.containerPorts.sentinel Container port to open on Valkey Sentinel nodes + ## + containerPorts: + sentinel: 26379 + ## Configure extra options for Valkey containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param sentinel.startupProbe.enabled Enable startupProbe on Valkey Sentinel nodes + ## @param sentinel.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param sentinel.startupProbe.periodSeconds Period seconds for startupProbe + ## @param sentinel.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param sentinel.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param sentinel.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: true + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 22 + ## @param sentinel.livenessProbe.enabled Enable livenessProbe on Valkey Sentinel nodes + ## @param sentinel.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param sentinel.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param sentinel.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param sentinel.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param sentinel.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 6 + ## @param sentinel.readinessProbe.enabled Enable readinessProbe on Valkey Sentinel nodes + ## @param sentinel.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param sentinel.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param sentinel.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param sentinel.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param sentinel.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 6 + ## @param sentinel.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param sentinel.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param sentinel.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## Persistence parameters + ## ref: https://kubernetes.io/docs/concepts/storage/persistent-volumes/ + ## + persistence: + ## @param sentinel.persistence.enabled Enable persistence on Valkey sentinel nodes using Persistent Volume Claims (Experimental) + ## + enabled: false + ## @param sentinel.persistence.storageClass 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 + ## + storageClass: "" + ## @param sentinel.persistence.accessModes Persistent Volume access modes + ## + accessModes: + - ReadWriteOnce + ## @param sentinel.persistence.size Persistent Volume size + ## + size: 100Mi + ## @param sentinel.persistence.annotations Additional custom annotations for the PVC + ## + annotations: {} + ## @param sentinel.persistence.labels Additional custom labels for the PVC + ## + labels: {} + ## @param sentinel.persistence.selector Additional labels to match for the PVC + ## e.g: + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## @param sentinel.persistence.dataSource Custom PVC data source + ## + dataSource: {} + ## @param sentinel.persistence.medium Provide a medium for `emptyDir` volumes. + ## + medium: "" + ## @param sentinel.persistence.sizeLimit Set this to enable a size limit for `emptyDir` volumes. + ## + sizeLimit: "" + ## persistentVolumeClaimRetentionPolicy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention + ## @param sentinel.persistentVolumeClaimRetentionPolicy.enabled Controls if and how PVCs are deleted during the lifecycle of a StatefulSet + ## @param sentinel.persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced + ## @param sentinel.persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted + ## + persistentVolumeClaimRetentionPolicy: + enabled: false + whenScaled: Retain + whenDeleted: Retain + ## Valkey Sentinel resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param sentinel.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if sentinel.resources is set (sentinel.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param sentinel.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param sentinel.containerSecurityContext.enabled Enabled Valkey Sentinel containers' Security Context + ## @param sentinel.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param sentinel.containerSecurityContext.runAsUser Set Valkey Sentinel containers' Security Context runAsUser + ## @param sentinel.containerSecurityContext.runAsGroup Set Valkey Sentinel containers' Security Context runAsGroup + ## @param sentinel.containerSecurityContext.runAsNonRoot Set Valkey Sentinel containers' Security Context runAsNonRoot + ## @param sentinel.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context read-only root filesystem + ## @param sentinel.containerSecurityContext.allowPrivilegeEscalation Set Valkey Sentinel containers' Security Context allowPrivilegeEscalation + ## @param sentinel.containerSecurityContext.seccompProfile.type Set Valkey Sentinel containers' Security Context seccompProfile + ## @param sentinel.containerSecurityContext.capabilities.drop Set Valkey Sentinel containers' Security Context capabilities to drop + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + seccompProfile: + type: RuntimeDefault + capabilities: + drop: ["ALL"] + ## @param sentinel.lifecycleHooks for the Valkey sentinel container(s) to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param sentinel.extraVolumes Optionally specify extra list of additional volumes for the Valkey Sentinel + ## + extraVolumes: [] + ## @param sentinel.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the Valkey Sentinel container(s) + ## + extraVolumeMounts: [] + ## Valkey Sentinel service parameters + ## + service: + ## @param sentinel.service.type Valkey Sentinel service type + ## + type: ClusterIP + ## @param sentinel.service.ports.valkey Valkey service port for Valkey + ## @param sentinel.service.ports.sentinel Valkey service port for Valkey Sentinel + ## + ports: + valkey: 6379 + sentinel: 26379 + ## @param sentinel.service.nodePorts.valkey Node port for Valkey + ## @param sentinel.service.nodePorts.sentinel Node port for Sentinel + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## NOTE: choose port between <30000-32767> + ## NOTE: By leaving these values blank, they will be generated by ports-configmap + ## If setting manually, please leave at least replica.replicaCount + 1 in between sentinel.service.nodePorts.valkey and sentinel.service.nodePorts.sentinel to take into account the ports that will be created while incrementing that base port + ## + nodePorts: + valkey: "" + sentinel: "" + ## @param sentinel.service.externalTrafficPolicy Valkey Sentinel service external traffic policy + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param sentinel.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param sentinel.service.clusterIP Valkey Sentinel service Cluster IP + ## + clusterIP: "" + + ## @param sentinel.service.createPrimary Enable primary service pointing to the current primary (experimental) + ## NOTE: rbac.create need to be set to true + ## + createPrimary: false + + ## @param sentinel.service.loadBalancerIP Valkey Sentinel service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param sentinel.service.loadBalancerClass sentinel service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerClass: "" + ## @param sentinel.service.loadBalancerSourceRanges Valkey Sentinel service Load Balancer sources + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g. + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param sentinel.service.annotations Additional custom annotations for Valkey Sentinel service + ## + annotations: {} + ## @param sentinel.service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param sentinel.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## Headless service properties + ## + headless: + ## @param sentinel.service.headless.annotations Annotations for the headless service. + ## + annotations: {} + ## @param sentinel.terminationGracePeriodSeconds Integer setting the termination grace period for the valkey-node pods + ## + terminationGracePeriodSeconds: 30 +## @section Other Parameters +## + +## @param serviceBindings.enabled Create secret for service binding (Experimental) +## Ref: https://servicebinding.io/service-provider/ +## +serviceBindings: + enabled: false +## Network Policy configuration +## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ +## +networkPolicy: + ## @param networkPolicy.enabled Enable creation of NetworkPolicy resources + ## + enabled: true + ## @param networkPolicy.allowExternal Don't require client label for connections + ## When set to false, only pods with the correct client label will have network access to the ports + ## Valkey is listening on. When true, Valkey will accept connections from any source + ## (with the correct destination port). + ## + allowExternal: true + ## @param networkPolicy.allowExternalEgress Allow the pod to access any range of port and all destinations. + ## + allowExternalEgress: true + ## @param networkPolicy.extraIngress Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraIngress: + ## - ports: + ## - port: 1234 + ## from: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraIngress: [] + ## @param networkPolicy.extraEgress Add extra egress rules to the NetworkPolicy + ## e.g: + ## extraEgress: + ## - ports: + ## - port: 1234 + ## to: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraEgress: [] + ## @param networkPolicy.ingressNSMatchLabels Labels to match to allow traffic from other namespaces + ## @param networkPolicy.ingressNSPodMatchLabels Pod labels to match to allow traffic from other namespaces + ## + ingressNSMatchLabels: {} + ingressNSPodMatchLabels: {} + metrics: + ## @param networkPolicy.metrics.allowExternal Don't require client label for connections for metrics endpoint + ## When set to false, only pods with the correct client label will have network access to the metrics port + ## + allowExternal: true + ## @param networkPolicy.metrics.ingressNSMatchLabels Labels to match to allow traffic from other namespaces to metrics endpoint + ## @param networkPolicy.metrics.ingressNSPodMatchLabels Pod labels to match to allow traffic from other namespaces to metrics endpoint + ## + ingressNSMatchLabels: {} + ingressNSPodMatchLabels: {} +## PodSecurityPolicy configuration +## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ +## +podSecurityPolicy: + ## @param podSecurityPolicy.create Whether to create a PodSecurityPolicy. WARNING: PodSecurityPolicy is deprecated in Kubernetes v1.21 or later, unavailable in v1.25 or later + ## + create: false + ## @param podSecurityPolicy.enabled Enable PodSecurityPolicy's RBAC rules + ## + enabled: false +## RBAC configuration +## +rbac: + ## @param rbac.create Specifies whether RBAC resources should be created + ## + create: false + ## @param rbac.rules Custom RBAC rules to set + ## e.g: + ## rules: + ## - apiGroups: + ## - "" + ## resources: + ## - pods + ## verbs: + ## - get + ## - list + ## + rules: [] +## ServiceAccount configuration +## +serviceAccount: + ## @param serviceAccount.create Specifies whether a ServiceAccount should be created + ## + create: true + ## @param serviceAccount.name The name of the ServiceAccount to use. + ## If not set and create is true, a name is generated using the common.names.fullname template + ## + name: "" + ## @param serviceAccount.automountServiceAccountToken Whether to auto mount the service account token + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server + ## + automountServiceAccountToken: false + ## @param serviceAccount.annotations Additional custom annotations for the ServiceAccount + ## + annotations: {} +## Redis® Pod Disruption Budget configuration +## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ +## @param pdb DEPRECATED Please use `primary.pdb` and `replica.pdb` values instead +## +pdb: {} +## TLS configuration +## +tls: + ## @param tls.enabled Enable TLS traffic + ## + enabled: false + ## @param tls.authClients Require clients to authenticate + ## + authClients: true + ## @param tls.autoGenerated Enable autogenerated certificates + ## + autoGenerated: false + ## @param tls.existingSecret The name of the existing secret that contains the TLS certificates + ## + existingSecret: "" + ## @param tls.certFilename Certificate filename + ## + certFilename: "" + ## @param tls.certKeyFilename Certificate Key filename + ## + certKeyFilename: "" + ## @param tls.certCAFilename CA Certificate filename + ## + certCAFilename: "" + ## @param tls.dhParamsFilename File containing DH params (in order to support DH based ciphers) + ## + dhParamsFilename: "" +## @section Metrics Parameters +## +metrics: + ## @param metrics.enabled Start a sidecar prometheus exporter to expose Valkey metrics + ## + enabled: false + ## Bitnami Valkey Exporter image + ## ref: https://hub.docker.com/r/bitnami/valkey-exporter/tags/ + ## @param metrics.image.registry [default: REGISTRY_NAME] Valkey Exporter image registry + ## @param metrics.image.repository [default: REPOSITORY_NAME/valkey-exporter] Valkey Exporter image repository + ## @skip metrics.image.tag Valkey Exporter image tag (immutable tags are recommended) + ## @param metrics.image.digest Valkey Exporter image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param metrics.image.pullPolicy Valkey Exporter image pull policy + ## @param metrics.image.pullSecrets Valkey Exporter image pull secrets + ## + image: + registry: docker.io + repository: bitnami/redis-exporter + tag: 1.76.0-debian-12-r0 + digest: "" + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## @param metrics.containerPorts.http Metrics HTTP container port + ## + containerPorts: + http: 9121 + ## Configure extra options for Valkey containers' liveness, readiness & startup probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ + ## @param metrics.startupProbe.enabled Enable startupProbe on Valkey replicas nodes + ## @param metrics.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param metrics.startupProbe.periodSeconds Period seconds for startupProbe + ## @param metrics.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param metrics.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param metrics.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param metrics.livenessProbe.enabled Enable livenessProbe on Valkey replicas nodes + ## @param metrics.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param metrics.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param metrics.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param metrics.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param metrics.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param metrics.readinessProbe.enabled Enable readinessProbe on Valkey replicas nodes + ## @param metrics.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param metrics.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param metrics.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param metrics.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param metrics.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 3 + ## @param metrics.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param metrics.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param metrics.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param metrics.command Override default metrics container init command (useful when using custom images) + ## + command: [] + ## @param metrics.valkeyTargetHost A way to specify an alternative Valkey hostname + ## Useful for certificate CN/SAN matching + ## + valkeyTargetHost: "localhost" + ## @param metrics.extraArgs Extra arguments for Valkey exporter, for example: + ## e.g.: + ## extraArgs: + ## check-keys: myKey,myOtherKey + ## + extraArgs: {} + ## @param metrics.extraEnvVars Array with extra environment variables to add to Valkey exporter + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param metrics.containerSecurityContext.enabled Enabled Valkey exporter containers' Security Context + ## @param metrics.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param metrics.containerSecurityContext.runAsUser Set Valkey exporter containers' Security Context runAsUser + ## @param metrics.containerSecurityContext.runAsGroup Set Valkey exporter containers' Security Context runAsGroup + ## @param metrics.containerSecurityContext.runAsNonRoot Set Valkey exporter containers' Security Context runAsNonRoot + ## @param metrics.containerSecurityContext.allowPrivilegeEscalation Set Valkey exporter containers' Security Context allowPrivilegeEscalation + ## @param metrics.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context read-only root filesystem + ## @param metrics.containerSecurityContext.seccompProfile.type Set Valkey exporter containers' Security Context seccompProfile + ## @param metrics.containerSecurityContext.capabilities.drop Set Valkey exporter containers' Security Context capabilities to drop + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + seccompProfile: + type: RuntimeDefault + capabilities: + drop: ["ALL"] + ## @param metrics.extraVolumes Optionally specify extra list of additional volumes for the Valkey metrics sidecar + ## + extraVolumes: [] + ## @param metrics.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the Valkey metrics sidecar + ## + extraVolumeMounts: [] + ## Valkey exporter resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param metrics.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if metrics.resources is set (metrics.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param metrics.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## @param metrics.podLabels Extra labels for Valkey exporter pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param metrics.podAnnotations [object] Annotations for Valkey exporter pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: + prometheus.io/scrape: "true" + prometheus.io/port: "9121" + ## Valkey exporter service parameters + ## + service: + ## @param metrics.service.enabled Create Service resource(s) for scraping metrics using PrometheusOperator ServiceMonitor, can be disabled when using a PodMonitor + ## + enabled: true + ## @param metrics.service.type Valkey exporter service type + ## + type: ClusterIP + ## @param metrics.service.ports.http Valkey exporter service port + ## + ports: + http: 9121 + ## @param metrics.service.externalTrafficPolicy Valkey exporter service external traffic policy + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param metrics.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param metrics.service.loadBalancerIP Valkey exporter service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param metrics.service.loadBalancerClass exporter service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerClass: "" + ## @param metrics.service.loadBalancerSourceRanges Valkey exporter service Load Balancer sources + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g. + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param metrics.service.annotations Additional custom annotations for Valkey exporter service + ## + annotations: {} + ## @param metrics.service.clusterIP Valkey exporter service Cluster IP + ## + clusterIP: "" + ## Prometheus Service Monitor + ## ref: https://github.com/coreos/prometheus-operator + ## https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint + ## + serviceMonitor: + ## @param metrics.serviceMonitor.port the service port to scrape metrics from + ## + port: http-metrics + ## @param metrics.serviceMonitor.enabled Create ServiceMonitor resource(s) for scraping metrics using PrometheusOperator + ## + enabled: false + ## @param metrics.serviceMonitor.namespace The namespace in which the ServiceMonitor will be created + ## + namespace: "" + ## @param metrics.serviceMonitor.interval The interval at which metrics should be scraped + ## + interval: 30s + ## @param metrics.serviceMonitor.scrapeTimeout The timeout after which the scrape is ended + ## + scrapeTimeout: "" + ## @param metrics.serviceMonitor.relabelings Metrics RelabelConfigs to apply to samples before scraping. + ## + relabelings: [] + ## @param metrics.serviceMonitor.metricRelabelings Metrics RelabelConfigs to apply to samples before ingestion. + ## + metricRelabelings: [] + ## @param metrics.serviceMonitor.honorLabels Specify honorLabels parameter to add the scrape endpoint + ## + honorLabels: false + ## @param metrics.serviceMonitor.additionalLabels Additional labels that can be used so ServiceMonitor resource(s) can be discovered by Prometheus + ## + additionalLabels: {} + ## @param metrics.serviceMonitor.podTargetLabels Labels from the Kubernetes pod to be transferred to the created metrics + ## + podTargetLabels: [] + ## @param metrics.serviceMonitor.sampleLimit Limit of how many samples should be scraped from every Pod + ## + sampleLimit: false + ## @param metrics.serviceMonitor.targetLimit Limit of how many targets should be scraped + ## + targetLimit: false + ## @param metrics.serviceMonitor.additionalEndpoints Additional endpoints to scrape (e.g sentinel) + ## + additionalEndpoints: [] + # uncomment in order to scrape sentinel metrics, also to in order distinguish between Sentinel and Valkey container metrics + # add metricRelabelings with label like app=valkey to main valkey pod-monitor port + # - interval: "30s" + # path: "/scrape" + # port: "metrics" + # params: + # target: ["localhost:26379"] + # metricRelabelings: + # - targetLabel: "app" + # replacement: "sentinel" + ## Prometheus Pod Monitor + ## ref: https://github.com/coreos/prometheus-operator + ## https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#podmonitor + ## + podMonitor: + ## @param metrics.podMonitor.port the pod port to scrape metrics from + ## + port: metrics + ## @param metrics.podMonitor.enabled Create PodMonitor resource(s) for scraping metrics using PrometheusOperator + ## + enabled: false + ## @param metrics.podMonitor.namespace The namespace in which the PodMonitor will be created + ## + namespace: "" + ## @param metrics.podMonitor.interval The interval at which metrics should be scraped + ## + interval: 30s + ## @param metrics.podMonitor.scrapeTimeout The timeout after which the scrape is ended + ## + scrapeTimeout: "" + ## @param metrics.podMonitor.relabelings Metrics RelabelConfigs to apply to samples before scraping. + ## + relabelings: [] + ## @param metrics.podMonitor.metricRelabelings Metrics RelabelConfigs to apply to samples before ingestion. + ## + metricRelabelings: [] + # - targetLabel: "app" + # replacement: "valkey" + ## @param metrics.podMonitor.honorLabels Specify honorLabels parameter to add the scrape endpoint + ## + honorLabels: false + ## @param metrics.podMonitor.additionalLabels Additional labels that can be used so PodMonitor resource(s) can be discovered by Prometheus + ## + additionalLabels: {} + ## @param metrics.podMonitor.podTargetLabels Labels from the Kubernetes pod to be transferred to the created metrics + ## + podTargetLabels: [] + ## @param metrics.podMonitor.sampleLimit Limit of how many samples should be scraped from every Pod + ## + sampleLimit: false + ## @param metrics.podMonitor.targetLimit Limit of how many targets should be scraped + ## + targetLimit: false + ## @param metrics.podMonitor.additionalEndpoints Additional endpoints to scrape (e.g sentinel) + ## + additionalEndpoints: [] + # - interval: "30s" + # path: "/scrape" + # port: "metrics" + # params: + # target: ["localhost:26379"] + # metricRelabelings: + # - targetLabel: "app" + # replacement: "sentinel" + ## Custom PrometheusRule to be defined + ## ref: https://github.com/coreos/prometheus-operator#customresourcedefinitions + ## + prometheusRule: + ## @param metrics.prometheusRule.enabled Create a custom prometheusRule Resource for scraping metrics using PrometheusOperator + ## + enabled: false + ## @param metrics.prometheusRule.namespace The namespace in which the prometheusRule will be created + ## + namespace: "" + ## @param metrics.prometheusRule.additionalLabels Additional labels for the prometheusRule + ## + additionalLabels: {} + ## @param metrics.prometheusRule.rules Custom Prometheus rules + ## e.g: + ## rules: + ## - alert: ValkeyDown + ## expr: valkey_up{service="{{ template "common.names.fullname" . }}-metrics"} == 0 + ## for: 2m + ## labels: + ## severity: error + ## annotations: + ## summary: Valkey instance {{ "{{ $labels.instance }}" }} down + ## description: Valkey instance {{ "{{ $labels.instance }}" }} is down + ## - alert: ValkeyMemoryHigh + ## expr: > + ## valkey_memory_used_bytes{service="{{ template "common.names.fullname" . }}-metrics"} * 100 + ## / + ## valkey_memory_max_bytes{service="{{ template "common.names.fullname" . }}-metrics"} + ## > 90 + ## for: 2m + ## labels: + ## severity: error + ## annotations: + ## summary: Valkey instance {{ "{{ $labels.instance }}" }} is using too much memory + ## description: | + ## Valkey instance {{ "{{ $labels.instance }}" }} is using {{ "{{ $value }}" }}% of its available memory. + ## - alert: ValkeyKeyEviction + ## expr: | + ## increase(valkey_evicted_keys_total{service="{{ template "common.names.fullname" . }}-metrics"}[5m]) > 0 + ## for: 1s + ## labels: + ## severity: error + ## annotations: + ## summary: Valkey instance {{ "{{ $labels.instance }}" }} has evicted keys + ## description: | + ## Valkey instance {{ "{{ $labels.instance }}" }} has evicted {{ "{{ $value }}" }} keys in the last 5 minutes. + ## + rules: [] +## @section Init Container Parameters +## + +## 'volumePermissions' init container parameters +## Changes the owner and group of the persistent volume mount point to runAsUser:fsGroup values +## based on the *podSecurityContext/*containerSecurityContext parameters +## +volumePermissions: + ## @param volumePermissions.enabled Enable init container that changes the owner/group of the PV mount point to `runAsUser:fsGroup` + ## + enabled: false + ## OS Shell + Utility image + ## ref: https://hub.docker.com/r/bitnami/os-shell/tags/ + ## @param volumePermissions.image.registry [default: REGISTRY_NAME] OS Shell + Utility image registry + ## @param volumePermissions.image.repository [default: REPOSITORY_NAME/os-shell] OS Shell + Utility image repository + ## @skip volumePermissions.image.tag OS Shell + Utility image tag (immutable tags are recommended) + ## @param volumePermissions.image.digest OS Shell + Utility image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param volumePermissions.image.pullPolicy OS Shell + Utility image pull policy + ## @param volumePermissions.image.pullSecrets OS Shell + Utility image pull secrets + ## + image: + registry: docker.io + repository: bitnami/os-shell + tag: 12-debian-12-r51 + digest: "" + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Init container's resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param volumePermissions.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if volumePermissions.resources is set (volumePermissions.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param volumePermissions.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Init container Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param volumePermissions.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param volumePermissions.containerSecurityContext.runAsUser Set init container's Security Context runAsUser + ## NOTE: when runAsUser is set to special value "auto", init container will try to chown the + ## data folder to auto-determined user&group, using commands: `id -u`:`id -G | cut -d" " -f2` + ## "auto" is especially useful for OpenShift which has scc with dynamic user ids (and 0 is not allowed) + ## + containerSecurityContext: + seLinuxOptions: {} + runAsUser: 0 + +## Kubectl InitContainer +## used by Sentinel to update the isPrimary label on the Valkey(TM) pods +## +kubectl: + ## Bitnami Kubectl image version + ## ref: https://hub.docker.com/r/bitnami/kubectl/tags/ + ## @param kubectl.image.registry [default: REGISTRY_NAME] Kubectl image registry + ## @param kubectl.image.repository [default: REPOSITORY_NAME/kubectl] Kubectl image repository + ## @skip kubectl.image.tag Kubectl image tag (immutable tags are recommended), by default, using the current version + ## @param kubectl.image.digest Kubectl image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param kubectl.image.pullPolicy Kubectl image pull policy + ## @param kubectl.image.pullSecrets Kubectl pull secrets + ## + image: + registry: docker.io + repository: bitnami/kubectl + tag: 1.33.4-debian-12-r0 + digest: "" + ## Specify a imagePullPolicy + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## @param kubectl.command kubectl command to execute + ## + command: ["/opt/bitnami/scripts/kubectl-scripts/update-primary-label.sh"] + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param kubectl.containerSecurityContext.enabled Enabled kubectl containers' Security Context + ## @param kubectl.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param kubectl.containerSecurityContext.runAsUser Set kubectl containers' Security Context runAsUser + ## @param kubectl.containerSecurityContext.runAsGroup Set kubectl containers' Security Context runAsGroup + ## @param kubectl.containerSecurityContext.runAsNonRoot Set kubectl containers' Security Context runAsNonRoot + ## @param kubectl.containerSecurityContext.allowPrivilegeEscalation Set kubectl containers' Security Context allowPrivilegeEscalation + ## @param kubectl.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context read-only root filesystem + ## @param kubectl.containerSecurityContext.seccompProfile.type Set kubectl containers' Security Context seccompProfile + ## @param kubectl.containerSecurityContext.capabilities.drop Set kubectl containers' Security Context capabilities to drop + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + seccompProfile: + type: RuntimeDefault + capabilities: + drop: ["ALL"] + ## Bitnami Kubectl resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param kubectl.resources.limits The resources limits for the kubectl containers + ## @param kubectl.resources.requests The requested resources for the kubectl containers + ## + resources: + limits: {} + requests: {} +## @section useExternalDNS Parameters +## +## @param useExternalDNS.enabled Enable various syntax that would enable external-dns to work. Note this requires a working installation of `external-dns` to be usable. +## @param useExternalDNS.additionalAnnotations Extra annotations to be utilized when `external-dns` is enabled. +## @param useExternalDNS.annotationKey The annotation key utilized when `external-dns` is enabled. Setting this to `false` will disable annotations. +## @param useExternalDNS.suffix The DNS suffix utilized when `external-dns` is enabled. Note that we prepend the suffix with the full name of the release. +## +useExternalDNS: + enabled: false + suffix: "" + annotationKey: external-dns.alpha.kubernetes.io/ + additionalAnnotations: {} diff --git a/backing-services/gitea/docs/ha-setup.md b/backing-services/gitea/docs/ha-setup.md new file mode 100644 index 0000000..99b87e6 --- /dev/null +++ b/backing-services/gitea/docs/ha-setup.md @@ -0,0 +1,178 @@ +# High Availability + +All components (in-memory DB, volume/asset storage, code indexer) used by Gitea must be deployed in a HA-ready fashion to achieve a full HA-ready Gitea deployment. +The following document explains how to achieve this for all individual components. + +The resulting Gitea deployment will consist of ~ 10 pods (depending on the chosen components and their replicas). +One should evaluate upfront whether a HA-deployment is required as switching between HA/non-HA comes with some effort. +For production instances, HA is always recommended to increase uptime and have a frictionless update process. + +A general comment about chart dependencies and external services: +Instead of relying on chart dependencies, it is often better to rely on an external, (managed) instances (in-memory database, asset storage provider, database, etc.). +Many cloud providers offer such services, at least for databases or in-memory databases. +They might cost a bit more than using a self-hosted k8s variant but are usually easier to maintain and scale, if needed. +Also they can be centrally managed and are not linked to the Gitea helm chart or namespace. +Please consider using external services before you start with your Gitea HA setup, it will make your life (and the life of the Gitea maintainers) easier. + +This helm chart tries to help as much as possible to simplify and assert the provisioning of a HA-ready Gitea instance by implementing smart conditionals if `replicaCount` is set to a value > 1. +Nevertheless, we cannot guarantee for every possible combination of Gitea settings to work together perfectly in a HA setup. +As a general advice, we recommend to have a test environment aside on which to test possible changes/upgrades before applying these to a production installation. + +## Requirements for HA + +Storage-wise, the HA-Gitea setup requires a RWX file-system which can be shared among the deployment-based replica pods. +In addition, the following components are required for full HA-readiness: + +- A HA-ready issue (and optionally code) indexer: `elasticsearch` or `meilisearch` +- A HA-ready external object/asset storage (`minio`) (optional, assets can also be stored on the RWX file-system) +- A HA-ready cache (`valkey-cluster`) +- A HA-ready DB + +`postgres.enabled`, which default to `true`, must be set to `false` for a HA setup. +The default `postgres` chart dependency is not HA-ready (there's a dedicated `postgres-ha` chart). + +The following sections discuss each of the components in more detail. +Note that for each component discussed, the shown configurations only provides a (working) starting point, not necessarily the most optimal setup. +We try to optimize this document over time as we have gained more experience with HA setups from users. + +## Indexers (Issues and code/repo) + +The default code indexer `bleve` is not able to allow multiple connections and hence cannot be used in a HA setup. +Alternatives are `elasticsearch` and `meilisearch` (as of >= 1.19.2). +Unless you have an existing `elasticsearch` cluster, we recommend using `meilisearch` as it is faster and requires way less resources. + +Unfortunately, `meilisearch` does only support the `ISSUE_INDEXER` and not the `REPO_INDEXER` yet ([tracking issue](https://github.com/go-gitea/gitea/pull/24149)). +This means that the `REPO_INDEXER` must still be disabled for a HA setup right now. +An alternative to the two options above for the `ISSUE_INDEXER` is `"db"`, however we recommend to just go with `meilisearch` in this case and to not bother the DB with indexing. + +To configure `meilisearch` within Gitea, do the following: + +```yml +gitea: + config: + indexer: + ISSUE_INDEXER_CONN_STR: .svc.cluster.local:7700> + ISSUE_INDEXER_ENABLED: true + ISSUE_INDEXER_TYPE: meilisearch + REPO_INDEXER_ENABLED: false + # REPO_INDEXER_TYPE: meilisearch # not yet working +``` + +Unfortunately `meilisearch` cannot be deployed in HA as of now. +Nevertheless it allows for multiple Gitea requests at the same time and is therefore required in a HA setup. + +Exemplary configuration for the [meilisearch-kubernetes](https://github.com/meilisearch/meilisearch-kubernetes/tree/main/charts/meilisearch) chart: + +```yaml +persistence: + enabled: true + accessMode: ReadWriteOnce + size: 5Gi +``` + +## Cache, session and queue + +A `valkey` instance is required for the in-memory cache. +Two options exist: + +- `valkey` +- `valkey-cluster` + +The chart provides `valkey-cluster` as a dependency as this one can be used for both HA and non-HA setups. +You're also welcome to go with `valkey` if you prefer or already have a running instance. + +It should be noted that `valkey-cluster` support is only available starting with Gitea 1.19.2. +You can also configure an external (managed) `valkey` instance to be used. +To do so, you need to set the following configuration values yourself: + +- `gitea.config.queue.TYPE`: valkey` +- `gitea.config.queue.CONN_STR`: `` + +- `gitea.config.session.PROVIDER`: `valkey` +- `gitea.config.session.PROVIDER_CONFIG`: `` + +- `gitea.config.cache.ENABLED`: `true` +- `gitea.config.cache.ADAPTER`: `valkey` +- `gitea.config.cache.HOST`: `` + +By default, the `valkey-cluster` chart provisions three standalone master nodes of which each has a single replica. +To reduce the number of pods for a default Gitea deployment, we opted to omit the replicas (`replicas: 0`) by default. +Only the minimum required number of master pods for a functional `valkey-cluster` deployment are provisioned. +For a "proper" `valkey-cluster` setup however, we recommend to set `replicas: 1` and `nodes: 6`. + +## Object and asset storage + +Object/asset storage refers to the storage of attachments, avatars, LFS files, etc. +While most of these can be stored on the RWX file-system, it is recommended to use an external S3-compatible object storage for such, mainly for performance reasons. + +By default the chart provisions a single RWO volume to store everything (repos, avatars, packages, etc.). +This volume cannot be mounted by multiple pods. +Hence, a RWX volume is required and (optionally) an external HA-ready object storage. + +> **Note:** Double-check that the file permissions are set correctly on the RWX volume! That is everything should be owned by the `git` user which usually has `uid=1000` and `gid=1000`. + +To use `minio` you need to deploy and configure an external `minio` instance yourself and explicitly define the `STORAGE_TYPE` values as shown below. + +Note that `MINIO_BUCKET` here is just a name and does not refer to a S3 bucket. +It's the root access point for all objects belonging to the respective application, i.e., to Gitea in this case. + +```yaml +gitea: + config: + attachment: + STORAGE_TYPE: minio + lfs: + STORAGE_TYPE: minio + picture: + AVATAR_STORAGE_TYPE: minio + "storage.packages": + STORAGE_TYPE: minio + + storage: + MINIO_ENDPOINT: .svc.cluster.local:9000> + MINIO_LOCATION: + MINIO_ACCESS_KEY_ID: + MINIO_SECRET_ACCESS_KEY: + MINIO_BUCKET: + MINIO_USE_SSL: false +``` + +Exemplary configuration for the [bitnami minio](https://github.com/bitnami/charts/blob/main/bitnami/minio) chart: + +```yaml +auth: + rootUser: minio +mode: distributed +replicaCount: 4 +persistence: + enabled: true + size: 20Gi + accessModes: + - ReadWriteOnce +``` + +## Database + +If you do not have an HA-ready DB, using a managed database service in the cloud might be the easiest and most robust solution. +Remember: disable the built-in `postgres` dependency and configure the database connection manually via `gitea.config.database`: + +```yml +gitea: + database: + builtIn: + postgresql: + enabled: false + config: + database: + DB_TYPE: postgres + HOST: + NAME: + USER: +``` + +## Known issues + +- Currently Cron jobs are run on all replicas as no leader election is implemented. + See [https://github.com/go-gitea/gitea/issues/13791](https://github.com/go-gitea/gitea/issues/13791) for a discussion and possible solution. + +- Running with multiple replicas slows down Gitea a bit, i.e. page loading time increases. \ No newline at end of file diff --git a/backing-services/gitea/install-man-page.sh b/backing-services/gitea/install-man-page.sh new file mode 100644 index 0000000..82715ec --- /dev/null +++ b/backing-services/gitea/install-man-page.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +my_path="$(command -v yq)" + +if [ -z "$my_path" ]; then + echo "'yq' wasn't found in your PATH, so we don't know where to put the man pages." + echo "Please update your PATH to include yq, and run this script again." + exit 1 +fi + +# ex: ~/.local/bin/yq => ~/.local/ +my_prefix="$(dirname "$(dirname "$(command -v yq)")")" +mkdir -p "$my_prefix/share/man/man1/" +cp yq.1 "$my_prefix/share/man/man1/" diff --git a/backing-services/gitea/scripts/act_runner/token.sh b/backing-services/gitea/scripts/act_runner/token.sh new file mode 100644 index 0000000..cbb2ebd --- /dev/null +++ b/backing-services/gitea/scripts/act_runner/token.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +set -eu + +timeout_delay=15 + +check_token() { + set +e + + echo "Checking for existing token..." + token="$(kubectl get secret "$SECRET_NAME" -o jsonpath="{.data['token']}" 2> /dev/null)" + [ $? -ne 0 ] && return 1 + [ -z "$token" ] && return 2 + return 0 +} + +create_token() { + echo "Waiting for new token to be generated..." + begin=$(date +%s) + end=$((begin + timeout_delay)) + while true; do + [ -f /data/actions/token ] && return 0 + [ "$(date +%s)" -gt $end ] && return 1 + sleep 5 + done +} + +store_token() { + echo "Storing the token in Kubernetes secret..." + kubectl patch secret "$SECRET_NAME" -p "{\"data\":{\"token\":\"$(base64 /data/actions/token | tr -d '\n')\"}}" +} + +if check_token; then + echo "Key already in place, exiting." + exit +fi + +if ! create_token; then + echo "Checking for an existing act runner token in secret $SECRET_NAME timed out after $timeout_delay" + exit 1 +fi + +store_token diff --git a/backing-services/gitea/scripts/init-containers/config/config_environment.sh b/backing-services/gitea/scripts/init-containers/config/config_environment.sh new file mode 100644 index 0000000..ed00ea6 --- /dev/null +++ b/backing-services/gitea/scripts/init-containers/config/config_environment.sh @@ -0,0 +1,154 @@ +#!/usr/bin/env bash +set -euo pipefail + +function env2ini::log() { + printf "${1}\n" +} + +function env2ini::read_config_to_env() { + local section="${1}" + local line="${2}" + + if [[ -z "${line}" ]]; then + # skip empty line + return + fi + + # 'xargs echo -n' trims all leading/trailing whitespaces and a trailing new line + local setting="$(awk -F '=' '{print $1}' <<< "${line}" | xargs echo -n)" + + if [[ -z "${setting}" ]]; then + env2ini::log ' ! invalid setting' + exit 1 + fi + + local value='' + local regex="^${setting}(\s*)=(\s*)(.*)" + if [[ $line =~ $regex ]]; then + value="${BASH_REMATCH[3]}" + else + env2ini::log ' ! invalid setting' + exit 1 + fi + + env2ini::log " + '${setting}'" + + if [[ -z "${section}" ]]; then + export "GITEA____${setting^^}=${value}" # '^^' makes the variable content uppercase + return + fi + + local masked_section="${section//./_0X2E_}" # '//' instructs to replace all matches + masked_section="${masked_section//-/_0X2D_}" + + export "GITEA__${masked_section^^}__${setting^^}=${value}" # '^^' makes the variable content uppercase +} + +function env2ini::reload_preset_envs() { + env2ini::log "Reloading preset envs..." + + while read -r line; do + if [[ -z "${line}" ]]; then + # skip empty line + return + fi + + # 'xargs echo -n' trims all leading/trailing whitespaces and a trailing new line + local setting="$(awk -F '=' '{print $1}' <<< "${line}" | xargs echo -n)" + + if [[ -z "${setting}" ]]; then + env2ini::log ' ! invalid setting' + exit 1 + fi + + local value='' + local regex="^${setting}(\s*)=(\s*)(.*)" + if [[ $line =~ $regex ]]; then + value="${BASH_REMATCH[3]}" + else + env2ini::log ' ! invalid setting' + exit 1 + fi + + env2ini::log " + '${setting}'" + + export "${setting^^}=${value}" # '^^' makes the variable content uppercase + done < "$TMP_EXISTING_ENVS_FILE" + + rm $TMP_EXISTING_ENVS_FILE +} + + +function env2ini::process_config_file() { + local config_file="${1}" + local section="$(basename "${config_file}")" + + if [[ $section == '_generals_' ]]; then + env2ini::log " [ini root]" + section='' + else + env2ini::log " ${section}" + fi + + while read -r line; do + env2ini::read_config_to_env "${section}" "${line}" + done < <(awk 1 "${config_file}") # Helm .toYaml trims the trailing new line which breaks line processing; awk 1 ... adds it back while reading +} + +function env2ini::load_config_sources() { + local path="${1}" + + if [[ -d "${path}" ]]; then + env2ini::log "Processing $(basename "${path}")..." + + while read -d '' configFile; do + env2ini::process_config_file "${configFile}" + done < <(find "${path}" -type l -not -name '..data' -print0) + + env2ini::log "\n" + fi +} + +function env2ini::generate_initial_secrets() { + # These environment variables will either be + # - overwritten with user defined values, + # - initially used to set up Gitea + # Anyway, they won't harm existing app.ini files + + export GITEA__SECURITY__INTERNAL_TOKEN=$(gitea generate secret INTERNAL_TOKEN) + export GITEA__SECURITY__SECRET_KEY=$(gitea generate secret SECRET_KEY) + export GITEA__OAUTH2__JWT_SECRET=$(gitea generate secret JWT_SECRET) + export GITEA__SERVER__LFS_JWT_SECRET=$(gitea generate secret LFS_JWT_SECRET) + + env2ini::log "...Initial secrets generated\n" +} + +# save existing envs prior to script execution. Necessary to keep order of preexisting and custom envs +env | (grep -e '^GITEA__' || [[ $? == 1 ]]) > $TMP_EXISTING_ENVS_FILE + +# MUST BE CALLED BEFORE OTHER CONFIGURATION +env2ini::generate_initial_secrets + +env2ini::load_config_sources "$ENV_TO_INI_MOUNT_POINT/inlines/" +env2ini::load_config_sources "$ENV_TO_INI_MOUNT_POINT/additionals/" + +# load existing envs to override auto generated envs +env2ini::reload_preset_envs + +env2ini::log "=== All configuration sources loaded ===\n" + +# safety to prevent rewrite of secret keys if an app.ini already exists +if [ -f ${GITEA_APP_INI} ]; then + env2ini::log 'An app.ini file already exists. To prevent overwriting secret keys, these settings are dropped and remain unchanged:' + env2ini::log ' - security.INTERNAL_TOKEN' + env2ini::log ' - security.SECRET_KEY' + env2ini::log ' - oauth2.JWT_SECRET' + env2ini::log ' - server.LFS_JWT_SECRET' + + unset GITEA__SECURITY__INTERNAL_TOKEN + unset GITEA__SECURITY__SECRET_KEY + unset GITEA__OAUTH2__JWT_SECRET + unset GITEA__SERVER__LFS_JWT_SECRET +fi + +environment-to-ini -o $GITEA_APP_INI diff --git a/backing-services/gitea/scripts/init-containers/init/configure_gpg_environment.sh b/backing-services/gitea/scripts/init-containers/init/configure_gpg_environment.sh new file mode 100644 index 0000000..894eb1d --- /dev/null +++ b/backing-services/gitea/scripts/init-containers/init/configure_gpg_environment.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -eu + +gpg --batch --import "$TMP_RAW_GPG_KEY" diff --git a/backing-services/gitea/templates/NOTES.txt b/backing-services/gitea/templates/NOTES.txt new file mode 100644 index 0000000..ad5a8fa --- /dev/null +++ b/backing-services/gitea/templates/NOTES.txt @@ -0,0 +1,36 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.http.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "gitea.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.http.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "gitea.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "gitea.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.http.type }} + echo "Visit http://127.0.0.1:{{ .Values.service.http.port }} to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward svc/{{ .Release.Name }}-http {{ .Values.service.http.port }}:{{ .Values.service.http.port }} +{{- end }} +{{- $warnings := list -}} +{{- if eq (get .Values.gitea.config.cache "ADAPTER") "memory" -}} + {{- $warnings = append $warnings "Gitea uses 'memory' for caching which is not recommended for production use. See https://docs.gitea.com/next/administration/config-cheat-sheet#cache-cache for available options." -}} +{{- end }} +{{- if eq (get .Values.gitea.config.queue "TYPE") "level" -}} + {{- $warnings = append $warnings "Gitea uses 'leveldb' for queue actions which is not recommended for production use. See https://docs.gitea.com/next/administration/config-cheat-sheet#queue-queue-and-queue for available options." -}} +{{- end }} +{{- if eq (get .Values.gitea.config.session "PROVIDER") "memory" -}} + {{- $warnings = append $warnings "Gitea uses 'memory' for sessions which is not recommended for production use. See https://docs.gitea.com/next/administration/config-cheat-sheet#session-session for available options." -}} +{{- end }} +{{- if gt (len $warnings) 0 }} +2. Review these warnings: +{{- range $warnings }} + - {{ . }} +{{- end }} +{{- end }} diff --git a/backing-services/gitea/templates/_helpers.tpl b/backing-services/gitea/templates/_helpers.tpl new file mode 100644 index 0000000..f993b95 --- /dev/null +++ b/backing-services/gitea/templates/_helpers.tpl @@ -0,0 +1,473 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} + +{{- define "gitea.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "gitea.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 worker name. +*/}} +{{- define "gitea.workername" -}} +{{- printf "%s-%s" .global.Release.Name .worker | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "gitea.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create image name and tag used by the deployment. +*/}} +{{- define "gitea.image" -}} +{{- $fullOverride := .Values.image.fullOverride | default "" -}} +{{- $registry := .Values.global.imageRegistry | default .Values.image.registry -}} +{{- $repository := .Values.image.repository -}} +{{- $separator := ":" -}} +{{- $tag := .Values.image.tag | default .Chart.AppVersion | toString -}} +{{- $rootless := ternary "-rootless" "" (.Values.image.rootless) -}} +{{- $digest := "" -}} +{{- if .Values.image.digest }} + {{- $digest = (printf "@%s" (.Values.image.digest | toString)) -}} +{{- end -}} +{{- if $fullOverride }} + {{- printf "%s" $fullOverride -}} +{{- else if $registry }} + {{- printf "%s/%s%s%s%s%s" $registry $repository $separator $tag $rootless $digest -}} +{{- else -}} + {{- printf "%s%s%s%s%s" $repository $separator $tag $rootless $digest -}} +{{- end -}} +{{- end -}} + +{{/* +Docker Image Registry Secret Names evaluating values as templates +*/}} +{{- define "gitea.images.pullSecrets" -}} +{{- $pullSecrets := .Values.imagePullSecrets -}} +{{- range .Values.global.imagePullSecrets -}} + {{- $pullSecrets = append $pullSecrets (dict "name" .) -}} +{{- end -}} +{{- if (not (empty $pullSecrets)) }} +imagePullSecrets: +{{ toYaml $pullSecrets }} +{{- end }} +{{- end -}} + + +{{/* +Storage Class +*/}} +{{- define "gitea.persistence.storageClass" -}} +{{- $storageClass := (tpl ( default "" .Values.persistence.storageClass) .) | default (tpl ( default "" .Values.global.storageClass) .) }} +{{- if $storageClass }} +storageClassName: {{ $storageClass | quote }} +{{- end }} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "gitea.labels" -}} +helm.sh/chart: {{ include "gitea.chart" . }} +app: {{ include "gitea.name" . }} +{{ include "gitea.selectorLabels" . }} +app.kubernetes.io/version: {{ .Values.image.tag | default .Chart.AppVersion | quote }} +version: {{ .Values.image.tag | default .Chart.AppVersion | quote }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{- define "gitea.labels.actRunner" -}} +helm.sh/chart: {{ include "gitea.chart" . }} +app: {{ include "gitea.name" . }}-act-runner +{{ include "gitea.selectorLabels.actRunner" . }} +app.kubernetes.io/version: {{ .Values.image.tag | default .Chart.AppVersion | quote }} +version: {{ .Values.image.tag | default .Chart.AppVersion | quote }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "gitea.selectorLabels" -}} +app.kubernetes.io/name: {{ include "gitea.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{- define "gitea.selectorLabels.actRunner" -}} +app.kubernetes.io/name: {{ include "gitea.name" . }}-act-runner +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{- define "postgresql-ha.dns" -}} +{{- if (index .Values "postgresql-ha").enabled -}} +{{- printf "%s-postgresql-ha-pgpool.%s.svc.%s:%g" .Release.Name .Release.Namespace .Values.clusterDomain (index .Values "postgresql-ha" "service" "ports" "postgresql") -}} +{{- end -}} +{{- end -}} + +{{- define "postgresql.dns" -}} +{{- if (index .Values "postgresql").enabled -}} +{{- printf "%s-postgresql.%s.svc.%s:%g" .Release.Name .Release.Namespace .Values.clusterDomain .Values.postgresql.global.postgresql.service.ports.postgresql -}} +{{- end -}} +{{- end -}} + +{{- define "valkey.dns" -}} +{{- if and ((index .Values "valkey-cluster").enabled) ((index .Values "valkey").enabled) -}} +{{- fail "valkey and valkey-cluster cannot be enabled at the same time. Please only choose one." -}} +{{- else if (index .Values "valkey-cluster").enabled -}} +{{- printf "redis+cluster://:%s@%s-valkey-cluster-headless.%s.svc.%s:%g/0?pool_size=100&idle_timeout=180s&" (index .Values "valkey-cluster").global.valkey.password .Release.Name .Release.Namespace .Values.clusterDomain (index .Values "valkey-cluster").service.ports.valkey -}} +{{- else if (index .Values "valkey").enabled -}} +{{- printf "redis://:%s@%s-valkey-headless.%s.svc.%s:%g/0?pool_size=100&idle_timeout=180s&" (index .Values "valkey").global.valkey.password .Release.Name .Release.Namespace .Values.clusterDomain (index .Values "valkey").master.service.ports.valkey -}} +{{- end -}} +{{- end -}} + +{{- define "valkey.port" -}} +{{- if (index .Values "valkey-cluster").enabled -}} +{{ (index .Values "valkey-cluster").service.ports.valkey }} +{{- else if (index .Values "valkey").enabled -}} +{{ (index .Values "valkey").master.service.ports.valkey }} +{{- end -}} +{{- end -}} + +{{- define "valkey.servicename" -}} +{{- if (index .Values "valkey-cluster").enabled -}} +{{- printf "%s-valkey-cluster-headless.%s.svc.%s" .Release.Name .Release.Namespace .Values.clusterDomain -}} +{{- else if (index .Values "valkey").enabled -}} +{{- printf "%s-valkey-headless.%s.svc.%s" .Release.Name .Release.Namespace .Values.clusterDomain -}} +{{- end -}} +{{- end -}} + +{{- define "gitea.default_domain" -}} +{{- printf "%s-http.%s.svc.%s" (include "gitea.fullname" .) .Release.Namespace .Values.clusterDomain -}} +{{- end -}} + +{{- define "gitea.ldap_settings" -}} +{{- $idx := index . 0 }} +{{- $values := index . 1 }} + +{{- if not (hasKey $values "bindDn") -}} +{{- $_ := set $values "bindDn" "" -}} +{{- end -}} + +{{- if not (hasKey $values "bindPassword") -}} +{{- $_ := set $values "bindPassword" "" -}} +{{- end -}} + +{{- $flags := list "notActive" "skipTlsVerify" "allowDeactivateAll" "synchronizeUsers" "attributesInBind" -}} +{{- range $key, $val := $values -}} +{{- if and (ne $key "enabled") (ne $key "existingSecret") -}} +{{- if eq $key "bindDn" -}} +{{- printf "--%s \"${GITEA_LDAP_BIND_DN_%d}\" " ($key | kebabcase) ($idx) -}} +{{- else if eq $key "bindPassword" -}} +{{- printf "--%s \"${GITEA_LDAP_PASSWORD_%d}\" " ($key | kebabcase) ($idx) -}} +{{- else if eq $key "port" -}} +{{- printf "--%s %d " $key ($val | int) -}} +{{- else if has $key $flags -}} +{{- printf "--%s " ($key | kebabcase) -}} +{{- else -}} +{{- printf "--%s %s " ($key | kebabcase) ($val | squote) -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{- define "gitea.oauth_settings" -}} +{{- $idx := index . 0 }} +{{- $values := index . 1 }} + +{{- if not (hasKey $values "key") -}} +{{- $_ := set $values "key" (printf "${GITEA_OAUTH_KEY_%d}" $idx) -}} +{{- end -}} + +{{- if not (hasKey $values "secret") -}} +{{- $_ := set $values "secret" (printf "${GITEA_OAUTH_SECRET_%d}" $idx) -}} +{{- end -}} + +{{- range $key, $val := $values -}} +{{- if ne $key "existingSecret" -}} +{{- printf "--%s %s " ($key | kebabcase) ($val | quote) -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{- define "gitea.public_protocol" -}} +{{- if and .Values.ingress.enabled (gt (len .Values.ingress.tls) 0) -}} +https +{{- else -}} +{{ .Values.gitea.config.server.PROTOCOL }} +{{- end -}} +{{- end -}} + +{{- define "gitea.inline_configuration" -}} + {{- include "gitea.inline_configuration.init" . -}} + {{- include "gitea.inline_configuration.defaults" . -}} + + {{- $generals := list -}} + {{- $inlines := dict -}} + + {{- range $key, $value := .Values.gitea.config }} + {{- if kindIs "map" $value }} + {{- if gt (len $value) 0 }} + {{- $section := default list (get $inlines $key) -}} + {{- range $n_key, $n_value := $value }} + {{- $section = append $section (printf "%s=%v" $n_key $n_value) -}} + {{- end }} + {{- $_ := set $inlines $key (join "\n" $section) -}} + {{- end -}} + {{- else }} + {{- if or (eq $key "APP_NAME") (eq $key "RUN_USER") (eq $key "RUN_MODE") -}} + {{- $generals = append $generals (printf "%s=%s" $key $value) -}} + {{- else -}} + {{- (printf "Key %s cannot be on top level of configuration" $key) | fail -}} + {{- end -}} + + {{- end }} + {{- end }} + + {{- $_ := set $inlines "_generals_" (join "\n" $generals) -}} + {{- toYaml $inlines -}} +{{- end -}} + +{{- define "gitea.inline_configuration.init" -}} + {{- if not (hasKey .Values.gitea.config "cache") -}} + {{- $_ := set .Values.gitea.config "cache" dict -}} + {{- end -}} + {{- if not (hasKey .Values.gitea.config "server") -}} + {{- $_ := set .Values.gitea.config "server" dict -}} + {{- end -}} + {{- if not (hasKey .Values.gitea.config "metrics") -}} + {{- $_ := set .Values.gitea.config "metrics" dict -}} + {{- end -}} + {{- if not (hasKey .Values.gitea.config "database") -}} + {{- $_ := set .Values.gitea.config "database" dict -}} + {{- end -}} + {{- if not (hasKey .Values.gitea.config "security") -}} + {{- $_ := set .Values.gitea.config "security" dict -}} + {{- end -}} + {{- if not .Values.gitea.config.repository -}} + {{- $_ := set .Values.gitea.config "repository" dict -}} + {{- end -}} + {{- if not (hasKey .Values.gitea.config "oauth2") -}} + {{- $_ := set .Values.gitea.config "oauth2" dict -}} + {{- end -}} + {{- if not (hasKey .Values.gitea.config "session") -}} + {{- $_ := set .Values.gitea.config "session" dict -}} + {{- end -}} + {{- if not (hasKey .Values.gitea.config "queue") -}} + {{- $_ := set .Values.gitea.config "queue" dict -}} + {{- end -}} + {{- if not (hasKey .Values.gitea.config "queue.issue_indexer") -}} + {{- $_ := set .Values.gitea.config "queue.issue_indexer" dict -}} + {{- end -}} + {{- if not (hasKey .Values.gitea.config "indexer") -}} + {{- $_ := set .Values.gitea.config "indexer" dict -}} + {{- end -}} + {{- if not (hasKey .Values.gitea.config "actions") -}} + {{- $_ := set .Values.gitea.config "actions" dict -}} + {{- end -}} +{{- end -}} + +{{- define "gitea.inline_configuration.defaults" -}} + {{- include "gitea.inline_configuration.defaults.server" . -}} + {{- include "gitea.inline_configuration.defaults.database" . -}} + + {{- if not .Values.gitea.config.repository.ROOT -}} + {{- $_ := set .Values.gitea.config.repository "ROOT" "/data/git/gitea-repositories" -}} + {{- end -}} + {{- if not .Values.gitea.config.security.INSTALL_LOCK -}} + {{- $_ := set .Values.gitea.config.security "INSTALL_LOCK" "true" -}} + {{- end -}} + {{- if not (hasKey .Values.gitea.config.metrics "ENABLED") -}} + {{- $_ := set .Values.gitea.config.metrics "ENABLED" .Values.gitea.metrics.enabled -}} + {{- end -}} + {{- if and (not (hasKey .Values.gitea.config.metrics "TOKEN")) (.Values.gitea.metrics.token) (.Values.gitea.metrics.enabled) -}} + {{- $_ := set .Values.gitea.config.metrics "TOKEN" .Values.gitea.metrics.token -}} + {{- end -}} + {{- /* valkey queue */ -}} + {{- if or ((index .Values "valkey-cluster").enabled) ((index .Values "valkey").enabled) -}} + {{- $_ := set .Values.gitea.config.queue "TYPE" "redis" -}} + {{- $_ := set .Values.gitea.config.queue "CONN_STR" (include "valkey.dns" .) -}} + {{- $_ := set .Values.gitea.config.session "PROVIDER" "redis" -}} + {{- $_ := set .Values.gitea.config.session "PROVIDER_CONFIG" (include "valkey.dns" .) -}} + {{- $_ := set .Values.gitea.config.cache "ADAPTER" "redis" -}} + {{- $_ := set .Values.gitea.config.cache "HOST" (include "valkey.dns" .) -}} + {{- else -}} + {{- if not (get .Values.gitea.config.session "PROVIDER") -}} + {{- $_ := set .Values.gitea.config.session "PROVIDER" "memory" -}} + {{- end -}} + {{- if not (get .Values.gitea.config.session "PROVIDER_CONFIG") -}} + {{- $_ := set .Values.gitea.config.session "PROVIDER_CONFIG" "" -}} + {{- end -}} + {{- if not (get .Values.gitea.config.queue "TYPE") -}} + {{- $_ := set .Values.gitea.config.queue "TYPE" "level" -}} + {{- end -}} + {{- if not (get .Values.gitea.config.queue "CONN_STR") -}} + {{- $_ := set .Values.gitea.config.queue "CONN_STR" "" -}} + {{- end -}} + {{- if not (get .Values.gitea.config.cache "ADAPTER") -}} + {{- $_ := set .Values.gitea.config.cache "ADAPTER" "memory" -}} + {{- end -}} + {{- if not (get .Values.gitea.config.cache "HOST") -}} + {{- $_ := set .Values.gitea.config.cache "HOST" "" -}} + {{- end -}} + {{- end -}} + {{- if not .Values.gitea.config.indexer.ISSUE_INDEXER_TYPE -}} + {{- $_ := set .Values.gitea.config.indexer "ISSUE_INDEXER_TYPE" "db" -}} + {{- end -}} +{{- end -}} + +{{- define "gitea.inline_configuration.defaults.server" -}} + {{- if not (hasKey .Values.gitea.config.server "HTTP_PORT") -}} + {{- $_ := set .Values.gitea.config.server "HTTP_PORT" .Values.service.http.port -}} + {{- end -}} + {{- if not .Values.gitea.config.server.PROTOCOL -}} + {{- $_ := set .Values.gitea.config.server "PROTOCOL" "http" -}} + {{- end -}} + {{- if not (.Values.gitea.config.server.DOMAIN) -}} + {{- if gt (len .Values.ingress.hosts) 0 -}} + {{- $_ := set .Values.gitea.config.server "DOMAIN" ( tpl (index .Values.ingress.hosts 0).host $) -}} + {{- else -}} + {{- $_ := set .Values.gitea.config.server "DOMAIN" (include "gitea.default_domain" .) -}} + {{- end -}} + {{- end -}} + {{- if not .Values.gitea.config.server.ROOT_URL -}} + {{- $_ := set .Values.gitea.config.server "ROOT_URL" (printf "%s://%s" (include "gitea.public_protocol" .) .Values.gitea.config.server.DOMAIN) -}} + {{- end -}} + {{- if not .Values.gitea.config.server.SSH_DOMAIN -}} + {{- $_ := set .Values.gitea.config.server "SSH_DOMAIN" .Values.gitea.config.server.DOMAIN -}} + {{- end -}} + {{- if not .Values.gitea.config.server.SSH_PORT -}} + {{- $_ := set .Values.gitea.config.server "SSH_PORT" .Values.service.ssh.port -}} + {{- end -}} + {{- if not (hasKey .Values.gitea.config.server "START_SSH_SERVER") -}} + {{- if .Values.image.rootless -}} + {{- $_ := set .Values.gitea.config.server "START_SSH_SERVER" "true" -}} + {{- if not (hasKey .Values.gitea.config.server "SSH_LISTEN_PORT") -}} + {{- if not .Values.gitea.config.server.SSH_LISTEN_PORT -}} + {{- $_ := set .Values.gitea.config.server "SSH_LISTEN_PORT" .Values.gitea.config.server.SSH_PORT -}} + {{- else -}} + {{- $_ := set .Values.gitea.config.server "SSH_LISTEN_PORT" .Values.gitea.config.server.SSH_LISTEN_PORT -}} + {{- end -}} + {{- end -}} + {{- else -}} + {{- $_ := set .Values.gitea.config.server "START_SSH_SERVER" "false" -}} + {{- end -}} + {{- end -}} + {{- if not (hasKey .Values.gitea.config.server "APP_DATA_PATH") -}} + {{- $_ := set .Values.gitea.config.server "APP_DATA_PATH" "/data" -}} + {{- end -}} + {{- if not (hasKey .Values.gitea.config.server "ENABLE_PPROF") -}} + {{- $_ := set .Values.gitea.config.server "ENABLE_PPROF" false -}} + {{- end -}} +{{- end -}} + +{{- define "gitea.inline_configuration.defaults.database" -}} + {{- if (index .Values "postgresql-ha" "enabled") -}} + {{- $_ := set .Values.gitea.config.database "DB_TYPE" "postgres" -}} + {{- if not (.Values.gitea.config.database.HOST) -}} + {{- $_ := set .Values.gitea.config.database "HOST" (include "postgresql-ha.dns" .) -}} + {{- end -}} + {{- $_ := set .Values.gitea.config.database "NAME" (index .Values "postgresql-ha" "global" "postgresql" "database") -}} + {{- $_ := set .Values.gitea.config.database "USER" (index .Values "postgresql-ha" "global" "postgresql" "username") -}} + {{- $_ := set .Values.gitea.config.database "PASSWD" (index .Values "postgresql-ha" "global" "postgresql" "password") -}} + {{- end -}} + {{- if (index .Values "postgresql" "enabled") -}} + {{- $_ := set .Values.gitea.config.database "DB_TYPE" "postgres" -}} + {{- if not (.Values.gitea.config.database.HOST) -}} + {{- $_ := set .Values.gitea.config.database "HOST" (include "postgresql.dns" .) -}} + {{- end -}} + {{- $_ := set .Values.gitea.config.database "NAME" .Values.postgresql.global.postgresql.auth.database -}} + {{- $_ := set .Values.gitea.config.database "USER" .Values.postgresql.global.postgresql.auth.username -}} + {{- $_ := set .Values.gitea.config.database "PASSWD" .Values.postgresql.global.postgresql.auth.password -}} + {{- end -}} +{{- end -}} + +{{- define "gitea.init-additional-mounts" -}} + {{- /* Honor the deprecated extraVolumeMounts variable when defined */ -}} + {{- if gt (len .Values.extraInitVolumeMounts) 0 -}} + {{- toYaml .Values.extraInitVolumeMounts -}} + {{- else if gt (len .Values.extraVolumeMounts) 0 -}} + {{- toYaml .Values.extraVolumeMounts -}} + {{- end -}} +{{- end -}} + +{{- define "gitea.container-additional-mounts" -}} + {{- /* Honor the deprecated extraVolumeMounts variable when defined */ -}} + {{- if gt (len .Values.extraContainerVolumeMounts) 0 -}} + {{- toYaml .Values.extraContainerVolumeMounts -}} + {{- else if gt (len .Values.extraVolumeMounts) 0 -}} + {{- toYaml .Values.extraVolumeMounts -}} + {{- end -}} +{{- end -}} + +{{- define "gitea.gpg-key-secret-name" -}} +{{ default (printf "%s-gpg-key" (include "gitea.fullname" .)) .Values.signing.existingSecret }} +{{- end -}} + +{{- define "gitea.serviceAccountName" -}} +{{ .Values.serviceAccount.name | default (include "gitea.fullname" .) }} +{{- end -}} + +{{- define "ingress.annotations" -}} + {{- if .Values.ingress.annotations }} + annotations: + {{- $tp := typeOf .Values.ingress.annotations }} + {{- if eq $tp "string" }} + {{- tpl .Values.ingress.annotations . | nindent 4 }} + {{- else }} + {{- toYaml .Values.ingress.annotations | nindent 4 }} + {{- end }} + {{- end }} +{{- end -}} + +{{- define "gitea.admin.passwordMode" -}} +{{- if has .Values.gitea.admin.passwordMode (tuple "keepUpdated" "initialOnlyNoReset" "initialOnlyRequireReset") -}} +{{ .Values.gitea.admin.passwordMode }} +{{- else -}} +{{ printf "gitea.admin.passwordMode must be set to one of 'keepUpdated', 'initialOnlyNoReset', or 'initialOnlyRequireReset'. Received: '%s'" .Values.gitea.admin.passwordMode | fail }} +{{- end -}} +{{- end -}} + +{{/* Create a functioning probe object for rendering. Given argument must be either a livenessProbe, readinessProbe, or startupProbe */}} +{{- define "gitea.deployment.probe" -}} + {{- $probe := unset . "enabled" -}} + {{- $probeKeys := keys $probe -}} + {{- $containsCustomMethod := false -}} + {{- $chartDefaultMethod := "tcpSocket" -}} + {{- $nonChartDefaultMethods := list "exec" "httpGet" "grpc" -}} + {{- range $probeKeys -}} + {{- if has . $nonChartDefaultMethods -}} + {{- $containsCustomMethod = true -}} + {{- end -}} + {{- end -}} + {{- if $containsCustomMethod -}} + {{- $probe = unset . $chartDefaultMethod -}} + {{- end -}} + {{- toYaml $probe -}} +{{- end -}} + +{{- define "gitea.metrics-secret-name" -}} +{{ default (printf "%s-metrics-secret" (include "gitea.fullname" .)) }} +{{- end -}} diff --git a/backing-services/gitea/templates/gitea/check-actions-not-present.yaml b/backing-services/gitea/templates/gitea/check-actions-not-present.yaml new file mode 100644 index 0000000..ad17bf6 --- /dev/null +++ b/backing-services/gitea/templates/gitea/check-actions-not-present.yaml @@ -0,0 +1,3 @@ +{{- if .Values.actions -}} + {{- fail "The actions sub-chart has been outsourced to a dedicated chart available at https://gitea.com/gitea/helm-actions. For assistance with the migration process, check https://gitea.com/gitea/helm-actions/issues/9." -}} +{{- end -}} diff --git a/backing-services/gitea/templates/gitea/config.yaml b/backing-services/gitea/templates/gitea/config.yaml new file mode 100644 index 0000000..b5d0dd6 --- /dev/null +++ b/backing-services/gitea/templates/gitea/config.yaml @@ -0,0 +1,57 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "gitea.fullname" . }}-inline-config + namespace: {{ .Values.namespace | default .Release.Namespace }} + labels: + {{- include "gitea.labels" . | nindent 4 }} +type: Opaque +stringData: + {{- include "gitea.inline_configuration" . | nindent 2 }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "gitea.fullname" . }} + namespace: {{ .Values.namespace | default .Release.Namespace }} + labels: + {{- include "gitea.labels" . | nindent 4 }} +type: Opaque +stringData: +{{ (.Files.Glob "scripts/init-containers/config/*.sh").AsConfig | indent 2 }} + assertions: | + + {{- /*assert that only one PG dep is enabled */ -}} + {{- if and (.Values.postgresql.enabled) (index .Values "postgresql-ha" "enabled") -}} + {{- fail "Only one of postgresql or postgresql-ha can be enabled at the same time." -}} + {{- end }} + + {{- /* multiple replicas assertions */ -}} + {{- if gt (.Values.replicaCount | int) 1 -}} + {{- if .Values.gitea.config.cron -}} + {{- if .Values.gitea.config.cron.GIT_GC_REPOS -}} + {{- if eq .Values.gitea.config.cron.GIT_GC_REPOS.ENABLED true -}} + {{ fail "Invoking the garbage collector via CRON is not yet supported when running with multiple replicas. Please set 'gitea.config.cron.GIT_GC_REPOS.enabled = false'." }} + {{- end }} + {{- end }} + {{- end }} + + {{- if eq (first .Values.persistence.accessModes) "ReadWriteOnce" -}} + {{- fail "When using multiple replicas, a RWX file system is required and persistence.accessModes[0] must be set to ReadWriteMany." -}} + {{- end }} + {{- if .Values.gitea.config.indexer -}} + {{- if eq .Values.gitea.config.indexer.ISSUE_INDEXER_TYPE "bleve" -}} + {{- fail "When using multiple replicas, the issue indexer (gitea.config.indexer.ISSUE_INDEXER_TYPE) must be set to a HA-ready provider such as 'meilisearch', 'elasticsearch' or 'db' (if the DB is HA-ready)." -}} + {{- end }} + {{- if .Values.gitea.config.indexer.REPO_INDEXER_TYPE -}} + {{- if eq .Values.gitea.config.indexer.REPO_INDEXER_TYPE "bleve" -}} + {{- if .Values.gitea.config.indexer.REPO_INDEXER_ENABLED -}} + {{- if eq .Values.gitea.config.indexer.REPO_INDEXER_ENABLED true -}} + {{- fail "When using multiple replicas, the repo indexer (gitea.config.indexer.REPO_INDEXER_TYPE) must be set to 'meilisearch' or 'elasticsearch' or disabled." -}} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + + {{- end }} diff --git a/backing-services/gitea/templates/gitea/deployment.yaml b/backing-services/gitea/templates/gitea/deployment.yaml new file mode 100644 index 0000000..40ad134 --- /dev/null +++ b/backing-services/gitea/templates/gitea/deployment.yaml @@ -0,0 +1,432 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "gitea.fullname" . }} + namespace: {{ .Values.namespace | default .Release.Namespace }} + annotations: + {{- if .Values.deployment.annotations }} + {{- toYaml .Values.deployment.annotations | nindent 4 }} + {{- end }} + labels: + {{- include "gitea.labels" . | nindent 4 }} + {{- if .Values.deployment.labels }} + {{- toYaml .Values.deployment.labels | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.replicaCount }} + strategy: + type: {{ .Values.strategy.type }} + {{- if eq .Values.strategy.type "RollingUpdate" }} + rollingUpdate: + maxUnavailable: {{ .Values.strategy.rollingUpdate.maxUnavailable }} + maxSurge: {{ .Values.strategy.rollingUpdate.maxSurge }} + {{- end }} + selector: + matchLabels: + {{- include "gitea.selectorLabels" . | nindent 6 }} + {{- if .Values.deployment.labels }} + {{- toYaml .Values.deployment.labels | nindent 6 }} + {{- end }} + template: + metadata: + annotations: + checksum/config: {{ include (print $.Template.BasePath "/gitea/config.yaml") . | sha256sum }} + {{- range $idx, $value := .Values.gitea.ldap }} + checksum/ldap_{{ $idx }}: {{ include "gitea.ldap_settings" (list $idx $value) | sha256sum }} + {{- end }} + {{- range $idx, $value := .Values.gitea.oauth }} + checksum/oauth_{{ $idx }}: {{ include "gitea.oauth_settings" (list $idx $value) | sha256sum }} + {{- end }} + {{- with .Values.gitea.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "gitea.labels" . | nindent 8 }} + {{- if .Values.deployment.labels }} + {{- toYaml .Values.deployment.labels | nindent 8 }} + {{- end }} + spec: + {{- if .Values.schedulerName }} + schedulerName: "{{ .Values.schedulerName }}" + {{- end }} + {{- if (or .Values.serviceAccount.create .Values.serviceAccount.name) }} + serviceAccountName: {{ include "gitea.serviceAccountName" . }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: "{{ .Values.priorityClassName }}" + {{- end }} + {{- include "gitea.images.pullSecrets" . | nindent 6 }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + initContainers: + {{- if .Values.preExtraInitContainers }} + {{- toYaml .Values.preExtraInitContainers | nindent 8 }} + {{- end }} + - name: init-directories + image: "{{ include "gitea.image" . }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - "{{ .Values.initContainersScriptsVolumeMountPath }}/init_directory_structure.sh" + env: + - name: GITEA_APP_INI + value: /data/gitea/conf/app.ini + - name: GITEA_CUSTOM + value: /data/gitea + - name: GITEA_WORK_DIR + value: /data + - name: GITEA_TEMP + value: /tmp/gitea + {{- if .Values.deployment.env }} + {{- toYaml .Values.deployment.env | nindent 12 }} + {{- end }} + {{- if .Values.signing.enabled }} + - name: GNUPGHOME + value: {{ .Values.signing.gpgHome }} + {{- end }} + volumeMounts: + - name: init + mountPath: {{ .Values.initContainersScriptsVolumeMountPath }} + - name: temp + mountPath: /tmp + - name: data + mountPath: /data + {{- if .Values.persistence.subPath }} + subPath: {{ .Values.persistence.subPath }} + {{- end }} + {{- include "gitea.init-additional-mounts" . | nindent 12 }} + securityContext: + {{- toYaml .Values.containerSecurityContext | nindent 12 }} + resources: + {{- toYaml .Values.initContainers.resources | nindent 12 }} + - name: init-app-ini + image: "{{ include "gitea.image" . }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - "{{ .Values.initContainersScriptsVolumeMountPath }}/config_environment.sh" + env: + - name: GITEA_APP_INI + value: /data/gitea/conf/app.ini + - name: GITEA_CUSTOM + value: /data/gitea + - name: GITEA_WORK_DIR + value: /data + - name: GITEA_TEMP + value: /tmp/gitea + - name: TMP_EXISTING_ENVS_FILE + value: /tmp/existing-envs + - name: ENV_TO_INI_MOUNT_POINT + value: /env-to-ini-mounts + {{- if .Values.deployment.env }} + {{- toYaml .Values.deployment.env | nindent 12 }} + {{- end }} + {{- if .Values.gitea.additionalConfigFromEnvs }} + {{- tpl (toYaml .Values.gitea.additionalConfigFromEnvs) $ | nindent 12 }} + {{- end }} + volumeMounts: + - name: config + mountPath: {{ .Values.initContainersScriptsVolumeMountPath }} + - name: temp + mountPath: /tmp + - name: data + mountPath: /data + {{- if .Values.persistence.subPath }} + subPath: {{ .Values.persistence.subPath }} + {{- end }} + - name: inline-config-sources + mountPath: /env-to-ini-mounts/inlines/ + {{- range $idx, $value := .Values.gitea.additionalConfigSources }} + - name: additional-config-sources-{{ $idx }} + mountPath: "/env-to-ini-mounts/additionals/{{ $idx }}/" + {{- end }} + {{- include "gitea.init-additional-mounts" . | nindent 12 }} + securityContext: + {{- toYaml .Values.containerSecurityContext | nindent 12 }} + resources: + {{- toYaml .Values.initContainers.resources | nindent 12 }} + {{- if .Values.signing.enabled }} + - name: configure-gpg + image: "{{ include "gitea.image" . }}" + command: + - "{{ .Values.initContainersScriptsVolumeMountPath }}/configure_gpg_environment.sh" + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + {{- /* By default this container runs as user 1000 unless otherwise stated */ -}} + {{- $csc := deepCopy .Values.containerSecurityContext -}} + {{- if not (hasKey $csc "runAsUser") -}} + {{- $_ := set $csc "runAsUser" 1000 -}} + {{- end -}} + {{- toYaml $csc | nindent 12 }} + env: + - name: GNUPGHOME + value: {{ .Values.signing.gpgHome }} + - name: TMP_RAW_GPG_KEY + value: /raw/private.asc + volumeMounts: + - name: init + mountPath: {{ .Values.initContainersScriptsVolumeMountPath }} + - name: data + mountPath: /data + {{- if .Values.persistence.subPath }} + subPath: {{ .Values.persistence.subPath }} + {{- end }} + - name: gpg-private-key + mountPath: /raw + readOnly: true + {{- if .Values.extraVolumeMounts }} + {{- toYaml .Values.extraVolumeMounts | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.initContainers.resources | nindent 12 }} + {{- end }} + - name: configure-gitea + image: "{{ include "gitea.image" . }}" + command: + - "{{ .Values.initContainersScriptsVolumeMountPath }}/configure_gitea.sh" + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + {{- /* By default this container runs as user 1000 unless otherwise stated */ -}} + {{- $csc := deepCopy .Values.containerSecurityContext -}} + {{- if not (hasKey $csc "runAsUser") -}} + {{- $_ := set $csc "runAsUser" 1000 -}} + {{- end -}} + {{- toYaml $csc | nindent 12 }} + env: + - name: GITEA_APP_INI + value: /data/gitea/conf/app.ini + - name: GITEA_CUSTOM + value: /data/gitea + - name: GITEA_WORK_DIR + value: /data + - name: GITEA_TEMP + value: /tmp/gitea + {{- if .Values.image.rootless }} + - name: HOME + value: /data/gitea/git + {{- end }} + {{- if .Values.gitea.ldap }} + {{- range $idx, $value := .Values.gitea.ldap }} + {{- if $value.existingSecret }} + - name: GITEA_LDAP_BIND_DN_{{ $idx }} + valueFrom: + secretKeyRef: + key: bindDn + name: {{ $value.existingSecret }} + - name: GITEA_LDAP_PASSWORD_{{ $idx }} + valueFrom: + secretKeyRef: + key: bindPassword + name: {{ $value.existingSecret }} + {{- else }} + - name: GITEA_LDAP_BIND_DN_{{ $idx }} + value: {{ $value.bindDn | quote }} + - name: GITEA_LDAP_PASSWORD_{{ $idx }} + value: {{ $value.bindPassword | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.gitea.oauth }} + {{- range $idx, $value := .Values.gitea.oauth }} + {{- if $value.existingSecret }} + - name: GITEA_OAUTH_KEY_{{ $idx }} + valueFrom: + secretKeyRef: + key: key + name: {{ $value.existingSecret }} + - name: GITEA_OAUTH_SECRET_{{ $idx }} + valueFrom: + secretKeyRef: + key: secret + name: {{ $value.existingSecret }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.gitea.admin.existingSecret }} + - name: GITEA_ADMIN_USERNAME + valueFrom: + secretKeyRef: + key: username + name: {{ .Values.gitea.admin.existingSecret }} + - name: GITEA_ADMIN_PASSWORD + valueFrom: + secretKeyRef: + key: password + name: {{ .Values.gitea.admin.existingSecret }} + {{- else }} + - name: GITEA_ADMIN_USERNAME + value: {{ .Values.gitea.admin.username | quote }} + - name: GITEA_ADMIN_PASSWORD + value: {{ .Values.gitea.admin.password | quote }} + {{- end }} + - name: GITEA_ADMIN_PASSWORD_MODE + value: {{ include "gitea.admin.passwordMode" $ }} + {{- if .Values.deployment.env }} + {{- toYaml .Values.deployment.env | nindent 12 }} + {{- end }} + volumeMounts: + - name: init + mountPath: {{ .Values.initContainersScriptsVolumeMountPath }} + - name: temp + mountPath: /tmp + - name: data + mountPath: /data + {{- if .Values.persistence.subPath }} + subPath: {{ .Values.persistence.subPath }} + {{- end }} + {{- include "gitea.init-additional-mounts" . | nindent 12 }} + resources: + {{- toYaml .Values.initContainers.resources | nindent 12 }} + {{- if .Values.postExtraInitContainers }} + {{- toYaml .Values.postExtraInitContainers | nindent 8 }} + {{- end }} + terminationGracePeriodSeconds: {{ .Values.deployment.terminationGracePeriodSeconds }} + containers: + - name: {{ .Chart.Name }} + image: "{{ include "gitea.image" . }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + env: + # SSH Port values have to be set here as well for openssh configuration + - name: SSH_LISTEN_PORT + value: {{ .Values.gitea.config.server.SSH_LISTEN_PORT | quote }} + - name: SSH_PORT + value: {{ .Values.gitea.config.server.SSH_PORT | quote }} + {{- if not .Values.image.rootless }} + - name: SSH_LOG_LEVEL + value: {{ .Values.gitea.ssh.logLevel | quote }} + {{- end }} + - name: GITEA_APP_INI + value: /data/gitea/conf/app.ini + - name: GITEA_CUSTOM + value: /data/gitea + - name: GITEA_WORK_DIR + value: /data + - name: GITEA_TEMP + value: /tmp/gitea + {{- if and (hasKey .Values.resources "limits") (hasKey .Values.resources.limits "cpu") }} + - name: GOMAXPROCS + valueFrom: + resourceFieldRef: + divisor: "1" + resource: limits.cpu + {{- end }} + - name: TMPDIR + value: /tmp/gitea + {{- if .Values.image.rootless }} + - name: HOME + value: /data/gitea/git + {{- end }} + {{- if .Values.signing.enabled }} + - name: GNUPGHOME + value: {{ .Values.signing.gpgHome }} + {{- end }} + {{- if .Values.deployment.env }} + {{- toYaml .Values.deployment.env | nindent 12 }} + {{- end }} + ports: + - name: ssh + containerPort: {{ .Values.gitea.config.server.SSH_LISTEN_PORT }} + {{- if .Values.service.ssh.hostPort }} + hostPort: {{ .Values.service.ssh.hostPort }} + {{- end }} + - name: http + containerPort: {{ .Values.gitea.config.server.HTTP_PORT }} + {{- if .Values.gitea.config.server.ENABLE_PPROF }} + - name: profiler + containerPort: 6060 + {{- end }} + {{- if .Values.gitea.livenessProbe.enabled }} + livenessProbe: + {{- include "gitea.deployment.probe" .Values.gitea.livenessProbe | nindent 12 }} + {{- end }} + {{- if .Values.gitea.readinessProbe.enabled }} + readinessProbe: + {{- include "gitea.deployment.probe" .Values.gitea.readinessProbe | nindent 12 }} + {{- end }} + {{- if .Values.gitea.startupProbe.enabled }} + startupProbe: + {{- include "gitea.deployment.probe" .Values.gitea.startupProbe | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + securityContext: + {{- /* Honor the deprecated securityContext variable when defined */ -}} + {{- if .Values.containerSecurityContext -}} + {{ toYaml .Values.containerSecurityContext | nindent 12 -}} + {{- else -}} + {{ toYaml .Values.securityContext | nindent 12 -}} + {{- end }} + volumeMounts: + - name: temp + mountPath: /tmp + - name: data + mountPath: /data + {{- if .Values.persistence.subPath }} + subPath: {{ .Values.persistence.subPath }} + {{- end }} + {{- include "gitea.container-additional-mounts" . | nindent 12 }} + {{- if .Values.extraContainers }} + {{- toYaml .Values.extraContainers | nindent 8 }} + {{- end }} + {{- with .Values.global.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- range $key, $value := .Values.nodeSelector }} + nodeSelector: + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.dnsConfig }} + dnsConfig: + {{- toYaml .Values.dnsConfig | nindent 8 }} + {{- end }} + volumes: + - name: init + secret: + secretName: {{ include "gitea.fullname" . }}-init + defaultMode: 110 + - name: config + secret: + secretName: {{ include "gitea.fullname" . }} + defaultMode: 110 + {{- if gt (len .Values.extraVolumes) 0 }} + {{- toYaml .Values.extraVolumes | nindent 8 }} + {{- end }} + - name: inline-config-sources + secret: + secretName: {{ include "gitea.fullname" . }}-inline-config + {{- range $idx, $value := .Values.gitea.additionalConfigSources }} + - name: additional-config-sources-{{ $idx }} + {{- toYaml $value | nindent 10 }} + {{- end }} + - name: temp + emptyDir: {} + {{- if .Values.signing.enabled }} + - name: gpg-private-key + secret: + secretName: {{ include "gitea.gpg-key-secret-name" . }} + items: + - key: privateKey + path: private.asc + defaultMode: 0100 + {{- end }} + {{- if .Values.persistence.enabled }} + {{- if .Values.persistence.mount }} + - name: data + persistentVolumeClaim: + claimName: {{ .Values.persistence.claimName }} + {{- end }} + {{- else if not .Values.persistence.enabled }} + - name: data + emptyDir: {} + {{- end }} diff --git a/backing-services/gitea/templates/gitea/deprecation.yaml b/backing-services/gitea/templates/gitea/deprecation.yaml new file mode 100644 index 0000000..057c5bd --- /dev/null +++ b/backing-services/gitea/templates/gitea/deprecation.yaml @@ -0,0 +1,34 @@ +{{- if .Values.checkDeprecation -}} + {{/* CUSTOM PROBES */}} + {{- if .Values.gitea.customLivenessProbe -}} + {{- fail "`gitea.customLivenessProbe` does no longer exist. Please refer to the changelog and configure `gitea.livenessProbe` instead." -}} + {{- end -}} + {{- if .Values.gitea.customReadinessProbe -}} + {{- fail "`gitea.customReadinessProbe` does no longer exist. Please refer to the changelog and configure `gitea.readinessProbe` instead." -}} + {{- end -}} + {{- if .Values.gitea.customStartupProbe -}} + {{- fail "`gitea.customStartupProbe` does no longer exist. Please refer to the changelog and configure `gitea.startupProbe` instead." -}} + {{- end -}} + + {{/* LDAP SOURCES */}} + {{- if kindIs "map" .Values.gitea.ldap -}} + {{- fail "You can configure multiple LDAP sources. Please refer to the changelog and switch `gitea.ldap` from object to array notation." -}} + {{- end -}} + + {{/* OAUTH SOURCES */}} + {{- if kindIs "map" .Values.gitea.oauth -}} + {{- fail "You can configure multiple OAuth sources. Please refer to the changelog and switch `gitea.oauth` from object to array notation." -}} + {{- end -}} + + {{/* BUILTIN */}} + {{- if .Values.gitea.cache -}} + {{- if .Values.gitea.cache.builtIn -}} + {{- fail "`gitea.cache.builtIn` does no longer exist. Please use `memcached` at root level instead." -}} + {{- end -}} + {{- end -}} + {{- if .Values.gitea.database -}} + {{- if .Values.gitea.database.builtIn -}} + {{- fail "`gitea.database.builtIn` does no longer exist. Builtin databases can be configured inside the dependencies itself. Please refer to the changelog." -}} + {{- end -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/gitea/templates/gitea/extra-list.yaml b/backing-services/gitea/templates/gitea/extra-list.yaml new file mode 100644 index 0000000..62c0aca --- /dev/null +++ b/backing-services/gitea/templates/gitea/extra-list.yaml @@ -0,0 +1,8 @@ +{{- range .Values.extraDeploy }} +--- +{{- if typeIs "string" . }} + {{- tpl . $ }} +{{- else }} + {{- tpl (. | toYaml) $ }} +{{- end }} +{{- end }} diff --git a/backing-services/gitea/templates/gitea/gpg-secret.yaml b/backing-services/gitea/templates/gitea/gpg-secret.yaml new file mode 100644 index 0000000..46633c8 --- /dev/null +++ b/backing-services/gitea/templates/gitea/gpg-secret.yaml @@ -0,0 +1,17 @@ +{{- if .Values.signing.enabled -}} +{{- if and (empty .Values.signing.privateKey) (empty .Values.signing.existingSecret) -}} + {{- fail "Either specify `signing.privateKey` or `signing.existingSecret`" -}} +{{- end }} +{{- if and (not (empty .Values.signing.privateKey)) (empty .Values.signing.existingSecret) -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "gitea.gpg-key-secret-name" . }} + namespace: {{ .Values.namespace | default .Release.Namespace }} + labels: + {{- include "gitea.labels" . | nindent 4 }} +type: Opaque +data: + privateKey: {{ .Values.signing.privateKey | b64enc }} +{{- end }} +{{- end }} diff --git a/backing-services/gitea/templates/gitea/http-svc.yaml b/backing-services/gitea/templates/gitea/http-svc.yaml new file mode 100644 index 0000000..28bd218 --- /dev/null +++ b/backing-services/gitea/templates/gitea/http-svc.yaml @@ -0,0 +1,54 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "gitea.fullname" . }}-http + namespace: {{ .Values.namespace | default .Release.Namespace }} + labels: + {{- include "gitea.labels" . | nindent 4 }} + {{- if .Values.service.http.labels }} + {{- toYaml .Values.service.http.labels | nindent 4 }} + {{- end }} + annotations: + {{- toYaml .Values.service.http.annotations | nindent 4 }} +spec: + type: {{ .Values.service.http.type }} + {{- if eq .Values.service.http.type "LoadBalancer" }} + {{- if .Values.service.http.loadBalancerClass }} + loadBalancerClass: {{ .Values.service.http.loadBalancerClass }} + {{- end }} + {{- if and .Values.service.http.loadBalancerIP }} + loadBalancerIP: {{ .Values.service.http.loadBalancerIP }} + {{- end }} + {{- if .Values.service.http.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- range .Values.service.http.loadBalancerSourceRanges }} + - {{ . }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.service.http.externalIPs }} + externalIPs: + {{- toYaml .Values.service.http.externalIPs | nindent 4 }} + {{- end }} + {{- if .Values.service.http.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.service.http.ipFamilyPolicy }} + {{- end }} + {{- with .Values.service.http.ipFamilies }} + ipFamilies: + {{- toYaml . | nindent 4 }} + {{- end -}} + {{- if .Values.service.http.externalTrafficPolicy }} + externalTrafficPolicy: {{ .Values.service.http.externalTrafficPolicy }} + {{- end }} + {{- if and .Values.service.http.clusterIP (eq .Values.service.http.type "ClusterIP") }} + clusterIP: {{ .Values.service.http.clusterIP }} + {{- end }} + ports: + - name: http + port: {{ .Values.service.http.port }} + {{- if .Values.service.http.nodePort }} + nodePort: {{ .Values.service.http.nodePort }} + {{- end }} + targetPort: {{ .Values.gitea.config.server.HTTP_PORT }} + selector: + {{- include "gitea.selectorLabels" . | nindent 4 }} diff --git a/backing-services/gitea/templates/gitea/ingress.yaml b/backing-services/gitea/templates/gitea/ingress.yaml new file mode 100644 index 0000000..9312ffb --- /dev/null +++ b/backing-services/gitea/templates/gitea/ingress.yaml @@ -0,0 +1,62 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "gitea.fullname" . -}} +{{- $httpPort := .Values.service.http.port -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ $fullName }} + namespace: {{ .Values.namespace | default .Release.Namespace }} + labels: + {{- include "gitea.labels" . | nindent 4 }} + annotations: + {{- range $key, $value := .Values.ingress.annotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} +spec: + ingressClassName: {{ tpl .Values.ingress.className . }} +{{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ tpl . $ | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} +{{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ tpl .host $ | quote }} + http: + paths: + {{- if .paths }} + {{- range .paths }} + {{- if kindIs "string" . }} + - path: {{ . }} + pathType: {{ default "Prefix" $.Values.ingress.pathType }} + backend: + service: + name: {{ $fullName }}-http + port: + number: {{ $httpPort }} + {{- else }} + - path: {{ .path | default "/" }} + pathType: {{ .pathType | default "Prefix" }} + backend: + service: + name: {{ $fullName }}-http + port: + number: {{ $httpPort }} + {{- end }} + {{- end }} + {{- else }} + - path: "/" + pathType: "Prefix" + backend: + service: + name: {{ $fullName }}-http + port: + number: {{ $httpPort }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/gitea/templates/gitea/init.yaml b/backing-services/gitea/templates/gitea/init.yaml new file mode 100644 index 0000000..2c30c9f --- /dev/null +++ b/backing-services/gitea/templates/gitea/init.yaml @@ -0,0 +1,228 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "gitea.fullname" . }}-init + namespace: {{ .Values.namespace | default .Release.Namespace }} + labels: + {{- include "gitea.labels" . | nindent 4 }} +type: Opaque +stringData: +{{ (.Files.Glob "scripts/init-containers/init/*.sh").AsConfig | indent 2 }} + init_directory_structure.sh: |- + #!/usr/bin/env bash + + set -euo pipefail + + {{- if .Values.initPreScript }} + # BEGIN: initPreScript + {{- with .Values.initPreScript -}} + {{ . | nindent 4}} + {{- end -}} + # END: initPreScript + {{- end }} + + {{- if not .Values.image.rootless }} + chown -v 1000:1000 /data + {{- end }} + mkdir -pv /data/git/.ssh + chmod -Rv 700 /data/git/.ssh + [ ! -d /data/gitea/conf ] && mkdir -pv /data/gitea/conf + + # prepare temp directory structure + mkdir -pv "${GITEA_TEMP}" + {{- if not .Values.image.rootless }} + chown -v 1000:1000 "${GITEA_TEMP}" + {{- end }} + chmod -v ug+rwx "${GITEA_TEMP}" + + {{ if .Values.signing.enabled -}} + if [ ! -d "${GNUPGHOME}" ]; then + mkdir -pv "${GNUPGHOME}" + chmod -v 700 "${GNUPGHOME}" + chown -v 1000:1000 "${GNUPGHOME}" + fi + {{- end }} + + configure_gitea.sh: |- + #!/usr/bin/env bash + + set -euo pipefail + + echo '==== BEGIN GITEA CONFIGURATION ====' + + { # try + gitea migrate + } || { # catch + echo "Gitea migrate might fail due to database connection...This init-container will try again in a few seconds" + exit 1 + } + + {{- if include "valkey.servicename" . }} + function test_valkey_connection() { + local RETRY=0 + local MAX=30 + + echo 'Wait for valkey to become avialable...' + until [ "${RETRY}" -ge "${MAX}" ]; do + nc -vz -w2 {{ include "valkey.servicename" . }} {{ include "valkey.port" . }} && break + RETRY=$[${RETRY}+1] + echo "...not ready yet (${RETRY}/${MAX})" + done + + if [ "${RETRY}" -ge "${MAX}" ]; then + echo "Valkey not reachable after '${MAX}' attempts!" + exit 1 + fi + } + + test_valkey_connection + {{- end }} + + + {{- if or .Values.gitea.admin.existingSecret (and .Values.gitea.admin.username .Values.gitea.admin.password) }} + function configure_admin_user() { + local full_admin_list=$(gitea admin user list --admin) + local actual_user_table='' + + # We might have distorted output due to warning logs, so we have to detect the actual user table by its headline and trim output above that line + local regex="(.*)(ID\s+Username\s+Email\s+IsActive.*)" + if [[ "${full_admin_list}" =~ $regex ]]; then + actual_user_table=$(echo "${BASH_REMATCH[2]}" | tail -n+2) # tail'ing to drop the table headline + else + # This code block should never be reached, as long as the output table header remains the same. + # If this code block is reached, the regex doesn't match anymore and we probably have to adjust this script. + + echo "ERROR: 'configure_admin_user' was not able to determine the current list of admin users." + echo " Please review the output of 'gitea admin user list --admin' shown below." + echo " If you think it is an issue with the Helm Chart provisioning, file an issue at https://gitea.com/gitea/helm-gitea/issues." + echo "DEBUG: Output of 'gitea admin user list --admin'" + echo "--" + echo "${full_admin_list}" + echo "--" + exit 1 + fi + + local ACCOUNT_ID=$(echo "${actual_user_table}" | grep -E "\s+${GITEA_ADMIN_USERNAME}\s+" | awk -F " " "{printf \$1}") + if [[ -z "${ACCOUNT_ID}" ]]; then + local -a create_args + create_args=(--admin --username "${GITEA_ADMIN_USERNAME}" --password "${GITEA_ADMIN_PASSWORD}" --email {{ .Values.gitea.admin.email | quote }}) + if [[ "${GITEA_ADMIN_PASSWORD_MODE}" = initialOnlyRequireReset ]]; then + create_args+=(--must-change-password=true) + else + create_args+=(--must-change-password=false) + fi + echo "No admin user '${GITEA_ADMIN_USERNAME}' found. Creating now..." + gitea admin user create "${create_args[@]}" + echo '...created.' + else + if [[ "${GITEA_ADMIN_PASSWORD_MODE}" = keepUpdated ]]; then + echo "Admin account '${GITEA_ADMIN_USERNAME}' already exist. Running update to sync password..." + # See https://gitea.com/gitea/helm-gitea/issues/673 + # --must-change-password argument was added to change-password, defaulting to true, counter to the previous behavior + # which acted as if it were provided with =false. If the argument is present in this version of gitea, then we + # should add it to prevent requiring frequent admin password resets. + local -a change_args + change_args=(--username "${GITEA_ADMIN_USERNAME}" --password "${GITEA_ADMIN_PASSWORD}") + if gitea admin user change-password --help | grep -qF -- '--must-change-password'; then + change_args+=(--must-change-password=false) + fi + gitea admin user change-password "${change_args[@]}" + echo '...password sync done.' + else + echo "Admin account '${GITEA_ADMIN_USERNAME}' already exist, but update mode is set to '${GITEA_ADMIN_PASSWORD_MODE}'. Skipping." + fi + fi + } + + configure_admin_user + {{- end }} + + function configure_ldap() { + {{- if .Values.gitea.ldap }} + {{- range $idx, $value := .Values.gitea.ldap }} + local LDAP_NAME={{ (printf "%s" $value.name) | squote }} + local full_auth_list=$(gitea admin auth list --vertical-bars) + local actual_auth_table='' + + # We might have distorted output due to warning logs, so we have to detect the actual user table by its headline and trim output above that line + local regex="(.*)(ID\s+\|Name\s+\|Type\s+\|Enabled.*)" + if [[ "${full_auth_list}" =~ $regex ]]; then + actual_auth_table=$(echo "${BASH_REMATCH[2]}" | tail -n+2) # tail'ing to drop the table headline + else + # This code block should never be reached, as long as the output table header remains the same. + # If this code block is reached, the regex doesn't match anymore and we probably have to adjust this script. + + echo "ERROR: 'configure_ldap' was not able to determine the current list of authentication sources." + echo " Please review the output of 'gitea admin auth list --vertical-bars' shown below." + echo " If you think it is an issue with the Helm Chart provisioning, file an issue at https://gitea.com/gitea/helm-gitea/issues." + echo "DEBUG: Output of 'gitea admin auth list --vertical-bars'" + echo "--" + echo "${full_auth_list}" + echo "--" + exit 1 + fi + + local GITEA_AUTH_ID=$(echo "${actual_auth_table}" | grep -E "\|${LDAP_NAME}\s+\|" | grep -iE '\|LDAP \(via BindDN\)\s+\|' | awk -F " " "{print \$1}") + + if [[ -z "${GITEA_AUTH_ID}" ]]; then + echo "No ldap configuration found with name '${LDAP_NAME}'. Installing it now..." + gitea admin auth add-ldap {{- include "gitea.ldap_settings" (list $idx $value) | indent 1 }} + echo '...installed.' + else + echo "Existing ldap configuration with name '${LDAP_NAME}': '${GITEA_AUTH_ID}'. Running update to sync settings..." + gitea admin auth update-ldap --id "${GITEA_AUTH_ID}" {{- include "gitea.ldap_settings" (list $idx $value) | indent 1 }} + echo '...sync settings done.' + fi + {{- end }} + {{- else }} + echo 'no ldap configuration... skipping.' + {{- end }} + } + + configure_ldap + + function configure_oauth() { + {{- if .Values.gitea.oauth }} + {{- range $idx, $value := .Values.gitea.oauth }} + local OAUTH_NAME={{ (printf "%s" $value.name) | squote }} + local full_auth_list=$(gitea admin auth list --vertical-bars) + local actual_auth_table='' + + # We might have distorted output due to warning logs, so we have to detect the actual user table by its headline and trim output above that line + local regex="(.*)(ID\s+\|Name\s+\|Type\s+\|Enabled.*)" + if [[ "${full_auth_list}" =~ $regex ]]; then + actual_auth_table=$(echo "${BASH_REMATCH[2]}" | tail -n+2) # tail'ing to drop the table headline + else + # This code block should never be reached, as long as the output table header remains the same. + # If this code block is reached, the regex doesn't match anymore and we probably have to adjust this script. + + echo "ERROR: 'configure_oauth' was not able to determine the current list of authentication sources." + echo " Please review the output of 'gitea admin auth list --vertical-bars' shown below." + echo " If you think it is an issue with the Helm Chart provisioning, file an issue at https://gitea.com/gitea/helm-gitea/issues." + echo "DEBUG: Output of 'gitea admin auth list --vertical-bars'" + echo "--" + echo "${full_auth_list}" + echo "--" + exit 1 + fi + + local AUTH_ID=$(echo "${actual_auth_table}" | grep -E "\|${OAUTH_NAME}\s+\|" | grep -iE '\|OAuth2\s+\|' | awk -F " " "{print \$1}") + + if [[ -z "${AUTH_ID}" ]]; then + echo "No oauth configuration found with name '${OAUTH_NAME}'. Installing it now..." + gitea admin auth add-oauth {{- include "gitea.oauth_settings" (list $idx $value) | indent 1 }} + echo '...installed.' + else + echo "Existing oauth configuration with name '${OAUTH_NAME}': '${AUTH_ID}'. Running update to sync settings..." + gitea admin auth update-oauth --id "${AUTH_ID}" {{- include "gitea.oauth_settings" (list $idx $value) | indent 1 }} + echo '...sync settings done.' + fi + {{- end }} + {{- else }} + echo 'no oauth configuration... skipping.' + {{- end }} + } + + configure_oauth + + echo '==== END GITEA CONFIGURATION ====' \ No newline at end of file diff --git a/backing-services/gitea/templates/gitea/metrics-secret.yaml b/backing-services/gitea/templates/gitea/metrics-secret.yaml new file mode 100644 index 0000000..fe26596 --- /dev/null +++ b/backing-services/gitea/templates/gitea/metrics-secret.yaml @@ -0,0 +1,12 @@ +{{- if and (.Values.gitea.metrics.enabled) (.Values.gitea.metrics.serviceMonitor.enabled) (.Values.gitea.metrics.token) -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "gitea.metrics-secret-name" . }} + namespace: {{ .Values.namespace | default .Release.Namespace }} + labels: + {{- include "gitea.labels" . | nindent 4 }} +type: Opaque +data: + token: {{ .Values.gitea.metrics.token | b64enc }} +{{- end }} \ No newline at end of file diff --git a/backing-services/gitea/templates/gitea/poddisruptionbudget.yaml b/backing-services/gitea/templates/gitea/poddisruptionbudget.yaml new file mode 100644 index 0000000..270d5cf --- /dev/null +++ b/backing-services/gitea/templates/gitea/poddisruptionbudget.yaml @@ -0,0 +1,18 @@ +{{- if .Values.podDisruptionBudget -}} +{{- if .Capabilities.APIVersions.Has "policy/v1" }} +apiVersion: policy/v1 +{{- else }} +apiVersion: policy/v1beta1 +{{- end }} +kind: PodDisruptionBudget +metadata: + name: {{ include "gitea.fullname" . }} + namespace: {{ .Values.namespace | default .Release.Namespace }} + labels: + {{- include "gitea.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "gitea.selectorLabels" . | nindent 6 }} + {{- toYaml .Values.podDisruptionBudget | nindent 2 }} +{{- end -}} \ No newline at end of file diff --git a/backing-services/gitea/templates/gitea/pvc.yaml b/backing-services/gitea/templates/gitea/pvc.yaml new file mode 100644 index 0000000..036e3a3 --- /dev/null +++ b/backing-services/gitea/templates/gitea/pvc.yaml @@ -0,0 +1,26 @@ +{{- if and .Values.persistence.enabled .Values.persistence.create }} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ .Values.persistence.claimName }} + namespace: {{ .Values.namespace | default .Release.Namespace }} + annotations: +{{ .Values.persistence.annotations | toYaml | indent 4}} + labels: +{{ .Values.persistence.labels | toYaml | indent 4}} +spec: + accessModes: + {{- if gt (.Values.replicaCount | int) 1 }} + - ReadWriteMany + {{- else }} + {{- .Values.persistence.accessModes | toYaml | nindent 4 }} + {{- end }} + volumeMode: Filesystem + {{- include "gitea.persistence.storageClass" . | nindent 2 }} + {{- with .Values.persistence.volumeName }} + volumeName: {{ . }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size }} +{{- end }} \ No newline at end of file diff --git a/backing-services/gitea/templates/gitea/serviceaccount.yaml b/backing-services/gitea/templates/gitea/serviceaccount.yaml new file mode 100644 index 0000000..0c211c5 --- /dev/null +++ b/backing-services/gitea/templates/gitea/serviceaccount.yaml @@ -0,0 +1,21 @@ +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "gitea.serviceAccountName" . }} + namespace: {{ .Values.namespace | default .Release.Namespace }} + labels: + {{- include "gitea.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.labels }} + {{- . | toYaml | nindent 4 }} + {{- end }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- . | toYaml | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +{{- with .Values.serviceAccount.imagePullSecrets }} +imagePullSecrets: + {{- . | toYaml | nindent 2 }} +{{- end }} +{{- end }} diff --git a/backing-services/gitea/templates/gitea/servicemonitor.yaml b/backing-services/gitea/templates/gitea/servicemonitor.yaml new file mode 100644 index 0000000..502a1a8 --- /dev/null +++ b/backing-services/gitea/templates/gitea/servicemonitor.yaml @@ -0,0 +1,43 @@ +{{- if and .Values.gitea.metrics.enabled .Values.gitea.metrics.serviceMonitor.enabled -}} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "gitea.fullname" . }} + namespace: {{ .Values.namespace | default .Release.Namespace }} + labels: + {{- include "gitea.labels" . | nindent 4 }} + {{- if .Values.gitea.metrics.serviceMonitor.additionalLabels }} + {{- toYaml .Values.gitea.metrics.serviceMonitor.additionalLabels | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "gitea.selectorLabels" . | nindent 6 }} + endpoints: + - port: http + {{- if .Values.gitea.metrics.serviceMonitor.interval }} + interval: {{ .Values.gitea.metrics.serviceMonitor.interval }} + {{- end }} + {{- with .Values.gitea.metrics.serviceMonitor.relabelings }} + relabelings: + {{- . | toYaml | nindent 6 }} + {{- end }} + {{- if .Values.gitea.metrics.serviceMonitor.scheme }} + scheme: {{ .Values.gitea.metrics.serviceMonitor.scheme }} + {{- end }} + {{- if .Values.gitea.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.gitea.metrics.serviceMonitor.scrapeTimeout }} + {{- end }} + {{- with .Values.gitea.metrics.serviceMonitor.tlsConfig }} + tlsConfig: + {{- . | toYaml | nindent 6 }} + {{- end }} + {{- if .Values.gitea.metrics.token }} + authorization: + type: Bearer + credentials: + name: {{ include "gitea.metrics-secret-name" . }} + key: token + optional: false + {{- end }} +{{- end -}} \ No newline at end of file diff --git a/backing-services/gitea/templates/gitea/ssh-svc.yaml b/backing-services/gitea/templates/gitea/ssh-svc.yaml new file mode 100644 index 0000000..b2046fe --- /dev/null +++ b/backing-services/gitea/templates/gitea/ssh-svc.yaml @@ -0,0 +1,57 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "gitea.fullname" . }}-ssh + namespace: {{ .Values.namespace | default .Release.Namespace }} + labels: + {{- include "gitea.labels" . | nindent 4 }} + {{- if .Values.service.ssh.labels }} + {{- toYaml .Values.service.ssh.labels | nindent 4 }} + {{- end }} + annotations: + {{- toYaml .Values.service.ssh.annotations | nindent 4 }} +spec: + type: {{ .Values.service.ssh.type }} + {{- if eq .Values.service.ssh.type "LoadBalancer" }} + {{- if .Values.service.ssh.loadBalancerClass }} + loadBalancerClass: {{ .Values.service.ssh.loadBalancerClass }} + {{- end }} + {{- if .Values.service.ssh.loadBalancerIP }} + loadBalancerIP: {{ .Values.service.ssh.loadBalancerIP }} + {{- end -}} + {{- if .Values.service.ssh.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- range .Values.service.ssh.loadBalancerSourceRanges }} + - {{ . }} + {{- end }} + {{- end }} + {{- end }} + {{- if and .Values.service.ssh.clusterIP (eq .Values.service.ssh.type "ClusterIP") }} + clusterIP: {{ .Values.service.ssh.clusterIP }} + {{- end }} + {{- if .Values.service.ssh.externalIPs }} + externalIPs: + {{- toYaml .Values.service.ssh.externalIPs | nindent 4 }} + {{- end }} + {{- if .Values.service.ssh.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.service.ssh.ipFamilyPolicy }} + {{- end }} + {{- with .Values.service.ssh.ipFamilies }} + ipFamilies: + {{- toYaml . | nindent 4 }} + {{- end -}} + {{- if .Values.service.ssh.externalTrafficPolicy }} + externalTrafficPolicy: {{ .Values.service.ssh.externalTrafficPolicy }} + {{- end }} + ports: + - name: ssh + port: {{ .Values.service.ssh.port }} + {{- if .Values.gitea.config.server.SSH_LISTEN_PORT }} + targetPort: {{ .Values.gitea.config.server.SSH_LISTEN_PORT }} + {{- end }} + protocol: TCP + {{- if .Values.service.ssh.nodePort }} + nodePort: {{ .Values.service.ssh.nodePort }} + {{- end }} + selector: + {{- include "gitea.selectorLabels" . | nindent 4 }} diff --git a/backing-services/gitea/templates/tests/test-http-connection.yaml b/backing-services/gitea/templates/tests/test-http-connection.yaml new file mode 100644 index 0000000..da28ea6 --- /dev/null +++ b/backing-services/gitea/templates/tests/test-http-connection.yaml @@ -0,0 +1,18 @@ +{{- if .Values.test.enabled }} +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "gitea.fullname" . }}-test-connection" + namespace: {{ .Values.namespace | default .Release.Namespace }} + labels: +{{ include "gitea.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test-success +spec: + containers: + - name: wget + image: "{{ .Values.test.image.name }}:{{ .Values.test.image.tag }}" + command: ['wget'] + args: ['{{ include "gitea.fullname" . }}-http:{{ .Values.service.http.port }}'] + restartPolicy: Never +{{- end }} diff --git a/backing-services/gitea/values.yaml b/backing-services/gitea/values.yaml new file mode 100644 index 0000000..bc1b85e --- /dev/null +++ b/backing-services/gitea/values.yaml @@ -0,0 +1,636 @@ +# Default values for gitea. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +## @section Global +# +## @param global.imageRegistry global image registry override +## @param global.imagePullSecrets global image pull secrets override; can be extended by `imagePullSecrets` +## @param global.storageClass global storage class override +## @param global.hostAliases global hostAliases which will be added to the pod's hosts files +global: + imageRegistry: "localhost:30516" + security: + allowInsecureImages: true + ## E.g. + ## imagePullSecrets: + ## - myRegistryKeySecretName + ## + imagePullSecrets: [] + storageClass: "" + hostAliases: [] + # - ip: 192.168.137.2 + # hostnames: + # - example.com + +## @param namespace An explicit namespace to deploy gitea into. Defaults to the release namespace if not specified +namespace: "" + +## @param replicaCount number of replicas for the deployment +replicaCount: 1 + +## @section strategy +## @param strategy.type strategy type +## @param strategy.rollingUpdate.maxSurge maxSurge +## @param strategy.rollingUpdate.maxUnavailable maxUnavailable +strategy: + type: "RollingUpdate" + rollingUpdate: + maxSurge: "100%" + maxUnavailable: 0 + +## @param clusterDomain cluster domain +clusterDomain: cluster.local + +## @section Image +## @param image.registry image registry, e.g. gcr.io,docker.io +## @param image.repository Image to start for this pod +## @param image.tag Visit: [Image tag](https://hub.docker.com/r/gitea/gitea/tags?page=1&ordering=last_updated). Defaults to `appVersion` within Chart.yaml. +## @param image.digest Image digest. Allows to pin the given image tag. Useful for having control over mutable tags like `latest` +## @param image.pullPolicy Image pull policy +## @param image.rootless Wether or not to pull the rootless version of Gitea, only works on Gitea 1.14.x or higher +## @param image.fullOverride Completely overrides the image registry, path/image, tag and digest. **Adjust `image.rootless` accordingly and review [Rootless defaults](#rootless-defaults).** +image: + registry: "docker.gitea.com" + repository: gitea + # Overrides the image tag whose default is the chart appVersion. + tag: "" + digest: "" + pullPolicy: IfNotPresent + rootless: true + fullOverride: "" + +## @param imagePullSecrets Secret to use for pulling the image +imagePullSecrets: [] + +## @section Security +# Security context is only usable with rootless image due to image design +## @param podSecurityContext.fsGroup Set the shared file system group for all containers in the pod. +podSecurityContext: + fsGroup: 1000 + +## @param containerSecurityContext Security context +containerSecurityContext: {} +# allowPrivilegeEscalation: false +# capabilities: +# drop: +# - ALL +# # Add the SYS_CHROOT capability for root and rootless images if you intend to +# # run pods on nodes that use the container runtime cri-o. Otherwise, you will +# # get an error message from the SSH server that it is not possible to read from +# # the repository. +# # https://gitea.com/gitea/helm-gitea/issues/161 +# add: +# - SYS_CHROOT +# privileged: false +# readOnlyRootFilesystem: true +# runAsGroup: 1000 +# runAsNonRoot: true +# runAsUser: 1000 + +## @deprecated The securityContext variable has been split two: +## - containerSecurityContext +## - podSecurityContext. +## @param securityContext Run init and Gitea containers as a specific securityContext +securityContext: {} + +## @param podDisruptionBudget Pod disruption budget +podDisruptionBudget: {} +# maxUnavailable: 1 +# minAvailable: 1 + +## @section Service +service: + ## @param service.http.type Kubernetes service type for web traffic + ## @param service.http.port Port number for web traffic + ## @param service.http.clusterIP ClusterIP setting for http autosetup for deployment is None + ## @param service.http.loadBalancerIP LoadBalancer IP setting + ## @param service.http.nodePort NodePort for http service + ## @param service.http.externalTrafficPolicy If `service.http.type` is `NodePort` or `LoadBalancer`, set this to `Local` to enable source IP preservation + ## @param service.http.externalIPs External IPs for service + ## @param service.http.ipFamilyPolicy HTTP service dual-stack policy + ## @param service.http.ipFamilies HTTP service dual-stack familiy selection,for dual-stack parameters see official kubernetes [dual-stack concept documentation](https://kubernetes.io/docs/concepts/services-networking/dual-stack/). + ## @param service.http.loadBalancerSourceRanges Source range filter for http loadbalancer + ## @param service.http.annotations HTTP service annotations + ## @param service.http.labels HTTP service additional labels + ## @param service.http.loadBalancerClass Loadbalancer class + http: + type: ClusterIP + port: 3000 + clusterIP: None + loadBalancerIP: + nodePort: + externalTrafficPolicy: + externalIPs: + ipFamilyPolicy: + ipFamilies: + loadBalancerSourceRanges: [] + annotations: {} + labels: {} + loadBalancerClass: + ## @param service.ssh.type Kubernetes service type for ssh traffic + ## @param service.ssh.port Port number for ssh traffic + ## @param service.ssh.clusterIP ClusterIP setting for ssh autosetup for deployment is None + ## @param service.ssh.loadBalancerIP LoadBalancer IP setting + ## @param service.ssh.nodePort NodePort for ssh service + ## @param service.ssh.externalTrafficPolicy If `service.ssh.type` is `NodePort` or `LoadBalancer`, set this to `Local` to enable source IP preservation + ## @param service.ssh.externalIPs External IPs for service + ## @param service.ssh.ipFamilyPolicy SSH service dual-stack policy + ## @param service.ssh.ipFamilies SSH service dual-stack familiy selection,for dual-stack parameters see official kubernetes [dual-stack concept documentation](https://kubernetes.io/docs/concepts/services-networking/dual-stack/). + ## @param service.ssh.hostPort HostPort for ssh service + ## @param service.ssh.loadBalancerSourceRanges Source range filter for ssh loadbalancer + ## @param service.ssh.annotations SSH service annotations + ## @param service.ssh.labels SSH service additional labels + ## @param service.ssh.loadBalancerClass Loadbalancer class + ssh: + type: ClusterIP + port: 22 + clusterIP: None + loadBalancerIP: + nodePort: + externalTrafficPolicy: + externalIPs: + ipFamilyPolicy: + ipFamilies: + hostPort: + loadBalancerSourceRanges: [] + annotations: {} + labels: {} + loadBalancerClass: + +## @section Ingress +## @param ingress.enabled Enable ingress +## @param ingress.className DEPRECATED: Ingress class name. +## @param ingress.pathType Ingress Path Type +## @param ingress.annotations Ingress annotations +## @param ingress.hosts[0].host Default Ingress host +## @param ingress.hosts[0].paths[0].path Default Ingress path +## @param ingress.tls Ingress tls settings +ingress: + enabled: true + className: nginx + pathType: Prefix + annotations: {} + hosts: + - host: gitea.bugx.ir + paths: + - path: / + tls: [] + # - secretName: chart-example-tls + # hosts: + # - git.example.com + +## @section deployment +# +## @param resources Kubernetes resources +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 + +## Use an alternate scheduler, e.g. "stork". +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +## @param schedulerName Use an alternate scheduler, e.g. "stork" +schedulerName: "" + +## @param nodeSelector NodeSelector for the deployment +nodeSelector: {} + +## @param tolerations Tolerations for the deployment +tolerations: [] + +## @param affinity Affinity for the deployment +affinity: {} + +## @param topologySpreadConstraints TopologySpreadConstraints for the deployment +topologySpreadConstraints: [] + +## @param dnsConfig dnsConfig for the deployment +dnsConfig: {} + +## @param priorityClassName priorityClassName for the deployment +priorityClassName: "" + +## @param deployment.env Additional environment variables to pass to containers +## @param deployment.terminationGracePeriodSeconds How long to wait until forcefully kill the pod +## @param deployment.labels Labels for the deployment +## @param deployment.annotations Annotations for the Gitea deployment to be created +deployment: + env: + [] + # - name: VARIABLE + # value: my-value + terminationGracePeriodSeconds: 60 + labels: {} + annotations: {} + +## @section ServiceAccount + +## @param serviceAccount.create Enable the creation of a ServiceAccount +## @param serviceAccount.name Name of the created ServiceAccount, defaults to release name. Can also link to an externally provided ServiceAccount that should be used. +## @param serviceAccount.automountServiceAccountToken Enable/disable auto mounting of the service account token +## @param serviceAccount.imagePullSecrets Image pull secrets, available to the ServiceAccount +## @param serviceAccount.annotations Custom annotations for the ServiceAccount +## @param serviceAccount.labels Custom labels for the ServiceAccount +serviceAccount: + create: false + name: "" + automountServiceAccountToken: false + imagePullSecrets: [] + # - name: private-registry-access + annotations: {} + labels: {} + +## @section Persistence +# +## @param persistence.enabled Enable persistent storage +## @param persistence.create Whether to create the persistentVolumeClaim for shared storage +## @param persistence.mount Whether the persistentVolumeClaim should be mounted (even if not created) +## @param persistence.claimName Use an existing claim to store repository information +## @param persistence.size Size for persistence to store repo information +## @param persistence.accessModes AccessMode for persistence +## @param persistence.labels Labels for the persistence volume claim to be created +## @param persistence.annotations.helm.sh/resource-policy Resource policy for the persistence volume claim +## @param persistence.storageClass Name of the storage class to use +## @param persistence.subPath Subdirectory of the volume to mount at +## @param persistence.volumeName Name of persistent volume in PVC +persistence: + enabled: true + create: true + mount: true + claimName: gitea-shared-storage + size: 10Gi + accessModes: + - ReadWriteOnce + labels: {} + storageClass: + subPath: + volumeName: "" + annotations: + helm.sh/resource-policy: keep + +## @param extraContainers Additional sidecar containers to run in the pod +extraContainers: [] +# - name: sidecar-bob +# image: busybox +# command: [/bin/sh, -c, 'echo "Hello world"'] + +## @param preExtraInitContainers Additional init containers to run in the pod before gitea runs it owns init containers. +preExtraInitContainers: [] +# - name: pre-init-container +# image: docker.io/library/busybox +# command: [ /bin/sh, -c, 'echo "Hello world! I am a pre init container."' ] + +## @param postExtraInitContainers Additional init containers to run in the pod after gitea runs it owns init containers. +postExtraInitContainers: [] +# - name: post-init-container +# image: docker.io/library/busybox +# command: [ /bin/sh, -c, 'echo "Hello world! I am a post init container."' ] + +## @param extraVolumes Additional volumes to mount to the Gitea deployment +extraVolumes: [] +# - name: postgres-ssl-vol +# secret: +# secretName: gitea-postgres-ssl + +## @param extraContainerVolumeMounts Mounts that are only mapped into the Gitea runtime/main container, to e.g. override custom templates. +extraContainerVolumeMounts: [] + +## @param extraInitVolumeMounts Mounts that are only mapped into the init-containers. Can be used for additional preconfiguration. +extraInitVolumeMounts: [] + +## @deprecated The extraVolumeMounts variable has been split two: +## - extraContainerVolumeMounts +## - extraInitVolumeMounts +## As an example, can be used to mount a client cert when connecting to an external Postgres server. +## @param extraVolumeMounts **DEPRECATED** Additional volume mounts for init containers and the Gitea main container +extraVolumeMounts: [] +# - name: postgres-ssl-vol +# readOnly: true +# mountPath: "/pg-ssl" + +## @section Init +## @param initPreScript Bash shell script copied verbatim to the start of the init-container. +initPreScript: "" +## @param initContainersScriptsVolumeMountPath Path to mount the scripts consumed from the Secrets +initContainersScriptsVolumeMountPath: "/usr/sbinx" +# +# initPreScript: | +# mkdir -p /data/git/.postgresql +# cp /pg-ssl/* /data/git/.postgresql/ +# chown -R git:git /data/git/.postgresql/ +# chmod 400 /data/git/.postgresql/postgresql.key + +## @param initContainers.resources.limits initContainers.limits Kubernetes resource limits for init containers +## @param initContainers.resources.requests.cpu initContainers.requests.cpu Kubernetes cpu resource limits for init containers +## @param initContainers.resources.requests.memory initContainers.requests.memory Kubernetes memory resource limits for init containers +initContainers: + resources: + limits: {} + requests: + cpu: 100m + memory: 128Mi + +# Configure commit/action signing prerequisites +## @section Signing +# +## @param signing.enabled Enable commit/action signing +## @param signing.gpgHome GPG home directory +## @param signing.privateKey Inline private gpg key for signed internal Git activity +## @param signing.existingSecret Use an existing secret to store the value of `signing.privateKey` +signing: + enabled: false + gpgHome: /data/git/.gnupg + privateKey: "" + # privateKey: |- + # -----BEGIN PGP PRIVATE KEY BLOCK----- + # ... + # -----END PGP PRIVATE KEY BLOCK----- + existingSecret: "" + +## @section Gitea +# +gitea: + ## @param gitea.admin.username Username for the Gitea admin user + ## @param gitea.admin.existingSecret Use an existing secret to store admin user credentials + ## @param gitea.admin.password Password for the Gitea admin user + ## @param gitea.admin.email Email for the Gitea admin user + ## @param gitea.admin.passwordMode Mode for how to set/update the admin user password. Options are: initialOnlyNoReset, initialOnlyRequireReset, and keepUpdated + admin: + # existingSecret: gitea-admin-secret + existingSecret: + username: gitea_admin + password: r8sA8CPHD9!bt6d + email: "gitea@local.domain" + passwordMode: keepUpdated + + ## @param gitea.metrics.enabled Enable Gitea metrics + ## @param gitea.metrics.token used for `bearer` token authentication on metrics endpoint. If not specified or empty metrics endpoint is public. + ## @param gitea.metrics.serviceMonitor.enabled Enable Gitea metrics service monitor. Requires, that `gitea.metrics.enabled` is also set to true, to enable metrics generally. + ## @param gitea.metrics.serviceMonitor.interval Interval at which metrics should be scraped. If not specified Prometheus' global scrape interval is used. + ## @param gitea.metrics.serviceMonitor.relabelings RelabelConfigs to apply to samples before scraping. + ## @param gitea.metrics.serviceMonitor.scheme HTTP scheme to use for scraping. For example `http` or `https`. Default is http. + ## @param gitea.metrics.serviceMonitor.scrapeTimeout Timeout after which the scrape is ended. If not specified, global Prometheus scrape timeout is used. + ## @param gitea.metrics.serviceMonitor.tlsConfig TLS configuration to use when scraping the metric endpoint by Prometheus. + metrics: + enabled: false + token: + serviceMonitor: + enabled: false + # additionalLabels: + # prometheus-release: prom1 + interval: "" + relabelings: [] + scheme: "" + scrapeTimeout: "" + tlsConfig: {} + + ## @param gitea.ldap LDAP configuration + ldap: + [] + # - name: "LDAP 1" + # existingSecret: + # securityProtocol: + # host: + # port: + # userSearchBase: + # userFilter: + # adminFilter: + # emailAttribute: + # bindDn: + # bindPassword: + # usernameAttribute: + # publicSSHKeyAttribute: + + # Either specify inline `key` and `secret` or refer to them via `existingSecret` + ## @param gitea.oauth OAuth configuration + oauth: + [] + # - name: 'OAuth 1' + # provider: + # key: + # secret: + # existingSecret: + # autoDiscoverUrl: + # useCustomUrls: + # customAuthUrl: + # customTokenUrl: + # customProfileUrl: + # customEmailUrl: + + ## @param gitea.config.server.SSH_PORT SSH port for rootlful Gitea image + ## @param gitea.config.server.SSH_LISTEN_PORT SSH port for rootless Gitea image + config: + # APP_NAME: "Gitea: Git with a cup of tea" + # RUN_MODE: dev + server: + SSH_PORT: 22 # rootful image + SSH_LISTEN_PORT: 2222 # rootless image + # + # security: + # PASSWORD_COMPLEXITY: spec + + ## @param gitea.additionalConfigSources Additional configuration from secret or configmap + additionalConfigSources: [] + # - secret: + # secretName: gitea-app-ini-oauth + # - configMap: + # name: gitea-app-ini-plaintext + + ## @param gitea.additionalConfigFromEnvs Additional configuration sources from environment variables + additionalConfigFromEnvs: [] + + ## @param gitea.podAnnotations Annotations for the Gitea pod + podAnnotations: {} + + ## @param gitea.ssh.logLevel Configure OpenSSH's log level. Only available for root-based Gitea image. + ssh: + logLevel: "INFO" + + ## @section LivenessProbe + # + ## @param gitea.livenessProbe.enabled Enable liveness probe + ## @param gitea.livenessProbe.tcpSocket.port Port to probe for liveness + ## @param gitea.livenessProbe.initialDelaySeconds Initial delay before liveness probe is initiated + ## @param gitea.livenessProbe.timeoutSeconds Timeout for liveness probe + ## @param gitea.livenessProbe.periodSeconds Period for liveness probe + ## @param gitea.livenessProbe.successThreshold Success threshold for liveness probe + ## @param gitea.livenessProbe.failureThreshold Failure threshold for liveness probe + # Modify the liveness probe for your needs or completely disable it by commenting out. + livenessProbe: + enabled: true + tcpSocket: + port: http + initialDelaySeconds: 200 + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 10 + + ## @section ReadinessProbe + # + ## @param gitea.readinessProbe.enabled Enable readiness probe + ## @param gitea.readinessProbe.tcpSocket.port Port to probe for readiness + ## @param gitea.readinessProbe.initialDelaySeconds Initial delay before readiness probe is initiated + ## @param gitea.readinessProbe.timeoutSeconds Timeout for readiness probe + ## @param gitea.readinessProbe.periodSeconds Period for readiness probe + ## @param gitea.readinessProbe.successThreshold Success threshold for readiness probe + ## @param gitea.readinessProbe.failureThreshold Failure threshold for readiness probe + # Modify the readiness probe for your needs or completely disable it by commenting out. + readinessProbe: + enabled: true + tcpSocket: + port: http + initialDelaySeconds: 5 + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + + # # Uncomment the startup probe to enable and modify it for your needs. + ## @section StartupProbe + # + ## @param gitea.startupProbe.enabled Enable startup probe + ## @param gitea.startupProbe.tcpSocket.port Port to probe for startup + ## @param gitea.startupProbe.initialDelaySeconds Initial delay before startup probe is initiated + ## @param gitea.startupProbe.timeoutSeconds Timeout for startup probe + ## @param gitea.startupProbe.periodSeconds Period for startup probe + ## @param gitea.startupProbe.successThreshold Success threshold for startup probe + ## @param gitea.startupProbe.failureThreshold Failure threshold for startup probe + startupProbe: + enabled: false + tcpSocket: + port: http + initialDelaySeconds: 60 + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 10 + +## @section valkey-cluster +## @param valkey-cluster.enabled Enable valkey cluster +# ⚠️ The valkey charts do not work well with special characters in the password (). +# Consider omitting such or open an issue in the Bitnami repo and let us know once this got fixed. +## @param valkey-cluster.usePassword Whether to use password authentication +## @param valkey-cluster.usePasswordFiles Whether to mount passwords as files instead of environment variables +## @param valkey-cluster.cluster.nodes Number of valkey cluster master nodes +## @param valkey-cluster.cluster.replicas Number of valkey cluster master node replicas +## @param valkey-cluster.service.ports.valkey Port of Valkey service +## @descriptionStart +## Valkey cluster and [Valkey](#valkey) cannot be enabled at the same time. +## @descriptionEnd +valkey-cluster: + enabled: false + usePassword: false + usePasswordFiles: false + cluster: + nodes: 3 # default: 6 + replicas: 0 # default: 1 + service: + ports: + valkey: 6379 + +## @section valkey +## @param valkey.enabled Enable valkey standalone or replicated +## @param valkey.architecture Whether to use standalone or replication +# ⚠️ The valkey charts do not work well with special characters in the password (). +# Consider omitting such or open an issue in the Bitnami repo and let us know once this got fixed. +## @param valkey.global.valkey.password Required password +## @param valkey.master.count Number of Valkey master instances to deploy +## @param valkey.master.service.ports.valkey Port of Valkey service +## @descriptionStart +## Valkey and [Valkey cluster](#valkey-cluster) cannot be enabled at the same time. +## @descriptionEnd +valkey: + enabled: true + architecture: standalone + global: + valkey: + password: changeme + master: + count: 1 + service: + ports: + valkey: 6379 + +## @section PostgreSQL HA +# +## @param postgresql-ha.enabled Enable PostgreSQL HA +## @param postgresql-ha.postgresql.password Password for the `gitea` user (overrides `auth.password`) +## @param postgresql-ha.global.postgresql.database Name for a custom database to create (overrides `auth.database`) +## @param postgresql-ha.global.postgresql.username Name for a custom user to create (overrides `auth.username`) +## @param postgresql-ha.global.postgresql.password Name for a custom password to create (overrides `auth.password`) +## @param postgresql-ha.postgresql.repmgrPassword Repmgr Password +## @param postgresql-ha.postgresql.postgresPassword postgres Password +## @param postgresql-ha.pgpool.adminPassword pgpool adminPassword +## @param postgresql-ha.pgpool.srCheckPassword pgpool srCheckPassword +## @param postgresql-ha.service.ports.postgresql PostgreSQL service port (overrides `service.ports.postgresql`) +## @param postgresql-ha.persistence.size PVC Storage Request for PostgreSQL HA volume +postgresql-ha: + global: + postgresql: + database: gitea + password: gitea + username: gitea + enabled: false + postgresql: + repmgrPassword: changeme2 + postgresPassword: changeme1 + password: changeme4 + pgpool: + adminPassword: changeme3 + srCheckPassword: changeme4 + service: + ports: + postgresql: 5432 + persistence: + size: 10Gi + +## @section PostgreSQL +# +## @param postgresql.enabled Enable PostgreSQL +## @param postgresql.global.postgresql.auth.password Password for the `gitea` user (overrides `auth.password`) +## @param postgresql.global.postgresql.auth.database Name for a custom database to create (overrides `auth.database`) +## @param postgresql.global.postgresql.auth.username Name for a custom user to create (overrides `auth.username`) +## @param postgresql.global.postgresql.service.ports.postgresql PostgreSQL service port (overrides `service.ports.postgresql`) +## @param postgresql.primary.persistence.size PVC Storage Request for PostgreSQL volume +postgresql: + enabled: true + global: + postgresql: + auth: + password: gitea + database: gitea + username: gitea + service: + ports: + postgresql: 5432 + primary: + persistence: + size: 10Gi + +# By default, removed or moved settings that still remain in a user defined values.yaml will cause Helm to fail running the install/update. +# Set it to false to skip this basic validation check. +## @section Advanced +## @param checkDeprecation Set it to false to skip this basic validation check. +## @param test.enabled Set it to false to disable test-connection Pod. +## @param test.image.name Image name for the wget container used in the test-connection Pod. +## @param test.image.tag Image tag for the wget container used in the test-connection Pod. +checkDeprecation: true +test: + enabled: true + image: + name: busybox + tag: latest + +## @param extraDeploy Array of extra objects to deploy with the release +## +extraDeploy: [] diff --git a/backing-services/gitea/yq.1 b/backing-services/gitea/yq.1 new file mode 100644 index 0000000..fef16e2 --- /dev/null +++ b/backing-services/gitea/yq.1 @@ -0,0 +1,17369 @@ +'\" t +.\" Automatically generated by Pandoc 2.14.2 +.\" +.TH "YQ" "1" "" "" "yq (https://github.com/mikefarah/yq/) version v4.45.4" +.hy +.SH NAME +.PP +\f[I]yq\f[R] is a portable command-line data file processor +.SH SYNOPSIS +.PP +yq [eval/eval-all] [expression] files.. +.PP +eval/e - (default) Apply the expression to each document in each yaml +file in sequence +.PP +eval-all/ea - Loads all yaml documents of all yaml files and runs +expression once +.SH DESCRIPTION +.PP +a lightweight and portable command-line data file processor. +\f[C]yq\f[R] uses jq (https://github.com/stedolan/jq) like syntax but +works with yaml, json, xml, csv, properties and TOML files. +It doesn\[cq]t yet support everything \f[C]jq\f[R] does - but it does +support the most common operations and functions, and more is being +added continuously. +.PP +This documentation is also available at https://mikefarah.gitbook.io/yq/ +# QUICK GUIDE +.SS Read a value: +.IP +.nf +\f[C] +yq \[aq].a.b[0].c\[aq] file.yaml +\f[R] +.fi +.SS Pipe from STDIN: +.IP +.nf +\f[C] +cat file.yaml | yq \[aq].a.b[0].c\[aq] +\f[R] +.fi +.SS Update a yaml file, in place +.IP +.nf +\f[C] +yq -i \[aq].a.b[0].c = \[dq]cool\[dq]\[aq] file.yaml +\f[R] +.fi +.SS Update using environment variables +.IP +.nf +\f[C] +NAME=mike yq -i \[aq].a.b[0].c = strenv(NAME)\[aq] file.yaml +\f[R] +.fi +.SS Merge multiple files +.IP +.nf +\f[C] +yq ea \[aq]. as $item ireduce ({}; . * $item )\[aq] path/to/*.yml +\f[R] +.fi +.PP +Note the use of \f[C]ea\f[R] to evaluate all files at once (instead of +in sequence.) +.SS Multiple updates to a yaml file +.IP +.nf +\f[C] +yq -i \[aq] + .a.b[0].c = \[dq]cool\[dq] | + .x.y.z = \[dq]foobar\[dq] | + .person.name = strenv(NAME) +\[aq] file.yaml +\f[R] +.fi +.PP +See the documentation (https://mikefarah.gitbook.io/yq/) for more. +.SH KNOWN ISSUES / MISSING FEATURES +.IP \[bu] 2 +\f[C]yq\f[R] attempts to preserve comment positions and whitespace as +much as possible, but it does not handle all scenarios (see +https://github.com/go-yaml/yaml/tree/v3 for details) +.IP \[bu] 2 +Powershell has its own\&...opinions: +https://mikefarah.gitbook.io/yq/usage/tips-and-tricks#quotes-in-windows-powershell +.SH BUGS / ISSUES / FEATURE REQUESTS +.PP +Please visit the GitHub page https://github.com/mikefarah/yq/. +.SH HOW IT WORKS +.PP +In \f[C]yq\f[R] expressions are made up of operators and pipes. +A context of nodes is passed through the expression and each operation +takes the context as input and returns a new context as output. +That output is piped in as input for the next operation in the +expression. +To begin with, the context is set to the first yaml document of the +first yaml file (if processing in sequence using eval). +.PP +Lets look at a couple of examples. +.SS Simple assignment example +.PP +Given a document like: +.IP +.nf +\f[C] +a: cat +b: dog +\f[R] +.fi +.PP +with an expression: +.IP +.nf +\f[C] +\&.a = .b +\f[R] +.fi +.PP +Like math expressions - operator precedence is important. +.PP +The \f[C]=\f[R] operator takes two arguments, a \f[C]lhs\f[R] +expression, which in this case is \f[C].a\f[R] and \f[C]rhs\f[R] +expression which is \f[C].b\f[R]. +.PP +It pipes the current, lets call it `root' context through the +\f[C]lhs\f[R] expression of \f[C].a\f[R] to return the node +.IP +.nf +\f[C] +cat +\f[R] +.fi +.PP +Side note: this node holds not only its value `cat', but comments and +metadata too, including path and parent information. +.PP +The \f[C]=\f[R] operator then pipes the `root' context through the +\f[C]rhs\f[R] expression of \f[C].b\f[R] to return the node +.IP +.nf +\f[C] +dog +\f[R] +.fi +.PP +Both sides have now been evaluated, so now the operator copies across +the value from the RHS (\f[C].b\f[R]) to the LHS (\f[C].a\f[R]), and it +returns the now updated context: +.IP +.nf +\f[C] +a: dog +b: dog +\f[R] +.fi +.SS Complex assignment, operator precedence rules +.PP +Just like math expressions - \f[C]yq\f[R] expressions have an order of +precedence. +The pipe \f[C]|\f[R] operator has a low order of precedence, so +operators with higher precedence will get evaluated first. +.PP +Most of the time, this is intuitively what you\[cq]d want, for instance +\f[C].a = \[dq]cat\[dq] | .b = \[dq]dog\[dq]\f[R] is effectively: +\f[C](.a = \[dq]cat\[dq]) | (.b = \[dq]dog\[dq])\f[R]. +.PP +However, this is not always the case, particularly if you have a complex +LHS or RHS expression, for instance if you want to select particular +nodes to update. +.PP +Lets say you had: +.IP +.nf +\f[C] +- name: bob + fruit: apple +- name: sally + fruit: orange +\f[R] +.fi +.PP +Lets say you wanted to update the \f[C]sally\f[R] entry to have fruit: +`mango'. +The \f[I]incorrect\f[R] way to do that is: +\f[C].[] | select(.name == \[dq]sally\[dq]) | .fruit = \[dq]mango\[dq]\f[R]. +.PP +Because \f[C]|\f[R] has a low operator precedence, this will be +evaluated (\f[I]incorrectly\f[R]) as : +\f[C](.[]) | (select(.name == \[dq]sally\[dq])) | (.fruit = \[dq]mango\[dq])\f[R]. +What you\[cq]ll see is only the updated segment returned: +.IP +.nf +\f[C] +name: sally +fruit: mango +\f[R] +.fi +.PP +To properly update this yaml, you will need to use brackets (think +BODMAS from maths) and wrap the entire LHS: +\f[C](.[] | select(.name == \[dq]sally\[dq]) | .fruit) = \[dq]mango\[dq]\f[R] +.PP +Now that entire LHS expression is passed to the `assign' (\f[C]=\f[R]) +operator, and the yaml is correctly updated and returned: +.IP +.nf +\f[C] +- name: bob + fruit: apple +- name: sally + fruit: mango +\f[R] +.fi +.SS Relative update (e.g.\ \f[C]|=\f[R]) +.PP +There is another form of the \f[C]=\f[R] operator which we call the +relative form. +It\[cq]s very similar to \f[C]=\f[R] but with one key difference when +evaluating the RHS expression. +.PP +In the plain form, we pass in the `root' level context to the RHS +expression. +In relative form, we pass in \f[I]each result of the LHS\f[R] to the RHS +expression. +Let\[cq]s go through an example. +.PP +Given a document like: +.IP +.nf +\f[C] +a: 1 +b: thing +\f[R] +.fi +.PP +with an expression: +.IP +.nf +\f[C] +\&.a |= . + 1 +\f[R] +.fi +.PP +Similar to the \f[C]=\f[R] operator, \f[C]|=\f[R] takes two operands, +the LHS and RHS. +.PP +It pipes the current context (the whole document) through the LHS +expression of \f[C].a\f[R] to get the node value: +.IP +.nf +\f[C] +1 +\f[R] +.fi +.PP +Now it pipes \f[I]that LHS context\f[R] into the RHS expression +\f[C]. + 1\f[R] (whereas in the \f[C]=\f[R] plain form it piped the +original document context into the RHS) to yield: +.IP +.nf +\f[C] +2 +\f[R] +.fi +.PP +The assignment operator then copies across the value from the RHS to the +value on the LHS, and it returns the now updated `root' context: +.IP +.nf +\f[C] +a: 2 +b: thing +\f[R] +.fi +.SH Add +.PP +Add behaves differently according to the type of the LHS: * arrays: +concatenate * number scalars: arithmetic addition * string scalars: +concatenate * maps: shallow merge (use the multiply operator +(\f[C]*\f[R]) to deeply merge) +.PP +Use \f[C]+=\f[R] as a relative append assign for things like increment. +Note that \f[C].a += .x\f[R] is equivalent to running +\f[C].a = .a + .x\f[R]. +.SS Concatenate arrays +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + - 1 + - 2 +b: + - 3 + - 4 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a + .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- 1 +- 2 +- 3 +- 4 +\f[R] +.fi +.SS Concatenate to existing array +.PP +Note that the styling of \f[C]a\f[R] is kept. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: [1,2] +b: + - 3 + - 4 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a += .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: [1, 2, 3, 4] +b: + - 3 + - 4 +\f[R] +.fi +.SS Concatenate null to array +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + - 1 + - 2 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a + null\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- 1 +- 2 +\f[R] +.fi +.SS Append to existing array +.PP +Note that the styling is copied from existing array elements +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: [\[aq]dog\[aq]] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a += \[dq]cat\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: [\[aq]dog\[aq], \[aq]cat\[aq]] +\f[R] +.fi +.SS Prepend to existing array +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + - dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a = [\[dq]cat\[dq]] + .a\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + - cat + - dog +\f[R] +.fi +.SS Add new object to array +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + - dog: woof +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a + {\[dq]cat\[dq]: \[dq]meow\[dq]}\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- dog: woof +- cat: meow +\f[R] +.fi +.SS Relative append +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + a1: + b: + - cat + a2: + b: + - dog + a3: {} +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a[].b += [\[dq]mouse\[dq]]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + a1: + b: + - cat + - mouse + a2: + b: + - dog + - mouse + a3: + b: + - mouse +\f[R] +.fi +.SS String concatenation +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +b: meow +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a += .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: catmeow +b: meow +\f[R] +.fi +.SS Number addition - float +.PP +If the lhs or rhs are floats then the expression will be calculated with +floats. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 3 +b: 4.9 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a = .a + .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: 7.9 +b: 4.9 +\f[R] +.fi +.SS Number addition - int +.PP +If both the lhs and rhs are ints then the expression will be calculated +with ints. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 3 +b: 4 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a = .a + .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: 7 +b: 4 +\f[R] +.fi +.SS Increment numbers +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 3 +b: 5 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] += 1\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: 4 +b: 6 +\f[R] +.fi +.SS Date addition +.PP +You can add durations to dates. +Assumes RFC3339 date time format, see date-time +operators (https://mikefarah.gitbook.io/yq/operators/date-time-operators) +for more information. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 2021-01-01T00:00:00Z +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a += \[dq]3h10m\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: 2021-01-01T03:10:00Z +\f[R] +.fi +.SS Date addition - custom format +.PP +You can add durations to dates. +See date-time +operators (https://mikefarah.gitbook.io/yq/operators/date-time-operators) +for more information. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: Saturday, 15-Dec-01 at 2:59AM GMT +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]with_dtf(\[dq]Monday, 02-Jan-06 at 3:04PM MST\[dq], .a += \[dq]3h1m\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: Saturday, 15-Dec-01 at 6:00AM GMT +\f[R] +.fi +.SS Add to null +.PP +Adding to null simply returns the rhs +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]null + \[dq]cat\[dq]\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cat +\f[R] +.fi +.SS Add maps to shallow merge +.PP +Adding objects together shallow merges them. +Use \f[C]*\f[R] to deeply merge. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + thing: + name: Astuff + value: x + a1: cool +b: + thing: + name: Bstuff + legs: 3 + b1: neat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a += .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + thing: + name: Bstuff + legs: 3 + a1: cool + b1: neat +b: + thing: + name: Bstuff + legs: 3 + b1: neat +\f[R] +.fi +.SS Custom types: that are really strings +.PP +When custom tags are encountered, yq will try to decode the underlying +type. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: !horse cat +b: !goat _meow +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a += .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: !horse cat_meow +b: !goat _meow +\f[R] +.fi +.SS Custom types: that are really numbers +.PP +When custom tags are encountered, yq will try to decode the underlying +type. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: !horse 1.2 +b: !goat 2.3 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a += .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: !horse 3.5 +b: !goat 2.3 +\f[R] +.fi +.SH Alternative (Default value) +.PP +This operator is used to provide alternative (or default) values when a +particular expression is either null or false. +.SS LHS is defined +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: bridge +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a // \[dq]hello\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +bridge +\f[R] +.fi +.SS LHS is not defined +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +{} +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a // \[dq]hello\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +hello +\f[R] +.fi +.SS LHS is null +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: \[ti] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a // \[dq]hello\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +hello +\f[R] +.fi +.SS LHS is false +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: false +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a // \[dq]hello\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +hello +\f[R] +.fi +.SS RHS is an expression +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: false +b: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a // .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cat +\f[R] +.fi +.SS Update or create - entity exists +.PP +This initialises \f[C]a\f[R] if it\[cq]s not present +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 1 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq](.a // (.a = 0)) += 1\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: 2 +\f[R] +.fi +.SS Update or create - entity does not exist +.PP +This initialises \f[C]a\f[R] if it\[cq]s not present +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +b: camel +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq](.a // (.a = 0)) += 1\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +b: camel +a: 1 +\f[R] +.fi +.SH Anchor and Alias Operators +.PP +Use the \f[C]alias\f[R] and \f[C]anchor\f[R] operators to read and write +yaml aliases and anchors. +The \f[C]explode\f[R] operator normalises a yaml file (dereference (or +expands) aliases and remove anchor names). +.PP +\f[C]yq\f[R] supports merge aliases (like \f[C]<<: *blah\f[R]) however +this is no longer in the standard yaml spec (1.2) and so \f[C]yq\f[R] +will automatically add the \f[C]!!merge\f[R] tag to these nodes as it is +effectively a custom tag. +.SS Merge one map +.PP +see https://yaml.org/type/merge.html +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- &CENTER + x: 1 + y: 2 +- &LEFT + x: 0 + y: 2 +- &BIG + r: 10 +- &SMALL + r: 1 +- !!merge <<: *CENTER + r: 10 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[4] | explode(.)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +x: 1 +y: 2 +r: 10 +\f[R] +.fi +.SS Merge multiple maps +.PP +see https://yaml.org/type/merge.html +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- &CENTER + x: 1 + y: 2 +- &LEFT + x: 0 + y: 2 +- &BIG + r: 10 +- &SMALL + r: 1 +- !!merge <<: + - *CENTER + - *BIG +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[4] | explode(.)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +r: 10 +x: 1 +y: 2 +\f[R] +.fi +.SS Override +.PP +see https://yaml.org/type/merge.html +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- &CENTER + x: 1 + y: 2 +- &LEFT + x: 0 + y: 2 +- &BIG + r: 10 +- &SMALL + r: 1 +- !!merge <<: + - *BIG + - *LEFT + - *SMALL + x: 1 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[4] | explode(.)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +r: 10 +x: 1 +y: 2 +\f[R] +.fi +.SS Get anchor +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: &billyBob cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a | anchor\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +billyBob +\f[R] +.fi +.SS Set anchor +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a anchor = \[dq]foobar\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: &foobar cat +\f[R] +.fi +.SS Set anchor relatively using assign-update +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + b: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a anchor |= .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: &cat + b: cat +\f[R] +.fi +.SS Get alias +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +b: &billyBob meow +a: *billyBob +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a | alias\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +billyBob +\f[R] +.fi +.SS Set alias +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +b: &meow purr +a: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a alias = \[dq]meow\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +b: &meow purr +a: *meow +\f[R] +.fi +.SS Set alias to blank does nothing +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +b: &meow purr +a: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a alias = \[dq]\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +b: &meow purr +a: cat +\f[R] +.fi +.SS Set alias relatively using assign-update +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +b: &meow purr +a: + f: meow +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a alias |= .f\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +b: &meow purr +a: *meow +\f[R] +.fi +.SS Explode alias and anchor +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +f: + a: &a cat + b: *a +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]explode(.f)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +f: + a: cat + b: cat +\f[R] +.fi +.SS Explode with no aliases or anchors +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: mike +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]explode(.a)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: mike +\f[R] +.fi +.SS Explode with alias keys +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +f: + a: &a cat + *a: b +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]explode(.f)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +f: + a: cat + cat: b +\f[R] +.fi +.SS Explode with merge anchors +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +foo: &foo + a: foo_a + thing: foo_thing + c: foo_c +bar: &bar + b: bar_b + thing: bar_thing + c: bar_c +foobarList: + b: foobarList_b + !!merge <<: + - *foo + - *bar + c: foobarList_c +foobar: + c: foobar_c + !!merge <<: *foo + thing: foobar_thing +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]explode(.)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +foo: + a: foo_a + thing: foo_thing + c: foo_c +bar: + b: bar_b + thing: bar_thing + c: bar_c +foobarList: + b: bar_b + thing: foo_thing + c: foobarList_c + a: foo_a +foobar: + c: foo_c + a: foo_a + thing: foobar_thing +\f[R] +.fi +.SS Dereference and update a field +.PP +Use explode with multiply to dereference an object +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +item_value: &item_value + value: true +thingOne: + name: item_1 + !!merge <<: *item_value +thingTwo: + name: item_2 + !!merge <<: *item_value +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].thingOne |= explode(.) * {\[dq]value\[dq]: false}\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +item_value: &item_value + value: true +thingOne: + name: item_1 + value: false +thingTwo: + name: item_2 + !!merge <<: *item_value +\f[R] +.fi +.SH Array to Map +.PP +Use this operator to convert an array to..a map. +The indices are used as map keys, null values in the array are skipped +over. +.PP +Behind the scenes, this is implemented using reduce: +.IP +.nf +\f[C] +(.[] | select(. != null) ) as $i ireduce({}; .[$i | key] = $i) +\f[R] +.fi +.SS Simple example +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +cool: + - null + - null + - hello +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].cool |= array_to_map\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cool: + 2: hello +\f[R] +.fi +.SH Assign (Update) +.PP +This operator is used to update node values. +It can be used in either the: +.SS plain form: \f[C]=\f[R] +.PP +Which will set the LHS node values equal to the RHS node values. +The RHS expression is run against the matching nodes in the pipeline. +.SS relative form: \f[C]|=\f[R] +.PP +This will do a similar thing to the plain form, but the RHS expression +is run with \f[I]each LHS node as context\f[R]. +This is useful for updating values based on old values, e.g.\ increment. +.SS Flags +.IP \[bu] 2 +\f[C]c\f[R] clobber custom tags +.SS Create yaml file +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq].a.b = \[dq]cat\[dq] | .x = \[dq]frog\[dq]\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: cat +x: frog +\f[R] +.fi +.SS Update node to be the child value +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + b: + g: foof +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a |= .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + g: foof +\f[R] +.fi +.SS Double elements in an array +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- 1 +- 2 +- 3 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] |= . * 2\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- 2 +- 4 +- 6 +\f[R] +.fi +.SS Update node from another file +.PP +Note this will also work when the second file is a scalar +(string/number) +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: apples +\f[R] +.fi +.PP +And another sample another.yml file of: +.IP +.nf +\f[C] +b: bob +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq eval-all \[aq]select(fileIndex==0).a = select(fileIndex==1) | select(fileIndex==0)\[aq] sample.yml another.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: bob +\f[R] +.fi +.SS Update node to be the sibling value +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + b: child +b: sibling +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a = .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: sibling +b: sibling +\f[R] +.fi +.SS Updated multiple paths +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: fieldA +b: fieldB +c: fieldC +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq](.a, .c) = \[dq]potato\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: potato +b: fieldB +c: potato +\f[R] +.fi +.SS Update string value +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + b: apple +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a.b = \[dq]frog\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: frog +\f[R] +.fi +.SS Update string value via |= +.PP +Note there is no difference between \f[C]=\f[R] and \f[C]|=\f[R] when +the RHS is a scalar +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + b: apple +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a.b |= \[dq]frog\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: frog +\f[R] +.fi +.SS Update deeply selected results +.PP +Note that the LHS is wrapped in brackets! This is to ensure we don\[cq]t +first filter out the yaml and then update the snippet. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + b: apple + c: cactus +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq](.a[] | select(. == \[dq]apple\[dq])) = \[dq]frog\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: frog + c: cactus +\f[R] +.fi +.SS Update array values +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- candy +- apple +- sandy +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq](.[] | select(. == \[dq]*andy\[dq])) = \[dq]bogs\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- bogs +- apple +- bogs +\f[R] +.fi +.SS Update empty object +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +{} +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a.b |= \[dq]bogs\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: bogs +\f[R] +.fi +.SS Update node value that has an anchor +.PP +Anchor will remain +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: &cool cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a = \[dq]dog\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: &cool dog +\f[R] +.fi +.SS Update empty object and array +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +{} +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a.b.[0] |= \[dq]bogs\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: + - bogs +\f[R] +.fi +.SS Custom types are maintained by default +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: !cat meow +b: !dog woof +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a = .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: !cat woof +b: !dog woof +\f[R] +.fi +.SS Custom types: clobber +.PP +Use the \f[C]c\f[R] option to clobber custom tags +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: !cat meow +b: !dog woof +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a =c .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: !dog woof +b: !dog woof +\f[R] +.fi +.SH Boolean Operators +.PP +The \f[C]or\f[R] and \f[C]and\f[R] operators take two parameters and +return a boolean result. +.PP +\f[C]not\f[R] flips a boolean from true to false, or vice versa. +.PP +\f[C]any\f[R] will return \f[C]true\f[R] if there are any \f[C]true\f[R] +values in an array sequence, and \f[C]all\f[R] will return true if +\f[I]all\f[R] elements in an array are true. +.PP +\f[C]any_c(condition)\f[R] and \f[C]all_c(condition)\f[R] are like +\f[C]any\f[R] and \f[C]all\f[R] but they take a condition expression +that is used against each element to determine if it\[cq]s +\f[C]true\f[R]. +Note: in \f[C]jq\f[R] you can simply pass a condition to \f[C]any\f[R] +or \f[C]all\f[R] and it simply works - \f[C]yq\f[R] isn\[cq]t that +clever..yet +.PP +These are most commonly used with the \f[C]select\f[R] operator to +filter particular nodes. +.SS Related Operators +.IP \[bu] 2 +equals / not equals (\f[C]==\f[R], \f[C]!=\f[R]) operators +here (https://mikefarah.gitbook.io/yq/operators/equals) +.IP \[bu] 2 +comparison (\f[C]>=\f[R], \f[C]<\f[R] etc) operators +here (https://mikefarah.gitbook.io/yq/operators/compare) +.IP \[bu] 2 +select operator here (https://mikefarah.gitbook.io/yq/operators/select) +.SS \f[C]or\f[R] example +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]true or false\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +true +\f[R] +.fi +.SS \[lq]yes\[rq] and \[lq]no\[rq] are strings +.PP +In the yaml 1.2 standard, support for yes/no as booleans was dropped - +they are now considered strings. +See `10.2.1.2. Boolean' in https://yaml.org/spec/1.2.2/ +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- yes +- no +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] | tag\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +!!str +!!str +\f[R] +.fi +.SS \f[C]and\f[R] example +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]true and false\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +false +\f[R] +.fi +.SS Matching nodes with select, equals and or +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- a: bird + b: dog +- a: frog + b: bird +- a: cat + b: fly +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq][.[] | select(.a == \[dq]cat\[dq] or .b == \[dq]dog\[dq])]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- a: bird + b: dog +- a: cat + b: fly +\f[R] +.fi +.SS \f[C]any\f[R] returns true if any boolean in a given array is true +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- false +- true +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]any\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +true +\f[R] +.fi +.SS \f[C]any\f[R] returns false for an empty array +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +[] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]any\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +false +\f[R] +.fi +.SS \f[C]any_c\f[R] returns true if any element in the array is true for the given condition. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + - rad + - awesome +b: + - meh + - whatever +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] |= any_c(. == \[dq]awesome\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: true +b: false +\f[R] +.fi +.SS \f[C]all\f[R] returns true if all booleans in a given array are true +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- true +- true +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]all\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +true +\f[R] +.fi +.SS \f[C]all\f[R] returns true for an empty array +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +[] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]all\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +true +\f[R] +.fi +.SS \f[C]all_c\f[R] returns true if all elements in the array are true for the given condition. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + - rad + - awesome +b: + - meh + - 12 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] |= all_c(tag == \[dq]!!str\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: true +b: false +\f[R] +.fi +.SS Not true is false +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]true | not\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +false +\f[R] +.fi +.SS Not false is true +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]false | not\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +true +\f[R] +.fi +.SS String values considered to be true +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]\[dq]cat\[dq] | not\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +false +\f[R] +.fi +.SS Empty string value considered to be true +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]\[dq]\[dq] | not\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +false +\f[R] +.fi +.SS Numbers are considered to be true +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]1 | not\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +false +\f[R] +.fi +.SS Zero is considered to be true +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]0 | not\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +false +\f[R] +.fi +.SS Null is considered to be false +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]\[ti] | not\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +true +\f[R] +.fi +.SH Collect into Array +.PP +This creates an array using the expression between the square brackets. +.SS Collect empty +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq][]\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +[] +\f[R] +.fi +.SS Collect single +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq][\[dq]cat\[dq]]\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- cat +\f[R] +.fi +.SS Collect many +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +b: dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq][.a, .b]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- cat +- dog +\f[R] +.fi +.SH Column +.PP +Returns the column of the matching node. +Starts from 1, 0 indicates there was no column data. +.PP +Column is the number of characters that precede that node on the line it +starts. +.SS Returns column of \f[I]value\f[R] node +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +b: bob +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].b | column\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +4 +\f[R] +.fi +.SS Returns column of \f[I]key\f[R] node +.PP +Pipe through the key operator to get the column of the key +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +b: bob +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].b | key | column\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +1 +\f[R] +.fi +.SS First column is 1 +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a | key | column\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +1 +\f[R] +.fi +.SS No column data is 0 +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]{\[dq]a\[dq]: \[dq]new entry\[dq]} | column\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +0 +\f[R] +.fi +.SH Comment Operators +.PP +Use these comment operators to set or retrieve comments. +Note that line comments on maps/arrays are actually set on the +\f[I]key\f[R] node as opposed to the \f[I]value\f[R] (map/array). +See below for examples. +.PP +Like the \f[C]=\f[R] and \f[C]|=\f[R] assign operators, the same syntax +applies when updating comments: +.SS plain form: \f[C]=\f[R] +.PP +This will set the LHS nodes\[cq] comments equal to the expression on the +RHS. +The RHS is run against the matching nodes in the pipeline +.SS relative form: \f[C]|=\f[R] +.PP +This is similar to the plain form, but it evaluates the RHS with +\f[I]each matching LHS node as context\f[R]. +This is useful if you want to set the comments as a relative expression +of the node, for instance its value or path. +.SS Set line comment +.PP +Set the comment on the key node for more reliability (see below). +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a line_comment=\[dq]single\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: cat # single +\f[R] +.fi +.SS Set line comment of a maps/arrays +.PP +For maps and arrays, you need to set the line comment on the +\f[I]key\f[R] node. +This will also work for scalars. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + b: things +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq](.a | key) line_comment=\[dq]single\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: # single + b: things +\f[R] +.fi +.SS Use update assign to perform relative updates +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +b: dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].. line_comment |= .\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: cat # cat +b: dog # dog +\f[R] +.fi +.SS Where is the comment - map key example +.PP +The underlying yaml parser can assign comments in a document to +surprising nodes. +Use an expression like this to find where you comment is. +`p' indicates the path, `isKey' is if the node is a map key (as opposed +to a map value). +From this, you can see the `hello-world-comment' is actually on the +`hello' key +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +hello: # hello-world-comment + message: world +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq][... | {\[dq]p\[dq]: path | join(\[dq].\[dq]), \[dq]isKey\[dq]: is_key, \[dq]hc\[dq]: headComment, \[dq]lc\[dq]: lineComment, \[dq]fc\[dq]: footComment}]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- p: \[dq]\[dq] + isKey: false + hc: \[dq]\[dq] + lc: \[dq]\[dq] + fc: \[dq]\[dq] +- p: hello + isKey: true + hc: \[dq]\[dq] + lc: hello-world-comment + fc: \[dq]\[dq] +- p: hello + isKey: false + hc: \[dq]\[dq] + lc: \[dq]\[dq] + fc: \[dq]\[dq] +- p: hello.message + isKey: true + hc: \[dq]\[dq] + lc: \[dq]\[dq] + fc: \[dq]\[dq] +- p: hello.message + isKey: false + hc: \[dq]\[dq] + lc: \[dq]\[dq] + fc: \[dq]\[dq] +\f[R] +.fi +.SS Retrieve comment - map key example +.PP +From the previous example, we know that the comment is on the `hello' +\f[I]key\f[R] as a lineComment +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +hello: # hello-world-comment + message: world +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].hello | key | line_comment\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +hello-world-comment +\f[R] +.fi +.SS Where is the comment - array example +.PP +The underlying yaml parser can assign comments in a document to +surprising nodes. +Use an expression like this to find where you comment is. +`p' indicates the path, `isKey' is if the node is a map key (as opposed +to a map value). +From this, you can see the `under-name-comment' is actually on the first +child +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +name: + # under-name-comment + - first-array-child +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq][... | {\[dq]p\[dq]: path | join(\[dq].\[dq]), \[dq]isKey\[dq]: is_key, \[dq]hc\[dq]: headComment, \[dq]lc\[dq]: lineComment, \[dq]fc\[dq]: footComment}]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- p: \[dq]\[dq] + isKey: false + hc: \[dq]\[dq] + lc: \[dq]\[dq] + fc: \[dq]\[dq] +- p: name + isKey: true + hc: \[dq]\[dq] + lc: \[dq]\[dq] + fc: \[dq]\[dq] +- p: name + isKey: false + hc: \[dq]\[dq] + lc: \[dq]\[dq] + fc: \[dq]\[dq] +- p: name.0 + isKey: false + hc: under-name-comment + lc: \[dq]\[dq] + fc: \[dq]\[dq] +\f[R] +.fi +.SS Retrieve comment - array example +.PP +From the previous example, we know that the comment is on the first +child as a headComment +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +name: + # under-name-comment + - first-array-child +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].name[0] | headComment\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +under-name-comment +\f[R] +.fi +.SS Set head comment +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]. head_comment=\[dq]single\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +# single +a: cat +\f[R] +.fi +.SS Set head comment of a map entry +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +f: foo +a: + b: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq](.a | key) head_comment=\[dq]single\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +f: foo +# single +a: + b: cat +\f[R] +.fi +.SS Set foot comment, using an expression +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]. foot_comment=.a\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: cat +# cat +\f[R] +.fi +.SS Remove comment +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat # comment +b: dog # leave this +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a line_comment=\[dq]\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: cat +b: dog # leave this +\f[R] +.fi +.SS Remove (strip) all comments +.PP +Note the use of \f[C]...\f[R] to ensure key nodes are included. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +# hi + +a: cat # comment +# great +b: # key comment +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]... comments=\[dq]\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: cat +b: +\f[R] +.fi +.SS Get line comment +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +# welcome! + +a: cat # meow +# have a great day +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a | line_comment\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +meow +\f[R] +.fi +.SS Get head comment +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +# welcome! + +a: cat # meow + +# have a great day +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]. | head_comment\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +welcome! +\f[R] +.fi +.SS Head comment with document split +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +# welcome! +--- +# bob +a: cat # meow + +# have a great day +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]head_comment\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +welcome! +bob +\f[R] +.fi +.SS Get foot comment +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +# welcome! + +a: cat # meow + +# have a great day +# no really +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]. | foot_comment\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +have a great day +no really +\f[R] +.fi +.SH Compare Operators +.PP +Comparison operators (\f[C]>\f[R], \f[C]>=\f[R], \f[C]<\f[R], +\f[C]<=\f[R]) can be used for comparing scalar values of the same time. +.PP +The following types are currently supported: +.IP \[bu] 2 +numbers +.IP \[bu] 2 +strings +.IP \[bu] 2 +datetimes +.SS Related Operators +.IP \[bu] 2 +equals / not equals (\f[C]==\f[R], \f[C]!=\f[R]) operators +here (https://mikefarah.gitbook.io/yq/operators/equals) +.IP \[bu] 2 +boolean operators (\f[C]and\f[R], \f[C]or\f[R], \f[C]any\f[R] etc) +here (https://mikefarah.gitbook.io/yq/operators/boolean-operators) +.IP \[bu] 2 +select operator here (https://mikefarah.gitbook.io/yq/operators/select) +.SS Compare numbers (>) +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 5 +b: 4 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a > .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +true +\f[R] +.fi +.SS Compare equal numbers (>=) +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 5 +b: 5 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a >= .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +true +\f[R] +.fi +.SS Compare strings +.PP +Compares strings by their bytecode. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: zoo +b: apple +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a > .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +true +\f[R] +.fi +.SS Compare date times +.PP +You can compare date times. +Assumes RFC3339 date time format, see date-time +operators (https://mikefarah.gitbook.io/yq/operators/date-time-operators) +for more information. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 2021-01-01T03:10:00Z +b: 2020-01-01T03:10:00Z +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a > .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +true +\f[R] +.fi +.SS Both sides are null: > is false +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq].a > .b\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +false +\f[R] +.fi +.SS Both sides are null: >= is true +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq].a >= .b\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +true +\f[R] +.fi +.SH Contains +.PP +This returns \f[C]true\f[R] if the context contains the passed in +parameter, and false otherwise. +For arrays, this will return true if the passed in array is contained +within the array. +For strings, it will return true if the string is a substring. +.PP +{% hint style=\[lq]warning\[rq] %} +.PP +\f[I]Note\f[R] that, just like jq, when checking if an array of strings +\f[C]contains\f[R] another, this will use \f[C]contains\f[R] and +\f[I]not\f[R] equals to check each string. +This means an expression like \f[C]contains([\[dq]cat\[dq]])\f[R] will +return true for an array \f[C][\[dq]cats\[dq]]\f[R]. +.PP +See the \[lq]Array has a subset array\[rq] example below on how to check +for a subset. +.PP +{% endhint %} +.SS Array contains array +.PP +Array is equal or subset of +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- foobar +- foobaz +- blarp +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]contains([\[dq]baz\[dq], \[dq]bar\[dq]])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +true +\f[R] +.fi +.SS Array has a subset array +.PP +Subtract the superset array from the subset, if there\[cq]s anything +left, it\[cq]s not a subset +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- foobar +- foobaz +- blarp +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq][\[dq]baz\[dq], \[dq]bar\[dq]] - . | length == 0\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +false +\f[R] +.fi +.SS Object included in array +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +\[dq]foo\[dq]: 12 +\[dq]bar\[dq]: + - 1 + - 2 + - \[dq]barp\[dq]: 12 + \[dq]blip\[dq]: 13 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]contains({\[dq]bar\[dq]: [{\[dq]barp\[dq]: 12}]})\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +true +\f[R] +.fi +.SS Object not included in array +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +\[dq]foo\[dq]: 12 +\[dq]bar\[dq]: + - 1 + - 2 + - \[dq]barp\[dq]: 12 + \[dq]blip\[dq]: 13 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]contains({\[dq]foo\[dq]: 12, \[dq]bar\[dq]: [{\[dq]barp\[dq]: 15}]})\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +false +\f[R] +.fi +.SS String contains substring +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +foobar +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]contains(\[dq]bar\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +true +\f[R] +.fi +.SS String equals string +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +meow +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]contains(\[dq]meow\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +true +\f[R] +.fi +.SH Create, Collect into Object +.PP +This is used to construct objects (or maps). +This can be used against existing yaml, or to create fresh yaml +documents. +.SS Collect empty object +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]{}\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +{} +\f[R] +.fi +.SS Wrap (prefix) existing object +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +name: Mike +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]{\[dq]wrap\[dq]: .}\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +wrap: + name: Mike +\f[R] +.fi +.SS Using splat to create multiple objects +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +name: Mike +pets: + - cat + - dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]{.name: .pets.[]}\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +Mike: cat +Mike: dog +\f[R] +.fi +.SS Working with multiple documents +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +name: Mike +pets: + - cat + - dog +--- +name: Rosey +pets: + - monkey + - sheep +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]{.name: .pets.[]}\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +Mike: cat +Mike: dog +--- +Rosey: monkey +Rosey: sheep +\f[R] +.fi +.SS Creating yaml from scratch +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]{\[dq]wrap\[dq]: \[dq]frog\[dq]}\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +wrap: frog +\f[R] +.fi +.SS Creating yaml from scratch with multiple objects +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq](.a.b = \[dq]foo\[dq]) | (.d.e = \[dq]bar\[dq])\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: foo +d: + e: bar +\f[R] +.fi +.SH Date Time +.PP +Various operators for parsing and manipulating dates. +.SS Date time formattings +.PP +This uses Golang\[cq]s built in time library for parsing and formatting +date times. +.PP +When not specified, the RFC3339 standard is assumed +\f[C]2006-01-02T15:04:05Z07:00\f[R] for parsing. +.PP +To specify a custom parsing format, use the \f[C]with_dtf\f[R] operator. +The first parameter sets the datetime parsing format for the expression +in the second parameter. +The expression can be any valid \f[C]yq\f[R] expression tree. +.IP +.nf +\f[C] +yq \[aq]with_dtf(\[dq]myformat\[dq]; .a + \[dq]3h\[dq] | tz(\[dq]Australia/Melbourne\[dq]))\[aq] +\f[R] +.fi +.PP +See the library docs (https://pkg.go.dev/time#pkg-constants) for +examples of formatting options. +.SS Timezones +.PP +This uses Golang\[cq]s built in LoadLocation function to parse timezones +strings. +See the library docs (https://pkg.go.dev/time#LoadLocation) for more +details. +.SS Durations +.PP +Durations are parsed using Golang\[cq]s built in +ParseDuration (https://pkg.go.dev/time#ParseDuration) function. +.PP +You can add durations to time using the \f[C]+\f[R] operator. +.SS Format: from standard RFC3339 format +.PP +Providing a single parameter assumes a standard RFC3339 datetime format. +If the target format is not a valid yaml datetime format, the result +will be a string tagged node. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 2001-12-15T02:59:43.1Z +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a |= format_datetime(\[dq]Monday, 02-Jan-06 at 3:04PM\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: Saturday, 15-Dec-01 at 2:59AM +\f[R] +.fi +.SS Format: from custom date time +.PP +Use with_dtf to set a custom datetime format for parsing. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: Saturday, 15-Dec-01 at 2:59AM +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a |= with_dtf(\[dq]Monday, 02-Jan-06 at 3:04PM\[dq]; format_datetime(\[dq]2006-01-02\[dq]))\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: 2001-12-15 +\f[R] +.fi +.SS Format: get the day of the week +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 2001-12-15 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a | format_datetime(\[dq]Monday\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +Saturday +\f[R] +.fi +.SS Now +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cool +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].updated = now\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: cool +updated: 2021-05-19T01:02:03Z +\f[R] +.fi +.SS From Unix +.PP +Converts from unix time. +Note, you don\[cq]t have to pipe through the tz operator :) +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]1675301929 | from_unix | tz(\[dq]UTC\[dq])\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +2023-02-02T01:38:49Z +\f[R] +.fi +.SS To Unix +.PP +Converts to unix time +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]now | to_unix\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +1621386123 +\f[R] +.fi +.SS Timezone: from standard RFC3339 format +.PP +Returns a new datetime in the specified timezone. +Specify standard IANA Time Zone format or `utc', `local'. +When given a single parameter, this assumes the datetime is in RFC3339 +format. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cool +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].updated = (now | tz(\[dq]Australia/Sydney\[dq]))\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: cool +updated: 2021-05-19T11:02:03+10:00 +\f[R] +.fi +.SS Timezone: with custom format +.PP +Specify standard IANA Time Zone format or `utc', `local' +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: Saturday, 15-Dec-01 at 2:59AM GMT +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a |= with_dtf(\[dq]Monday, 02-Jan-06 at 3:04PM MST\[dq]; tz(\[dq]Australia/Sydney\[dq]))\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: Saturday, 15-Dec-01 at 1:59PM AEDT +\f[R] +.fi +.SS Add and tz custom format +.PP +Specify standard IANA Time Zone format or `utc', `local' +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: Saturday, 15-Dec-01 at 2:59AM GMT +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a |= with_dtf(\[dq]Monday, 02-Jan-06 at 3:04PM MST\[dq]; tz(\[dq]Australia/Sydney\[dq]))\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: Saturday, 15-Dec-01 at 1:59PM AEDT +\f[R] +.fi +.SS Date addition +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 2021-01-01T00:00:00Z +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a += \[dq]3h10m\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: 2021-01-01T03:10:00Z +\f[R] +.fi +.SS Date subtraction +.PP +You can subtract durations from dates. +Assumes RFC3339 date time format, see date-time +operators (https://mikefarah.gitbook.io/yq/operators/datetime#date-time-formattings) +for more information. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 2021-01-01T03:10:00Z +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a -= \[dq]3h10m\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: 2021-01-01T00:00:00Z +\f[R] +.fi +.SS Date addition - custom format +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: Saturday, 15-Dec-01 at 2:59AM GMT +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]with_dtf(\[dq]Monday, 02-Jan-06 at 3:04PM MST\[dq]; .a += \[dq]3h1m\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: Saturday, 15-Dec-01 at 6:00AM GMT +\f[R] +.fi +.SS Date script with custom format +.PP +You can embed full expressions in with_dtf if needed. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: Saturday, 15-Dec-01 at 2:59AM GMT +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]with_dtf(\[dq]Monday, 02-Jan-06 at 3:04PM MST\[dq]; .a = (.a + \[dq]3h1m\[dq] | tz(\[dq]Australia/Perth\[dq])))\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: Saturday, 15-Dec-01 at 2:00PM AWST +\f[R] +.fi +.SH Delete +.PP +Deletes matching entries in maps or arrays. +.SS Delete entry in map +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +b: dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]del(.b)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: cat +\f[R] +.fi +.SS Delete nested entry in map +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + a1: fred + a2: frood +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]del(.a.a1)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + a2: frood +\f[R] +.fi +.SS Delete entry in array +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- 1 +- 2 +- 3 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]del(.[1])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- 1 +- 3 +\f[R] +.fi +.SS Delete nested entry in array +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- a: cat + b: dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]del(.[0].a)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- b: dog +\f[R] +.fi +.SS Delete no matches +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +b: dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]del(.c)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: cat +b: dog +\f[R] +.fi +.SS Delete matching entries +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +b: dog +c: bat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]del( .[] | select(. == \[dq]*at\[dq]) )\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +b: dog +\f[R] +.fi +.SS Recursively delete matching keys +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + name: frog + b: + name: blog + age: 12 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]del(.. | select(has(\[dq]name\[dq])).name)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: + age: 12 +\f[R] +.fi +.SH Divide +.PP +Divide behaves differently according to the type of the LHS: * strings: +split by the divider * number: arithmetic division +.SS String split +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat_meow +b: _ +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].c = .a / .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: cat_meow +b: _ +c: + - cat + - meow +\f[R] +.fi +.SS Number division +.PP +The result during division is calculated as a float +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 12 +b: 2.5 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a = .a / .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: 4.8 +b: 2.5 +\f[R] +.fi +.SS Number division by zero +.PP +Dividing by zero results in +Inf or -Inf +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 1 +b: -1 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a = .a / 0 | .b = .b / 0\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: !!float +Inf +b: !!float -Inf +\f[R] +.fi +.SH Document Index +.PP +Use the \f[C]documentIndex\f[R] operator (or the \f[C]di\f[R] shorthand) +to select nodes of a particular document. +.SS Retrieve a document index +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +--- +a: frog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a | document_index\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +0 +--- +1 +\f[R] +.fi +.SS Retrieve a document index, shorthand +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +--- +a: frog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a | di\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +0 +--- +1 +\f[R] +.fi +.SS Filter by document index +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +--- +a: frog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]select(document_index == 1)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: frog +\f[R] +.fi +.SS Filter by document index shorthand +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +--- +a: frog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]select(di == 1)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: frog +\f[R] +.fi +.SS Print Document Index with matches +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +--- +a: frog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a | ({\[dq]match\[dq]: ., \[dq]doc\[dq]: document_index})\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +match: cat +doc: 0 +--- +match: frog +doc: 1 +\f[R] +.fi +.SH Encoder / Decoder +.PP +Encode operators will take the piped in object structure and encode it +as a string in the desired format. +The decode operators do the opposite, they take a formatted string and +decode it into the relevant object structure. +.PP +Note that you can optionally pass an indent value to the encode +functions (see below). +.PP +These operators are useful to process yaml documents that have +stringified embedded yaml/json/props in them. +.PP +.TS +tab(@); +l l l. +T{ +Format +T}@T{ +Decode (from string) +T}@T{ +Encode (to string) +T} +_ +T{ +Yaml +T}@T{ +from_yaml/\[at]yamld +T}@T{ +to_yaml(i)/\[at]yaml +T} +T{ +JSON +T}@T{ +from_json/\[at]jsond +T}@T{ +to_json(i)/\[at]json +T} +T{ +Properties +T}@T{ +from_props/\[at]propsd +T}@T{ +to_props/\[at]props +T} +T{ +CSV +T}@T{ +from_csv/\[at]csvd +T}@T{ +to_csv/\[at]csv +T} +T{ +TSV +T}@T{ +from_tsv/\[at]tsvd +T}@T{ +to_tsv/\[at]tsv +T} +T{ +XML +T}@T{ +from_xml/\[at]xmld +T}@T{ +to_xml(i)/\[at]xml +T} +T{ +Base64 +T}@T{ +\[at]base64d +T}@T{ +\[at]base64 +T} +T{ +URI +T}@T{ +\[at]urid +T}@T{ +\[at]uri +T} +T{ +Shell +T}@T{ +T}@T{ +\[at]sh +T} +.TE +.PP +See CSV and TSV +documentation (https://mikefarah.gitbook.io/yq/usage/csv-tsv) for +accepted formats. +.PP +XML uses the \f[C]--xml-attribute-prefix\f[R] and +\f[C]xml-content-name\f[R] flags to identify attributes and content +fields. +.PP +Base64 assumes rfc4648 (https://rfc-editor.org/rfc/rfc4648.html) +encoding. +Encoding and decoding both assume that the content is a utf-8 string and +not binary content. +.SS Encode value as json string +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + cool: thing +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].b = (.a | to_json)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + cool: thing +b: | + { + \[dq]cool\[dq]: \[dq]thing\[dq] + } +\f[R] +.fi +.SS Encode value as json string, on one line +.PP +Pass in a 0 indent to print json on a single line. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + cool: thing +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].b = (.a | to_json(0))\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + cool: thing +b: \[aq]{\[dq]cool\[dq]:\[dq]thing\[dq]}\[aq] +\f[R] +.fi +.SS Encode value as json string, on one line shorthand +.PP +Pass in a 0 indent to print json on a single line. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + cool: thing +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].b = (.a | \[at]json)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + cool: thing +b: \[aq]{\[dq]cool\[dq]:\[dq]thing\[dq]}\[aq] +\f[R] +.fi +.SS Decode a json encoded string +.PP +Keep in mind JSON is a subset of YAML. +If you want idiomatic yaml, pipe through the style operator to clear out +the JSON styling. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: \[aq]{\[dq]cool\[dq]:\[dq]thing\[dq]}\[aq] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a | from_json | ... style=\[dq]\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cool: thing +\f[R] +.fi +.SS Encode value as props string +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + cool: thing +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].b = (.a | \[at]props)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + cool: thing +b: | + cool = thing +\f[R] +.fi +.SS Decode props encoded string +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: |- + cats=great + dogs=cool as well +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a |= \[at]propsd\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + cats: great + dogs: cool as well +\f[R] +.fi +.SS Decode csv encoded string +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: |- + cats,dogs + great,cool as well +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a |= \[at]csvd\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + - cats: great + dogs: cool as well +\f[R] +.fi +.SS Decode tsv encoded string +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: |- + cats dogs + great cool as well +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a |= \[at]tsvd\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + - cats: great + dogs: cool as well +\f[R] +.fi +.SS Encode value as yaml string +.PP +Indent defaults to 2 +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + cool: + bob: dylan +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].b = (.a | to_yaml)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + cool: + bob: dylan +b: | + cool: + bob: dylan +\f[R] +.fi +.SS Encode value as yaml string, with custom indentation +.PP +You can specify the indentation level as the first parameter. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + cool: + bob: dylan +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].b = (.a | to_yaml(8))\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + cool: + bob: dylan +b: | + cool: + bob: dylan +\f[R] +.fi +.SS Decode a yaml encoded string +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: \[aq]foo: bar\[aq] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].b = (.a | from_yaml)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: \[aq]foo: bar\[aq] +b: + foo: bar +\f[R] +.fi +.SS Update a multiline encoded yaml string +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: | + foo: bar + baz: dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a |= (from_yaml | .foo = \[dq]cat\[dq] | to_yaml)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: | + foo: cat + baz: dog +\f[R] +.fi +.SS Update a single line encoded yaml string +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: \[aq]foo: bar\[aq] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a |= (from_yaml | .foo = \[dq]cat\[dq] | to_yaml)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: \[aq]foo: cat\[aq] +\f[R] +.fi +.SS Encode array of scalars as csv string +.PP +Scalars are strings, numbers and booleans. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- cat +- thing1,thing2 +- true +- 3.40 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]\[at]csv\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cat,\[dq]thing1,thing2\[dq],true,3.40 +\f[R] +.fi +.SS Encode array of arrays as csv string +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- - cat + - thing1,thing2 + - true + - 3.40 +- - dog + - thing3 + - false + - 12 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]\[at]csv\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cat,\[dq]thing1,thing2\[dq],true,3.40 +dog,thing3,false,12 +\f[R] +.fi +.SS Encode array of arrays as tsv string +.PP +Scalars are strings, numbers and booleans. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- - cat + - thing1,thing2 + - true + - 3.40 +- - dog + - thing3 + - false + - 12 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]\[at]tsv\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cat thing1,thing2 true 3.40 +dog thing3 false 12 +\f[R] +.fi +.SS Encode value as xml string +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + cool: + foo: bar + +\[at]id: hi +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a | to_xml\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] + + bar + +\f[R] +.fi +.SS Encode value as xml string on a single line +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + cool: + foo: bar + +\[at]id: hi +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a | \[at]xml\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +bar +\f[R] +.fi +.SS Encode value as xml string with custom indentation +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + cool: + foo: bar + +\[at]id: hi +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]{\[dq]cat\[dq]: .a | to_xml(1)}\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cat: | + + bar + +\f[R] +.fi +.SS Decode a xml encoded string +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: bar +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].b = (.a | from_xml)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: bar +b: + foo: bar +\f[R] +.fi +.SS Encode a string to base64 +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +coolData: a special string +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].coolData | \[at]base64\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +YSBzcGVjaWFsIHN0cmluZw== +\f[R] +.fi +.SS Encode a yaml document to base64 +.PP +Pipe through \[at]yaml first to convert to a string, then use +\[at]base64 to encode it. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: apple +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]\[at]yaml | \[at]base64\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +YTogYXBwbGUK +\f[R] +.fi +.SS Encode a string to uri +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +coolData: this has & special () characters * +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].coolData | \[at]uri\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +this+has+%26+special+%28%29+characters+%2A +\f[R] +.fi +.SS Decode a URI to a string +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +this+has+%26+special+%28%29+characters+%2A +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]\[at]urid\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +this has & special () characters * +\f[R] +.fi +.SS Encode a string to sh +.PP +Sh/Bash friendly string +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +coolData: strings with spaces and a \[aq]quote\[aq] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].coolData | \[at]sh\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +strings\[aq] with spaces and a \[aq]\[rs]\[aq]quote\[rs]\[aq] +\f[R] +.fi +.SS Decode a base64 encoded string +.PP +Decoded data is assumed to be a string. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +coolData: V29ya3Mgd2l0aCBVVEYtMTYg8J+Yig== +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].coolData | \[at]base64d\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +Works with UTF-16 \[u1F60A] +\f[R] +.fi +.SS Decode a base64 encoded yaml document +.PP +Pipe through \f[C]from_yaml\f[R] to parse the decoded base64 string as a +yaml document. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +coolData: YTogYXBwbGUK +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].coolData |= (\[at]base64d | from_yaml)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +coolData: + a: apple +\f[R] +.fi +.SH Entries +.PP +Similar to the same named functions in \f[C]jq\f[R] these functions +convert to/from an object and an array of key-value pairs. +This is most useful for performing operations on keys of maps. +.PP +Use \f[C]with_entries(op)\f[R] as a syntatic sugar for doing +\f[C]to_entries | op | from_entries\f[R]. +.SS to_entries Map +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 1 +b: 2 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]to_entries\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- key: a + value: 1 +- key: b + value: 2 +\f[R] +.fi +.SS to_entries Array +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- a +- b +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]to_entries\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- key: 0 + value: a +- key: 1 + value: b +\f[R] +.fi +.SS to_entries null +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +null +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]to_entries\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +\f[R] +.fi +.SS from_entries map +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 1 +b: 2 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]to_entries | from_entries\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: 1 +b: 2 +\f[R] +.fi +.SS from_entries with numeric key indices +.PP +from_entries always creates a map, even for numeric keys +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- a +- b +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]to_entries | from_entries\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +0: a +1: b +\f[R] +.fi +.SS Use with_entries to update keys +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 1 +b: 2 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]with_entries(.key |= \[dq]KEY_\[dq] + .)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +KEY_a: 1 +KEY_b: 2 +\f[R] +.fi +.SS Use with_entries to update keys recursively +.PP +We use (.. +| select(tag=\[lq]map\[rq])) to find all the maps in the doc, then |= to +update each one of those maps. +In the update, with_entries is used. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 1 +b: + b_a: nested + b_b: thing +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq](.. | select(tag==\[dq]!!map\[dq])) |= with_entries(.key |= \[dq]KEY_\[dq] + .)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +KEY_a: 1 +KEY_b: + KEY_b_a: nested + KEY_b_b: thing +\f[R] +.fi +.SS Custom sort map keys +.PP +Use to_entries to convert to an array of key/value pairs, sort the array +using sort/sort_by/etc, and convert it back. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 1 +c: 3 +b: 2 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]to_entries | sort_by(.key) | reverse | from_entries\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +c: 3 +b: 2 +a: 1 +\f[R] +.fi +.SS Use with_entries to filter the map +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + b: bird +c: + d: dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]with_entries(select(.value | has(\[dq]b\[dq])))\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: bird +\f[R] +.fi +.SH Env Variable Operators +.PP +These operators are used to handle environment variables usage in +expressions and documents. +While environment variables can, of course, be passed in via your CLI +with string interpolation, this often comes with complex quote escaping +and can be tricky to write and read. +.PP +There are three operators: +.IP \[bu] 2 +\f[C]env\f[R] which takes a single environment variable name and parse +the variable as a yaml node (be it a map, array, string, number of +boolean) +.IP \[bu] 2 +\f[C]strenv\f[R] which also takes a single environment variable name, +and always parses the variable as a string. +.IP \[bu] 2 +\f[C]envsubst\f[R] which you pipe strings into and it interpolates +environment variables in strings using +envsubst (https://github.com/a8m/envsubst). +.SS EnvSubst Options +.PP +You can optionally pass envsubst any of the following options: +.IP \[bu] 2 +nu: NoUnset, this will fail if there are any referenced variables that +are not set +.IP \[bu] 2 +ne: NoEmpty, this will fail if there are any referenced variables that +are empty +.IP \[bu] 2 +ff: FailFast, this will abort on the first failure (rather than collect +all the errors) +.PP +E.g: \f[C]envsubst(ne, ff)\f[R] will fail on the first empty variable. +.PP +See Imposing +Restrictions (https://github.com/a8m/envsubst#imposing-restrictions) in +the \f[C]envsubst\f[R] documentation for more information, and below for +examples. +.SS Tip +.PP +To replace environment variables across all values in a document, +\f[C]envsubst\f[R] can be used with the recursive descent operator as +follows: +.IP +.nf +\f[C] +yq \[aq](.. | select(tag == \[dq]!!str\[dq])) |= envsubst\[aq] file.yaml +\f[R] +.fi +.SS Read string environment variable +.PP +Running +.IP +.nf +\f[C] +myenv=\[dq]cat meow\[dq] yq --null-input \[aq].a = env(myenv)\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: cat meow +\f[R] +.fi +.SS Read boolean environment variable +.PP +Running +.IP +.nf +\f[C] +myenv=\[dq]true\[dq] yq --null-input \[aq].a = env(myenv)\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: true +\f[R] +.fi +.SS Read numeric environment variable +.PP +Running +.IP +.nf +\f[C] +myenv=\[dq]12\[dq] yq --null-input \[aq].a = env(myenv)\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: 12 +\f[R] +.fi +.SS Read yaml environment variable +.PP +Running +.IP +.nf +\f[C] +myenv=\[dq]{b: fish}\[dq] yq --null-input \[aq].a = env(myenv)\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: {b: fish} +\f[R] +.fi +.SS Read boolean environment variable as a string +.PP +Running +.IP +.nf +\f[C] +myenv=\[dq]true\[dq] yq --null-input \[aq].a = strenv(myenv)\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: \[dq]true\[dq] +\f[R] +.fi +.SS Read numeric environment variable as a string +.PP +Running +.IP +.nf +\f[C] +myenv=\[dq]12\[dq] yq --null-input \[aq].a = strenv(myenv)\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: \[dq]12\[dq] +\f[R] +.fi +.SS Dynamically update a path from an environment variable +.PP +The env variable can be any valid yq expression. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + b: + - name: dog + - name: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +pathEnv=\[dq].a.b[0].name\[dq] valueEnv=\[dq]moo\[dq] yq \[aq]eval(strenv(pathEnv)) = strenv(valueEnv)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: + - name: moo + - name: cat +\f[R] +.fi +.SS Dynamic key lookup with environment variable +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +cat: meow +dog: woof +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +myenv=\[dq]cat\[dq] yq \[aq].[env(myenv)]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +meow +\f[R] +.fi +.SS Replace strings with envsubst +.PP +Running +.IP +.nf +\f[C] +myenv=\[dq]cat\[dq] yq --null-input \[aq]\[dq]the ${myenv} meows\[dq] | envsubst\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +the cat meows +\f[R] +.fi +.SS Replace strings with envsubst, missing variables +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]\[dq]the ${myenvnonexisting} meows\[dq] | envsubst\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +the meows +\f[R] +.fi +.SS Replace strings with envsubst(nu), missing variables +.PP +(nu) not unset, will fail if there are unset (missing) variables +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]\[dq]the ${myenvnonexisting} meows\[dq] | envsubst(nu)\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +Error: variable ${myenvnonexisting} not set +\f[R] +.fi +.SS Replace strings with envsubst(ne), missing variables +.PP +(ne) not empty, only validates set variables +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]\[dq]the ${myenvnonexisting} meows\[dq] | envsubst(ne)\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +the meows +\f[R] +.fi +.SS Replace strings with envsubst(ne), empty variable +.PP +(ne) not empty, will fail if a references variable is empty +.PP +Running +.IP +.nf +\f[C] +myenv=\[dq]\[dq] yq --null-input \[aq]\[dq]the ${myenv} meows\[dq] | envsubst(ne)\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +Error: variable ${myenv} set but empty +\f[R] +.fi +.SS Replace strings with envsubst, missing variables with defaults +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]\[dq]the ${myenvnonexisting-dog} meows\[dq] | envsubst\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +the dog meows +\f[R] +.fi +.SS Replace strings with envsubst(nu), missing variables with defaults +.PP +Having a default specified skips over the missing variable. +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]\[dq]the ${myenvnonexisting-dog} meows\[dq] | envsubst(nu)\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +the dog meows +\f[R] +.fi +.SS Replace strings with envsubst(ne), missing variables with defaults +.PP +Fails, because the variable is explicitly set to blank. +.PP +Running +.IP +.nf +\f[C] +myEmptyEnv=\[dq]\[dq] yq --null-input \[aq]\[dq]the ${myEmptyEnv-dog} meows\[dq] | envsubst(ne)\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +Error: variable ${myEmptyEnv} set but empty +\f[R] +.fi +.SS Replace string environment variable in document +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +v: ${myenv} +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +myenv=\[dq]cat meow\[dq] yq \[aq].v |= envsubst\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +v: cat meow +\f[R] +.fi +.SS (Default) Return all envsubst errors +.PP +By default, all errors are returned at once. +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]\[dq]the ${notThere} ${alsoNotThere}\[dq] | envsubst(nu)\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +Error: variable ${notThere} not set +variable ${alsoNotThere} not set +\f[R] +.fi +.SS Fail fast, return the first envsubst error (and abort) +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]\[dq]the ${notThere} ${alsoNotThere}\[dq] | envsubst(nu,ff)\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +Error: variable ${notThere} not set +\f[R] +.fi +.SH Equals / Not Equals +.PP +This is a boolean operator that will return \f[C]true\f[R] if the LHS is +equal to the RHS and \f[C]false\f[R] otherwise. +.IP +.nf +\f[C] +\&.a == .b +\f[R] +.fi +.PP +It is most often used with the select operator to find particular nodes: +.IP +.nf +\f[C] +select(.a == .b) +\f[R] +.fi +.PP +The not equals \f[C]!=\f[R] operator returns \f[C]false\f[R] if the LHS +is equal to the RHS. +.SS Related Operators +.IP \[bu] 2 +comparison (\f[C]>=\f[R], \f[C]<\f[R] etc) operators +here (https://mikefarah.gitbook.io/yq/operators/compare) +.IP \[bu] 2 +boolean operators (\f[C]and\f[R], \f[C]or\f[R], \f[C]any\f[R] etc) +here (https://mikefarah.gitbook.io/yq/operators/boolean-operators) +.IP \[bu] 2 +select operator here (https://mikefarah.gitbook.io/yq/operators/select) +.SS Match string +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- cat +- goat +- dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] | (. == \[dq]*at\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +true +true +false +\f[R] +.fi +.SS Don\[cq]t match string +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- cat +- goat +- dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] | (. != \[dq]*at\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +false +false +true +\f[R] +.fi +.SS Match number +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- 3 +- 4 +- 5 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] | (. == 4)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +false +true +false +\f[R] +.fi +.SS Don\[cq]t match number +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- 3 +- 4 +- 5 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] | (. != 4)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +true +false +true +\f[R] +.fi +.SS Match nulls +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]null == \[ti]\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +true +\f[R] +.fi +.SS Non existent key doesn\[cq]t equal a value +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: frog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]select(.b != \[dq]thing\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: frog +\f[R] +.fi +.SS Two non existent keys are equal +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: frog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]select(.b == .c)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: frog +\f[R] +.fi +.SH Error +.PP +Use this operation to short-circuit expressions. +Useful for validation. +.SS Validate a particular value +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: hello +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]select(.a == \[dq]howdy\[dq]) or error(\[dq].a [\[dq] + .a + \[dq]] is not howdy!\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +Error: .a [hello] is not howdy! +\f[R] +.fi +.SS Validate the environment variable is a number - invalid +.PP +Running +.IP +.nf +\f[C] +numberOfCats=\[dq]please\[dq] yq --null-input \[aq]env(numberOfCats) | select(tag == \[dq]!!int\[dq]) or error(\[dq]numberOfCats is not a number :(\[dq])\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +Error: numberOfCats is not a number :( +\f[R] +.fi +.SS Validate the environment variable is a number - valid +.PP +\f[C]with\f[R] can be a convenient way of encapsulating validation. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +name: Bob +favouriteAnimal: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +numberOfCats=\[dq]3\[dq] yq \[aq] + with(env(numberOfCats); select(tag == \[dq]!!int\[dq]) or error(\[dq]numberOfCats is not a number :(\[dq])) | + .numPets = env(numberOfCats) +\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +name: Bob +favouriteAnimal: cat +numPets: 3 +\f[R] +.fi +.SH Eval +.PP +Use \f[C]eval\f[R] to dynamically process an expression - for instance +from an environment variable. +.PP +\f[C]eval\f[R] takes a single argument, and evaluates that as a +\f[C]yq\f[R] expression. +Any valid expression can be used, be it a path +\f[C].a.b.c | select(. == \[dq]cat\[dq])\f[R], or an update +\f[C].a.b.c = \[dq]gogo\[dq]\f[R]. +.PP +Tip: This can be a useful way to parameterise complex scripts. +.SS Dynamically evaluate a path +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +pathExp: .a.b[] | select(.name == \[dq]cat\[dq]) +a: + b: + - name: dog + - name: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]eval(.pathExp)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +name: cat +\f[R] +.fi +.SS Dynamically update a path from an environment variable +.PP +The env variable can be any valid yq expression. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + b: + - name: dog + - name: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +pathEnv=\[dq].a.b[0].name\[dq] valueEnv=\[dq]moo\[dq] yq \[aq]eval(strenv(pathEnv)) = strenv(valueEnv)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: + - name: moo + - name: cat +\f[R] +.fi +.SH File Operators +.PP +File operators are most often used with merge when needing to merge +specific files together. +Note that when doing this, you will need to use \f[C]eval-all\f[R] to +ensure all yaml documents are loaded into memory before performing the +merge (as opposed to \f[C]eval\f[R] which runs the expression once per +document). +.PP +Note that the \f[C]fileIndex\f[R] operator has a short alias of +\f[C]fi\f[R]. +.SS Merging files +.PP +Note the use of eval-all to ensure all documents are loaded into memory. +.IP +.nf +\f[C] +yq eval-all \[aq]select(fi == 0) * select(filename == \[dq]file2.yaml\[dq])\[aq] file1.yaml file2.yaml +\f[R] +.fi +.SS Get filename +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]filename\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +sample.yml +\f[R] +.fi +.SS Get file index +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]file_index\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +0 +\f[R] +.fi +.SS Get file indices of multiple documents +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +\f[R] +.fi +.PP +And another sample another.yml file of: +.IP +.nf +\f[C] +a: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq eval-all \[aq]file_index\[aq] sample.yml another.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +0 +1 +\f[R] +.fi +.SS Get file index alias +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]fi\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +0 +\f[R] +.fi +.SH Filter +.PP +Filters an array (or map values) by the expression given. +Equivalent to doing \f[C]map(select(exp))\f[R]. +.SS Filter array +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- 1 +- 2 +- 3 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]filter(. < 3)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- 1 +- 2 +\f[R] +.fi +.SS Filter map values +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +c: + things: cool + frog: yes +d: + things: hot + frog: false +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]filter(.things == \[dq]cool\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- things: cool + frog: yes +\f[R] +.fi +.SH Flatten +.PP +This recursively flattens arrays. +.SS Flatten +.PP +Recursively flattens all arrays +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- 1 +- - 2 +- - - 3 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]flatten\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- 1 +- 2 +- 3 +\f[R] +.fi +.SS Flatten with depth of one +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- 1 +- - 2 +- - - 3 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]flatten(1)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- 1 +- 2 +- - 3 +\f[R] +.fi +.SS Flatten empty array +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- [] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]flatten\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +[] +\f[R] +.fi +.SS Flatten array of objects +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- foo: bar +- - foo: baz +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]flatten\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- foo: bar +- foo: baz +\f[R] +.fi +.SH Group By +.PP +This is used to group items in an array by an expression. +.SS Group by field +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- foo: 1 + bar: 10 +- foo: 3 + bar: 100 +- foo: 1 + bar: 1 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]group_by(.foo)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- - foo: 1 + bar: 10 + - foo: 1 + bar: 1 +- - foo: 3 + bar: 100 +\f[R] +.fi +.SS Group by field, with nulls +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- cat: dog +- foo: 1 + bar: 10 +- foo: 3 + bar: 100 +- no: foo for you +- foo: 1 + bar: 1 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]group_by(.foo)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- - cat: dog + - no: foo for you +- - foo: 1 + bar: 10 + - foo: 1 + bar: 1 +- - foo: 3 + bar: 100 +\f[R] +.fi +.SH Has +.PP +This operation returns true if the key exists in a map (or index in an +array), false otherwise. +.SS Has map key +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- a: yes +- a: \[ti] +- a: +- b: nope +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] | has(\[dq]a\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +true +true +true +false +\f[R] +.fi +.SS Select, checking for existence of deep paths +.PP +Simply pipe in parent expressions into \f[C]has\f[R] +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- a: + b: + c: cat +- a: + b: + d: dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] | select(.a.b | has(\[dq]c\[dq]))\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: + c: cat +\f[R] +.fi +.SS Has array index +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- [] +- [1] +- [1, 2] +- [1, null] +- [1, 2, 3] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] | has(1)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +false +false +true +true +true +\f[R] +.fi +.SH Keys +.PP +Use the \f[C]keys\f[R] operator to return map keys or array indices. +.SS Map keys +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +dog: woof +cat: meow +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]keys\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- dog +- cat +\f[R] +.fi +.SS Array keys +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- apple +- banana +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]keys\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- 0 +- 1 +\f[R] +.fi +.SS Retrieve array key +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- 1 +- 2 +- 3 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[1] | key\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +1 +\f[R] +.fi +.SS Retrieve map key +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: thing +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a | key\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a +\f[R] +.fi +.SS No key +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +{} +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]key\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +\f[R] +.fi +.SS Update map key +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + x: 3 + y: 4 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq](.a.x | key) = \[dq]meow\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + meow: 3 + y: 4 +\f[R] +.fi +.SS Get comment from map key +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + # comment on key + x: 3 + y: 4 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a.x | key | headComment\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +comment on key +\f[R] +.fi +.SS Check node is a key +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + b: + - cat + c: frog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq][... | { \[dq]p\[dq]: path | join(\[dq].\[dq]), \[dq]isKey\[dq]: is_key, \[dq]tag\[dq]: tag }]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- p: \[dq]\[dq] + isKey: false + tag: \[aq]!!map\[aq] +- p: a + isKey: true + tag: \[aq]!!str\[aq] +- p: a + isKey: false + tag: \[aq]!!map\[aq] +- p: a.b + isKey: true + tag: \[aq]!!str\[aq] +- p: a.b + isKey: false + tag: \[aq]!!seq\[aq] +- p: a.b.0 + isKey: false + tag: \[aq]!!str\[aq] +- p: a.c + isKey: true + tag: \[aq]!!str\[aq] +- p: a.c + isKey: false + tag: \[aq]!!str\[aq] +\f[R] +.fi +.SH Kind +.PP +The \f[C]kind\f[R] operator identifies the type of a node as either +\f[C]scalar\f[R], \f[C]map\f[R], or \f[C]seq\f[R]. +.PP +This can be used for filtering or transforming nodes based on their +type. +.PP +Note that \f[C]null\f[R] values are treated as \f[C]scalar\f[R]. +.SS Get kind +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +b: 5 +c: 3.2 +e: true +f: [] +g: {} +h: null +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].. | kind\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +map +scalar +scalar +scalar +scalar +seq +map +scalar +\f[R] +.fi +.SS Get kind, ignores custom tags +.PP +Unlike tag, kind is not affected by custom tags. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: !!thing cat +b: !!foo {} +c: !!bar [] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].. | kind\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +map +scalar +map +seq +\f[R] +.fi +.SS Add comments only to scalars +.PP +An example of how you can use kind +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + b: 5 + c: 3.2 +e: true +f: [] +g: {} +h: null +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq](.. | select(kind == \[dq]scalar\[dq])) line_comment = \[dq]this is a scalar\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: 5 # this is a scalar + c: 3.2 # this is a scalar +e: true # this is a scalar +f: [] +g: {} +h: null # this is a scalar +\f[R] +.fi +.SH Length +.PP +Returns the lengths of the nodes. +Length is defined according to the type of the node. +.SS String length +.PP +returns length of string +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a | length\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +3 +\f[R] +.fi +.SS null length +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: null +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a | length\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +0 +\f[R] +.fi +.SS Map length +.PP +returns number of entries +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +c: dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]length\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +2 +\f[R] +.fi +.SS Array length +.PP +returns number of elements +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- 2 +- 4 +- 6 +- 8 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]length\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +4 +\f[R] +.fi +.SH Line +.PP +Returns the line of the matching node. +Starts from 1, 0 indicates there was no line data. +.SS Returns line of \f[I]value\f[R] node +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +b: + c: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].b | line\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +3 +\f[R] +.fi +.SS Returns line of \f[I]key\f[R] node +.PP +Pipe through the key operator to get the line of the key +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +b: + c: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].b | key | line\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +2 +\f[R] +.fi +.SS First line is 1 +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a | line\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +1 +\f[R] +.fi +.SS No line data is 0 +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]{\[dq]a\[dq]: \[dq]new entry\[dq]} | line\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +0 +\f[R] +.fi +.SH Load +.PP +The load operators allows you to load in content from another file. +.PP +Note that you can use string operators like \f[C]+\f[R] and +\f[C]sub\f[R] to modify the value in the yaml file to a path that exists +in your system. +.PP +You can load files of the following supported types: +.PP +.TS +tab(@); +l l. +T{ +Format +T}@T{ +Load Operator +T} +_ +T{ +Yaml +T}@T{ +load +T} +T{ +XML +T}@T{ +load_xml +T} +T{ +Properties +T}@T{ +load_props +T} +T{ +Plain String +T}@T{ +load_str +T} +T{ +Base64 +T}@T{ +load_base64 +T} +.TE +.PP +Note that load_base64 only works for base64 encoded utf-8 strings. +.SS Samples files for tests: +.SS yaml +.PP +\f[C]../../examples/thing.yml\f[R]: +.IP +.nf +\f[C] +a: apple is included +b: cool +\f[R] +.fi +.SS xml +.PP +\f[C]small.xml\f[R]: +.IP +.nf +\f[C] +is some xml +\f[R] +.fi +.SS properties +.PP +\f[C]small.properties\f[R]: +.IP +.nf +\f[C] +this.is = a properties file +\f[R] +.fi +.SS base64 +.PP +\f[C]base64.txt\f[R]: +.IP +.nf +\f[C] +bXkgc2VjcmV0IGNoaWxsaSByZWNpcGUgaXMuLi4u +\f[R] +.fi +.SS Simple example +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +myFile: ../../examples/thing.yml +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]load(.myFile)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: apple is included +b: cool. +\f[R] +.fi +.SS Replace node with referenced file +.PP +Note that you can modify the filename in the load operator if needed. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +something: + file: thing.yml +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].something |= load(\[dq]../../examples/\[dq] + .file)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +something: + a: apple is included + b: cool. +\f[R] +.fi +.SS Replace \f[I]all\f[R] nodes with referenced file +.PP +Recursively match all the nodes (\f[C]..\f[R]) and then filter the ones +that have a `file' attribute. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +something: + file: thing.yml +over: + here: + - file: thing.yml +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq](.. | select(has(\[dq]file\[dq]))) |= load(\[dq]../../examples/\[dq] + .file)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +something: + a: apple is included + b: cool. +over: + here: + - a: apple is included + b: cool. +\f[R] +.fi +.SS Replace node with referenced file as string +.PP +This will work for any text based file +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +something: + file: thing.yml +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].something |= load_str(\[dq]../../examples/\[dq] + .file)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +something: |- + a: apple is included + b: cool. +\f[R] +.fi +.SS Load from XML +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +cool: things +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].more_stuff = load_xml(\[dq]../../examples/small.xml\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cool: things +more_stuff: + this: is some xml +\f[R] +.fi +.SS Load from Properties +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +cool: things +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].more_stuff = load_props(\[dq]../../examples/small.properties\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cool: things +more_stuff: + this: + is: a properties file +\f[R] +.fi +.SS Merge from properties +.PP +This can be used as a convenient way to update a yaml document +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +this: + is: from yaml + cool: ay +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]. *= load_props(\[dq]../../examples/small.properties\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +this: + is: a properties file + cool: ay +\f[R] +.fi +.SS Load from base64 encoded file +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +cool: things +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].more_stuff = load_base64(\[dq]../../examples/base64.txt\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cool: things +more_stuff: my secret chilli recipe is.... +\f[R] +.fi +.SH Map +.PP +Maps values of an array. +Use \f[C]map_values\f[R] to map values of an object. +.SS Map array +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- 1 +- 2 +- 3 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]map(. + 1)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- 2 +- 3 +- 4 +\f[R] +.fi +.SS Map object values +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 1 +b: 2 +c: 3 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]map_values(. + 1)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: 2 +b: 3 +c: 4 +\f[R] +.fi +.SH Max +.PP +Computes the maximum among an incoming sequence of scalar values. +.SS Maximum int +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- 99 +- 16 +- 12 +- 6 +- 66 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]max\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +99 +\f[R] +.fi +.SS Maximum string +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- foo +- bar +- baz +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]max\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +foo +\f[R] +.fi +.SS Maximum of empty +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +[] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]max\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +\f[R] +.fi +.SH Min +.PP +Computes the minimum among an incoming sequence of scalar values. +.SS Minimum int +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- 99 +- 16 +- 12 +- 6 +- 66 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]min\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +6 +\f[R] +.fi +.SS Minimum string +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- foo +- bar +- baz +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]min\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +bar +\f[R] +.fi +.SS Minimum of empty +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +[] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]min\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +\f[R] +.fi +.SH Modulo +.PP +Arithmetic modulo operator, returns the remainder from dividing two +numbers. +.SS Number modulo - int +.PP +If the lhs and rhs are ints then the expression will be calculated with +ints. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 13 +b: 2 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a = .a % .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: 1 +b: 2 +\f[R] +.fi +.SS Number modulo - float +.PP +If the lhs or rhs are floats then the expression will be calculated with +floats. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 12 +b: 2.5 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a = .a % .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: !!float 2 +b: 2.5 +\f[R] +.fi +.SS Number modulo - int by zero +.PP +If the lhs is an int and rhs is a 0 the result is an error. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 1 +b: 0 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a = .a % .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +Error: cannot modulo by 0 +\f[R] +.fi +.SS Number modulo - float by zero +.PP +If the lhs is a float and rhs is a 0 the result is NaN. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 1.1 +b: 0 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a = .a % .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: !!float NaN +b: 0 +\f[R] +.fi +.SH Multiply (Merge) +.PP +Like the multiple operator in jq, depending on the operands, this +multiply operator will do different things. +Currently numbers, arrays and objects are supported. +.SS Objects and arrays - merging +.PP +Objects are merged \f[I]deeply\f[R] matching on matching keys. +By default, array values override and are not deeply merged. +.PP +You can use the add operator \f[C]+\f[R], to shallow merge objects, see +more info here (https://mikefarah.gitbook.io/yq/operators/add). +.PP +Note that when merging objects, this operator returns the merged object +(not the parent). +This will be clearer in the examples below. +.SS Merge Flags +.PP +You can control how objects are merged by using one or more of the +following flags. +Multiple flags can be used together, e.g.\ \f[C].a *+? .b\f[R]. +See examples below +.IP \[bu] 2 +\f[C]+\f[R] append arrays +.IP \[bu] 2 +\f[C]d\f[R] deeply merge arrays +.IP \[bu] 2 +\f[C]?\f[R] only merge \f[I]existing\f[R] fields +.IP \[bu] 2 +\f[C]n\f[R] only merge \f[I]new\f[R] fields +.IP \[bu] 2 +\f[C]c\f[R] clobber custom tags +.PP +To perform a shallow merge only, use the add operator \f[C]+\f[R], see +more info here (https://mikefarah.gitbook.io/yq/operators/add). +.SS Merge two files together +.PP +This uses the load operator to merge file2 into file1. +.IP +.nf +\f[C] +yq \[aq]. *= load(\[dq]file2.yml\[dq])\[aq] file1.yml +\f[R] +.fi +.SS Merging all files +.PP +Note the use of \f[C]eval-all\f[R] to ensure all documents are loaded +into memory. +.IP +.nf +\f[C] +yq eval-all \[aq]. as $item ireduce ({}; . * $item )\[aq] *.yml +\f[R] +.fi +.SH Merging complex arrays together by a key field +.PP +By default - \f[C]yq\f[R] merge is naive. +It merges maps when they match the key name, and arrays are merged +either by appending them together, or merging the entries by their +position in the array. +.PP +For more complex array merging (e.g.\ merging items that match on a +certain key) please see the example +here (https://mikefarah.gitbook.io/yq/operators/multiply-merge#merge-arrays-of-objects-together-matching-on-a-key) +.SS Multiply integers +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 3 +b: 4 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a *= .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: 12 +b: 4 +\f[R] +.fi +.SS Multiply string node X int +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +b: banana +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].b * 4\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +bananabananabananabanana +\f[R] +.fi +.SS Multiply int X string node +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +b: banana +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]4 * .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +bananabananabananabanana +\f[R] +.fi +.SS Multiply string X int node +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +n: 4 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]\[dq]banana\[dq] * .n\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +bananabananabananabanana +\f[R] +.fi +.SS Multiply int node X string +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +n: 4 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].n * \[dq]banana\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +bananabananabananabanana +\f[R] +.fi +.SS Merge objects together, returning merged result only +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + field: me + fieldA: cat +b: + field: + g: wizz + fieldB: dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a * .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +field: + g: wizz +fieldA: cat +fieldB: dog +\f[R] +.fi +.SS Merge objects together, returning parent object +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + field: me + fieldA: cat +b: + field: + g: wizz + fieldB: dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]. * {\[dq]a\[dq]:.b}\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + field: + g: wizz + fieldA: cat + fieldB: dog +b: + field: + g: wizz + fieldB: dog +\f[R] +.fi +.SS Merge keeps style of LHS +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: {things: great} +b: + also: \[dq]me\[dq] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]. * {\[dq]a\[dq]:.b}\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: {things: great, also: \[dq]me\[dq]} +b: + also: \[dq]me\[dq] +\f[R] +.fi +.SS Merge arrays +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + - 1 + - 2 + - 3 +b: + - 3 + - 4 + - 5 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]. * {\[dq]a\[dq]:.b}\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + - 3 + - 4 + - 5 +b: + - 3 + - 4 + - 5 +\f[R] +.fi +.SS Merge, only existing fields +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + thing: one + cat: frog +b: + missing: two + thing: two +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a *? .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +thing: two +cat: frog +\f[R] +.fi +.SS Merge, only new fields +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + thing: one + cat: frog +b: + missing: two + thing: two +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a *n .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +thing: one +cat: frog +missing: two +\f[R] +.fi +.SS Merge, appending arrays +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + array: + - 1 + - 2 + - animal: dog + value: coconut +b: + array: + - 3 + - 4 + - animal: cat + value: banana +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a *+ .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +array: + - 1 + - 2 + - animal: dog + - 3 + - 4 + - animal: cat +value: banana +\f[R] +.fi +.SS Merge, only existing fields, appending arrays +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + thing: + - 1 + - 2 +b: + thing: + - 3 + - 4 + another: + - 1 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a *?+ .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +thing: + - 1 + - 2 + - 3 + - 4 +\f[R] +.fi +.SS Merge, deeply merging arrays +.PP +Merging arrays deeply means arrays are merged like objects, with indices +as their key. +In this case, we merge the first item in the array and do nothing with +the second. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + - name: fred + age: 12 + - name: bob + age: 32 +b: + - name: fred + age: 34 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a *d .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- name: fred + age: 34 +- name: bob + age: 32 +\f[R] +.fi +.SS Merge arrays of objects together, matching on a key +.PP +This is a fairly complex expression - you can use it as is by providing +the environment variables as seen in the example below. +.PP +It merges in the array provided in the second file into the first - +matching on equal keys. +.PP +Explanation: +.PP +The approach, at a high level, is to reduce into a merged map (keyed by +the unique key) and then convert that back into an array. +.PP +First the expression will create a map from the arrays keyed by the +idPath, the unique field we want to merge by. +The reduce operator is merging `({}; . * $item )', so array elements +with the matching key will be merged together. +.PP +Next, we convert the map back to an array, using reduce again, +concatenating all the map values together. +.PP +Finally, we set the result of the merged array back into the first doc. +.PP +Thanks Kev from +stackoverflow (https://stackoverflow.com/a/70109529/1168223) +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +myArray: + - a: apple + b: appleB + - a: kiwi + b: kiwiB + - a: banana + b: bananaB +something: else +\f[R] +.fi +.PP +And another sample another.yml file of: +.IP +.nf +\f[C] +newArray: + - a: banana + c: bananaC + - a: apple + b: appleB2 + - a: dingo + c: dingoC +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +idPath=\[dq].a\[dq] originalPath=\[dq].myArray\[dq] otherPath=\[dq].newArray\[dq] yq eval-all \[aq] +( + (( (eval(strenv(originalPath)) + eval(strenv(otherPath))) | .[] | {(eval(strenv(idPath))): .}) as $item ireduce ({}; . * $item )) as $uniqueMap + | ( $uniqueMap | to_entries | .[]) as $item ireduce([]; . + $item.value) +) as $mergedArray +| select(fi == 0) | (eval(strenv(originalPath))) = $mergedArray +\[aq] sample.yml another.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +myArray: + - a: apple + b: appleB2 + - a: kiwi + b: kiwiB + - a: banana + b: bananaB + c: bananaC + - a: dingo + c: dingoC +something: else +\f[R] +.fi +.SS Merge to prefix an element +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +b: dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]. * {\[dq]a\[dq]: {\[dq]c\[dq]: .a}}\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + c: cat +b: dog +\f[R] +.fi +.SS Merge with simple aliases +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: &cat + c: frog +b: + f: *cat +c: + g: thongs +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].c * .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +g: thongs +f: *cat +\f[R] +.fi +.SS Merge copies anchor names +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + c: &cat frog +b: + f: *cat +c: + g: thongs +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].c * .a\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +g: thongs +c: &cat frog +\f[R] +.fi +.SS Merge with merge anchors +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +foo: &foo + a: foo_a + thing: foo_thing + c: foo_c +bar: &bar + b: bar_b + thing: bar_thing + c: bar_c +foobarList: + b: foobarList_b + !!merge <<: + - *foo + - *bar + c: foobarList_c +foobar: + c: foobar_c + !!merge <<: *foo + thing: foobar_thing +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].foobar * .foobarList\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +c: foobarList_c +!!merge <<: + - *foo + - *bar +thing: foobar_thing +b: foobarList_b +\f[R] +.fi +.SS Custom types: that are really numbers +.PP +When custom tags are encountered, yq will try to decode the underlying +type. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: !horse 2 +b: !goat 3 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a = .a * .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: !horse 6 +b: !goat 3 +\f[R] +.fi +.SS Custom types: that are really maps +.PP +Custom tags will be maintained. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: !horse + cat: meow +b: !goat + dog: woof +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a = .a * .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: !horse + cat: meow + dog: woof +b: !goat + dog: woof +\f[R] +.fi +.SS Custom types: clobber tags +.PP +Use the \f[C]c\f[R] option to clobber custom tags. +Note that the second tag is now used. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: !horse + cat: meow +b: !goat + dog: woof +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a *=c .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: !goat + cat: meow + dog: woof +b: !goat + dog: woof +\f[R] +.fi +.SS Merging a null with a map +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]null * {\[dq]some\[dq]: \[dq]thing\[dq]}\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +some: thing +\f[R] +.fi +.SS Merging a map with null +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]{\[dq]some\[dq]: \[dq]thing\[dq]} * null\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +some: thing +\f[R] +.fi +.SS Merging a null with an array +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]null * [\[dq]some\[dq]]\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- some +\f[R] +.fi +.SS Merging an array with null +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq][\[dq]some\[dq]] * null\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- some +\f[R] +.fi +.SH Omit +.PP +Works like \f[C]pick\f[R], but instead you specify the keys/indices that +you \f[I]don\[cq]t\f[R] want included. +.SS Omit keys from map +.PP +Note that non existent keys are skipped. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +myMap: + cat: meow + dog: bark + thing: hamster + hamster: squeak +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].myMap |= omit([\[dq]hamster\[dq], \[dq]cat\[dq], \[dq]goat\[dq]])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +myMap: + dog: bark + thing: hamster +\f[R] +.fi +.SS Omit indices from array +.PP +Note that non existent indices are skipped. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- cat +- leopard +- lion +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]omit([2, 0, 734, -5])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- leopard +\f[R] +.fi +.SH Parent +.PP +Parent simply returns the parent nodes of the matching nodes. +.SS Simple example +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + nested: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a.nested | parent\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +nested: cat +\f[R] +.fi +.SS Parent of nested matches +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + fruit: apple + name: bob +b: + fruit: banana + name: sam +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].. | select(. == \[dq]banana\[dq]) | parent\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +fruit: banana +name: sam +\f[R] +.fi +.SS Get parent attribute +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + fruit: apple + name: bob +b: + fruit: banana + name: sam +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].. | select(. == \[dq]banana\[dq]) | parent.name\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +sam +\f[R] +.fi +.SS N-th parent +.PP +You can optionally supply the number of levels to go up for the parent, +the default being 1. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + b: + c: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a.b.c | parent(2)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +b: + c: cat +\f[R] +.fi +.SS N-th parent - another level +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + b: + c: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a.b.c | parent(3)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: + c: cat +\f[R] +.fi +.SS No parent +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +{} +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]parent\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +\f[R] +.fi +.SH Path +.PP +The \f[C]path\f[R] operator can be used to get the traversal paths of +matching nodes in an expression. +The path is returned as an array, which if traversed in order will lead +to the matching node. +.PP +You can get the key/index of matching nodes by using the \f[C]path\f[R] +operator to return the path array then piping that through +\f[C].[-1]\f[R] to get the last element of that array, the key. +.PP +Use \f[C]setpath\f[R] to set a value to the path array returned by +\f[C]path\f[R], and similarly \f[C]delpaths\f[R] for an array of path +arrays. +.SS Map path +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + b: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a.b | path\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- a +- b +\f[R] +.fi +.SS Get map key +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + b: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a.b | path | .[-1]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +b +\f[R] +.fi +.SS Array path +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + - cat + - dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a.[] | select(. == \[dq]dog\[dq]) | path\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- a +- 1 +\f[R] +.fi +.SS Get array index +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + - cat + - dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a.[] | select(. == \[dq]dog\[dq]) | path | .[-1]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +1 +\f[R] +.fi +.SS Print path and value +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + - cat + - dog + - frog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a[] | select(. == \[dq]*og\[dq]) | [{\[dq]path\[dq]:path, \[dq]value\[dq]:.}]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- path: + - a + - 1 + value: dog +- path: + - a + - 2 + value: frog +\f[R] +.fi +.SS Set path +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + b: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]setpath([\[dq]a\[dq], \[dq]b\[dq]]; \[dq]things\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: things +\f[R] +.fi +.SS Set on empty document +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]setpath([\[dq]a\[dq], \[dq]b\[dq]]; \[dq]things\[dq])\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: things +\f[R] +.fi +.SS Set path to prune deep paths +.PP +Like pick but recursive. +This uses \f[C]ireduce\f[R] to deeply set the selected paths into an +empty object. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +parentA: bob +parentB: + child1: i am child1 + child2: i am child2 +parentC: + child1: me child1 + child2: me child2 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq](.parentB.child2, .parentC.child1) as $i + ireduce({}; setpath($i | path; $i))\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +parentB: + child2: i am child2 +parentC: + child1: me child1 +\f[R] +.fi +.SS Set array path +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + - cat + - frog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]setpath([\[dq]a\[dq], 0]; \[dq]things\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + - things + - frog +\f[R] +.fi +.SS Set array path empty +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]setpath([\[dq]a\[dq], 0]; \[dq]things\[dq])\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + - things +\f[R] +.fi +.SS Delete path +.PP +Notice delpaths takes an \f[I]array\f[R] of paths. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + b: cat + c: dog + d: frog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]delpaths([[\[dq]a\[dq], \[dq]c\[dq]], [\[dq]a\[dq], \[dq]d\[dq]]])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: cat +\f[R] +.fi +.SS Delete array path +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + - cat + - frog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]delpaths([[\[dq]a\[dq], 0]])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + - frog +\f[R] +.fi +.SS Delete - wrong parameter +.PP +delpaths does not work with a single path array +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + - cat + - frog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]delpaths([\[dq]a\[dq], 0])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +Error: DELPATHS: expected entry [0] to be a sequence, but its a !!str. Note that delpaths takes an array of path arrays, e.g. [[\[dq]a\[dq], \[dq]b\[dq]]] +\f[R] +.fi +.SH Pick +.PP +Filter a map by the specified list of keys. +Map is returned with the key in the order of the pick list. +.PP +Similarly, filter an array by the specified list of indices. +.SS Pick keys from map +.PP +Note that the order of the keys matches the pick order and non existent +keys are skipped. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +myMap: + cat: meow + dog: bark + thing: hamster + hamster: squeak +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].myMap |= pick([\[dq]hamster\[dq], \[dq]cat\[dq], \[dq]goat\[dq]])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +myMap: + hamster: squeak + cat: meow +\f[R] +.fi +.SS Pick keys from map, included all the keys +.PP +We create a map of the picked keys plus all the current keys, and run +that through unique +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +myMap: + cat: meow + dog: bark + thing: hamster + hamster: squeak +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].myMap |= pick( ([\[dq]thing\[dq]] + keys) | unique)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +myMap: + thing: hamster + cat: meow + dog: bark + hamster: squeak +\f[R] +.fi +.SS Pick indices from array +.PP +Note that the order of the indices matches the pick order and non +existent indices are skipped. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- cat +- leopard +- lion +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]pick([2, 0, 734, -5])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- lion +- cat +\f[R] +.fi +.SH Pipe +.PP +Pipe the results of an expression into another. +Like the bash operator. +.SS Simple Pipe +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + b: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a | .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cat +\f[R] +.fi +.SS Multiple updates +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cow +b: sheep +c: same +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a = \[dq]cat\[dq] | .b = \[dq]dog\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: cat +b: dog +c: same +\f[R] +.fi +.SH Pivot +.PP +Emulates the \f[C]PIVOT\f[R] function supported by several popular RDBMS +systems. +.SS Pivot a sequence of sequences +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- - foo + - bar + - baz +- - sis + - boom + - bah +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]pivot\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- - foo + - sis +- - bar + - boom +- - baz + - bah +\f[R] +.fi +.SS Pivot sequence of heterogeneous sequences +.PP +Missing values are \[lq]padded\[rq] to null. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- - foo + - bar + - baz +- - sis + - boom + - bah + - blah +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]pivot\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- - foo + - sis +- - bar + - boom +- - baz + - bah +- - + - blah +\f[R] +.fi +.SS Pivot sequence of maps +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- foo: a + bar: b + baz: c +- foo: x + bar: y + baz: z +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]pivot\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +foo: + - a + - x +bar: + - b + - y +baz: + - c + - z +\f[R] +.fi +.SS Pivot sequence of heterogeneous maps +.PP +Missing values are \[lq]padded\[rq] to null. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- foo: a + bar: b + baz: c +- foo: x + bar: y + baz: z + what: ever +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]pivot\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +foo: + - a + - x +bar: + - b + - y +baz: + - c + - z +what: + - + - ever +\f[R] +.fi +.SH Recursive Descent (Glob) +.PP +This operator recursively matches (or globs) all children nodes given of +a particular element, including that node itself. +This is most often used to apply a filter recursively against all +matches. +.SS match values form \f[C]..\f[R] +.PP +This will, like the \f[C]jq\f[R] equivalent, recursively match all +\f[I]value\f[R] nodes. +Use it to find/manipulate particular values. +.PP +For instance to set the \f[C]style\f[R] of all \f[I]value\f[R] nodes in +a yaml doc, excluding map keys: +.IP +.nf +\f[C] +yq \[aq].. style= \[dq]flow\[dq]\[aq] file.yaml +\f[R] +.fi +.SS match values and map keys form \f[C]...\f[R] +.PP +The also includes map keys in the results set. +This is particularly useful in YAML as unlike JSON, map keys can have +their own styling and tags and also use anchors and aliases. +.PP +For instance to set the \f[C]style\f[R] of all nodes in a yaml doc, +including the map keys: +.IP +.nf +\f[C] +yq \[aq]... style= \[dq]flow\[dq]\[aq] file.yaml +\f[R] +.fi +.SS Recurse map (values only) +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: frog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]..\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: frog +frog +\f[R] +.fi +.SS Recursively find nodes with keys +.PP +Note that this example has wrapped the expression in \f[C][]\f[R] to +show that there are two matches returned. +You do not have to wrap in \f[C][]\f[R] in your path expression. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + name: frog + b: + name: blog + age: 12 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq][.. | select(has(\[dq]name\[dq]))]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- name: frog + b: + name: blog + age: 12 +- name: blog + age: 12 +\f[R] +.fi +.SS Recursively find nodes with values +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + nameA: frog + b: + nameB: frog + age: 12 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].. | select(. == \[dq]frog\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +frog +frog +\f[R] +.fi +.SS Recurse map (values and keys) +.PP +Note that the map key appears in the results +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: frog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]...\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: frog +a +frog +\f[R] +.fi +.SS Aliases are not traversed +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: &cat + c: frog +b: *cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq][..]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- a: &cat + c: frog + b: *cat +- &cat + c: frog +- frog +- *cat +\f[R] +.fi +.SS Merge docs are not traversed +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +foo: &foo + a: foo_a + thing: foo_thing + c: foo_c +bar: &bar + b: bar_b + thing: bar_thing + c: bar_c +foobarList: + b: foobarList_b + !!merge <<: + - *foo + - *bar + c: foobarList_c +foobar: + c: foobar_c + !!merge <<: *foo + thing: foobar_thing +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].foobar | [..]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- c: foobar_c + !!merge <<: *foo + thing: foobar_thing +- foobar_c +- *foo +- foobar_thing +\f[R] +.fi +.SH Reduce +.PP +Reduce is a powerful way to process a collection of data into a new +form. +.IP +.nf +\f[C] + as $ ireduce (; ) +\f[R] +.fi +.PP +e.g. +.IP +.nf +\f[C] +\&.[] as $item ireduce (0; . + $item) +\f[R] +.fi +.PP +On the LHS we are configuring the collection of items that will be +reduced \f[C]\f[R] as well as what each element will be called +\f[C]$\f[R]. +Note that the array has been splatted into its individual elements. +.PP +On the RHS there is \f[C]\f[R], the starting value of the +accumulator and \f[C]\f[R], the expression that will update the +accumulator for each element in the collection. +Note that within the block expression, \f[C].\f[R] will evaluate to the +current value of the accumulator. +.SS yq vs jq syntax +.PP +Reduce syntax in \f[C]yq\f[R] is a little different from \f[C]jq\f[R] - +as \f[C]yq\f[R] (currently) isn\[cq]t as sophisticated as \f[C]jq\f[R] +and its only supports infix notation (e.g.\ a + b, where the operator is +in the middle of the two parameters) - where as \f[C]jq\f[R] uses a mix +of infix notation with \f[I]prefix\f[R] notation +(e.g.\ \f[C]reduce a b\f[R] is like writing \f[C]+ a b\f[R]). +.PP +To that end, the reduce operator is called \f[C]ireduce\f[R] for +backwards compatibility if a \f[C]jq\f[R] like prefix version of +\f[C]reduce\f[R] is ever added. +.SS Sum numbers +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- 10 +- 2 +- 5 +- 3 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] as $item ireduce (0; . + $item)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +20 +\f[R] +.fi +.SS Merge all yaml files together +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +\f[R] +.fi +.PP +And another sample another.yml file of: +.IP +.nf +\f[C] +b: dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq eval-all \[aq]. as $item ireduce ({}; . * $item )\[aq] sample.yml another.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: cat +b: dog +\f[R] +.fi +.SS Convert an array to an object +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- name: Cathy + has: apples +- name: Bob + has: bananas +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] as $item ireduce ({}; .[$item | .name] = ($item | .has) )\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +Cathy: apples +Bob: bananas +\f[R] +.fi +.SH Reverse +.PP +Reverses the order of the items in an array +.SS Reverse +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- 1 +- 2 +- 3 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]reverse\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- 3 +- 2 +- 1 +\f[R] +.fi +.SS Sort descending by string field +.PP +Use sort with reverse to sort in descending order. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- a: banana +- a: cat +- a: apple +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]sort_by(.a) | reverse\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- a: cat +- a: banana +- a: apple +\f[R] +.fi +.SH Select +.PP +Select is used to filter arrays and maps by a boolean expression. +.SS Related Operators +.IP \[bu] 2 +equals / not equals (\f[C]==\f[R], \f[C]!=\f[R]) operators +here (https://mikefarah.gitbook.io/yq/operators/equals) +.IP \[bu] 2 +comparison (\f[C]>=\f[R], \f[C]<\f[R] etc) operators +here (https://mikefarah.gitbook.io/yq/operators/compare) +.IP \[bu] 2 +boolean operators (\f[C]and\f[R], \f[C]or\f[R], \f[C]any\f[R] etc) +here (https://mikefarah.gitbook.io/yq/operators/boolean-operators) +.SS Select elements from array using wildcard prefix +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- cat +- goat +- dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] | select(. == \[dq]*at\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cat +goat +\f[R] +.fi +.SS Select elements from array using wildcard suffix +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- go-kart +- goat +- dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] | select(. == \[dq]go*\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +go-kart +goat +\f[R] +.fi +.SS Select elements from array using wildcard prefix and suffix +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- ago +- go +- meow +- going +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] | select(. == \[dq]*go*\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +ago +go +going +\f[R] +.fi +.SS Select elements from array with regular expression +.PP +See more regular expression examples under the \f[C]string\f[R] operator +docs (https://mikefarah.gitbook.io/yq/operators/string-operators). +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- this_0 +- not_this +- nor_0_this +- thisTo_4 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] | select(test(\[dq][a-zA-Z]+_[0-9]$\[dq]))\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +this_0 +thisTo_4 +\f[R] +.fi +.SS Select items from a map +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +things: cat +bob: goat +horse: dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] | select(. == \[dq]cat\[dq] or test(\[dq]og$\[dq]))\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cat +dog +\f[R] +.fi +.SS Use select and with_entries to filter map keys +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +name: bob +legs: 2 +game: poker +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]with_entries(select(.key | test(\[dq]ame$\[dq])))\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +name: bob +game: poker +\f[R] +.fi +.SS Select multiple items in a map and update +.PP +Note the brackets around the entire LHS. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + things: cat + bob: goat + horse: dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq](.a.[] | select(. == \[dq]cat\[dq] or . == \[dq]goat\[dq])) |= \[dq]rabbit\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + things: rabbit + bob: rabbit + horse: dog +\f[R] +.fi +.SH Shuffle +.PP +Shuffles an array. +Note that this command does \f[I]not\f[R] use a cryptographically secure +random number generator to randomise the array order. +.SS Shuffle array +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- 1 +- 2 +- 3 +- 4 +- 5 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]shuffle\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- 5 +- 2 +- 4 +- 1 +- 3 +\f[R] +.fi +.SS Shuffle array in place +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +cool: + - 1 + - 2 + - 3 + - 4 + - 5 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].cool |= shuffle\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cool: + - 5 + - 2 + - 4 + - 1 + - 3 +\f[R] +.fi +.SH Slice/Splice Array +.PP +The slice array operator takes an array as input and returns a subarray. +Like the \f[C]jq\f[R] equivalent, \f[C].[10:15]\f[R] will return an +array of length 5, starting from index 10 inclusive, up to index 15 +exclusive. +Negative numbers count backwards from the end of the array. +.PP +You may leave out the first or second number, which will refer to the +start or end of the array respectively. +.SS Slicing arrays +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- cat +- dog +- frog +- cow +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[1:3]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- dog +- frog +\f[R] +.fi +.SS Slicing arrays - without the first number +.PP +Starts from the start of the array +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- cat +- dog +- frog +- cow +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[:2]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- cat +- dog +\f[R] +.fi +.SS Slicing arrays - without the second number +.PP +Finishes at the end of the array +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- cat +- dog +- frog +- cow +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[2:]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- frog +- cow +\f[R] +.fi +.SS Slicing arrays - use negative numbers to count backwards from the end +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- cat +- dog +- frog +- cow +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[1:-1]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- dog +- frog +\f[R] +.fi +.SS Inserting into the middle of an array +.PP +using an expression to find the index +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- cat +- dog +- frog +- cow +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq](.[] | select(. == \[dq]dog\[dq]) | key + 1) as $pos | .[0:($pos)] + [\[dq]rabbit\[dq]] + .[$pos:]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- cat +- dog +- rabbit +- frog +- cow +\f[R] +.fi +.SH Sort Keys +.PP +The Sort Keys operator sorts maps by their keys (based on their string +value). +This operator does not do anything to arrays or scalars (so you can +easily recursively apply it to all maps). +.PP +Sort is particularly useful for diffing two different yaml documents: +.IP +.nf +\f[C] +yq -i -P \[aq]sort_keys(..)\[aq] file1.yml +yq -i -P \[aq]sort_keys(..)\[aq] file2.yml +diff file1.yml file2.yml +\f[R] +.fi +.PP +Note that \f[C]yq\f[R] does not yet consider anchors when sorting by +keys - this may result in invalid yaml documents if you are using merge +anchors. +.PP +For more advanced sorting, you can use the +sort_by (https://mikefarah.gitbook.io/yq/operators/sort) function on a +map, and give it a custom function like +\f[C]sort_by(key | downcase)\f[R]. +.SS Sort keys of map +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +c: frog +a: blah +b: bing +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]sort_keys(.)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: blah +b: bing +c: frog +\f[R] +.fi +.SS Sort keys recursively +.PP +Note the array elements are left unsorted, but maps inside arrays are +sorted +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +bParent: + c: dog + array: + - 3 + - 1 + - 2 +aParent: + z: donkey + x: + - c: yum + b: delish + - b: ew + a: apple +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]sort_keys(..)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +aParent: + x: + - b: delish + c: yum + - a: apple + b: ew + z: donkey +bParent: + array: + - 3 + - 1 + - 2 + c: dog +\f[R] +.fi +.SH Sort +.PP +Sorts an array. +Use \f[C]sort\f[R] to sort an array as is, or \f[C]sort_by(exp)\f[R] to +sort by a particular expression (e.g.\ subfield). +.PP +To sort by descending order, pipe the results through the +\f[C]reverse\f[R] operator after sorting. +.PP +Note that at this stage, \f[C]yq\f[R] only sorts scalar fields. +.SS Sort by string field +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- a: banana +- a: cat +- a: apple +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]sort_by(.a)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- a: apple +- a: banana +- a: cat +\f[R] +.fi +.SS Sort by multiple fields +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- a: dog +- a: cat + b: banana +- a: cat + b: apple +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]sort_by(.a, .b)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- a: cat + b: apple +- a: cat + b: banana +- a: dog +\f[R] +.fi +.SS Sort descending by string field +.PP +Use sort with reverse to sort in descending order. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- a: banana +- a: cat +- a: apple +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]sort_by(.a) | reverse\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- a: cat +- a: banana +- a: apple +\f[R] +.fi +.SS Sort array in place +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +cool: + - a: banana + - a: cat + - a: apple +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].cool |= sort_by(.a)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cool: + - a: apple + - a: banana + - a: cat +\f[R] +.fi +.SS Sort array of objects by key +.PP +Note that you can give sort_by complex expressions, not just paths +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +cool: + - b: banana + - a: banana + - c: banana +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].cool |= sort_by(keys | .[0])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cool: + - a: banana + - b: banana + - c: banana +\f[R] +.fi +.SS Sort a map +.PP +Sorting a map, by default this will sort by the values +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +y: b +z: a +x: c +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]sort\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +z: a +y: b +x: c +\f[R] +.fi +.SS Sort a map by keys +.PP +Use sort_by to sort a map using a custom function +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +Y: b +z: a +x: c +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]sort_by(key | downcase)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +x: c +Y: b +z: a +\f[R] +.fi +.SS Sort is stable +.PP +Note the order of the elements in unchanged when equal in sorting. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- a: banana + b: 1 +- a: banana + b: 2 +- a: banana + b: 3 +- a: banana + b: 4 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]sort_by(.a)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- a: banana + b: 1 +- a: banana + b: 2 +- a: banana + b: 3 +- a: banana + b: 4 +\f[R] +.fi +.SS Sort by numeric field +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- a: 10 +- a: 100 +- a: 1 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]sort_by(.a)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- a: 1 +- a: 10 +- a: 100 +\f[R] +.fi +.SS Sort by custom date field +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- a: 12-Jun-2011 +- a: 23-Dec-2010 +- a: 10-Aug-2011 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]with_dtf(\[dq]02-Jan-2006\[dq]; sort_by(.a))\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- a: 23-Dec-2010 +- a: 12-Jun-2011 +- a: 10-Aug-2011 +\f[R] +.fi +.SS Sort, nulls come first +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- 8 +- 3 +- null +- 6 +- true +- false +- cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]sort\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- null +- false +- true +- 3 +- 6 +- 8 +- cat +\f[R] +.fi +.SH Split into Documents +.PP +This operator splits all matches into separate documents +.SS Split empty +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]split_doc\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +\f[R] +.fi +.SS Split array +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- a: cat +- b: dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] | split_doc\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: cat +--- +b: dog +\f[R] +.fi +.SH String Operators +.SS RegEx +.PP +This uses Golang\[cq]s native regex functions under the hood - See their +docs (https://github.com/google/re2/wiki/Syntax) for the supported +syntax. +.PP +Case insensitive tip: prefix the regex with \f[C](?i)\f[R] - +e.g.\ \f[C]test(\[dq](?i)cats\[dq])\f[R]. +.SS match(regEx) +.PP +This operator returns the substring match details of the given regEx. +.SS capture(regEx) +.PP +Capture returns named RegEx capture groups in a map. +Can be more convenient than \f[C]match\f[R] depending on what you are +doing. +.SS test(regEx) +.PP +Returns true if the string matches the RegEx, false otherwise. +.SS sub(regEx, replacement) +.PP +Substitutes matched substrings. +The first parameter is the regEx to match substrings within the original +string. +The second parameter specifies what to replace those matches with. +This can refer to capture groups from the first RegEx. +.SS String blocks, bash and newlines +.PP +Bash is notorious for chomping on precious trailing newline characters, +making it tricky to set strings with newlines properly. +In particular, the \f[C]$( exp )\f[R] \f[I]will trim trailing +newlines\f[R]. +.PP +For instance to get this yaml: +.IP +.nf +\f[C] +a: | + cat +\f[R] +.fi +.PP +Using \f[C]$( exp )\f[R] wont work, as it will trim the trailing +newline. +.IP +.nf +\f[C] +m=$(echo \[dq]cat\[rs]n\[dq]) yq -n \[aq].a = strenv(m)\[aq] +a: cat +\f[R] +.fi +.PP +However, using printf works: +.IP +.nf +\f[C] +printf -v m \[dq]cat\[rs]n\[dq] ; m=\[dq]$m\[dq] yq -n \[aq].a = strenv(m)\[aq] +a: | + cat +\f[R] +.fi +.PP +As well as having multiline expressions: +.IP +.nf +\f[C] +m=\[dq]cat +\[dq] yq -n \[aq].a = strenv(m)\[aq] +a: | + cat +\f[R] +.fi +.PP +Similarly, if you\[cq]re trying to set the content from a file, and want +a trailing newline: +.IP +.nf +\f[C] +IFS= read -rd \[aq]\[aq] output < <(cat my_file) +output=$output ./yq \[aq].data.values = strenv(output)\[aq] first.yml +\f[R] +.fi +.SS Interpolation +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +value: things +another: stuff +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].message = \[dq]I like \[rs](.value) and \[rs](.another)\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +value: things +another: stuff +message: I like things and stuff +\f[R] +.fi +.SS Interpolation - not a string +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +value: + an: apple +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].message = \[dq]I like \[rs](.value)\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +value: + an: apple +message: \[aq]I like an: apple\[aq] +\f[R] +.fi +.SS To up (upper) case +.PP +Works with unicode characters +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +\['a]gua +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]upcase\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +\['A]GUA +\f[R] +.fi +.SS To down (lower) case +.PP +Works with unicode characters +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +\['A]gUA +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]downcase\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +\['a]gua +\f[R] +.fi +.SS Join strings +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- cat +- meow +- 1 +- null +- true +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]join(\[dq]; \[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cat; meow; 1; ; true +\f[R] +.fi +.SS Trim strings +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- \[aq] cat\[aq] +- \[aq]dog \[aq] +- \[aq] cow cow \[aq] +- horse +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] | trim\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cat +dog +cow cow +horse +\f[R] +.fi +.SS Match string +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +foo bar foo +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]match(\[dq]foo\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +string: foo +offset: 0 +length: 3 +captures: [] +\f[R] +.fi +.SS Match string, case insensitive +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +foo bar FOO +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq][match(\[dq](?i)foo\[dq]; \[dq]g\[dq])]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- string: foo + offset: 0 + length: 3 + captures: [] +- string: FOO + offset: 8 + length: 3 + captures: [] +\f[R] +.fi +.SS Match with global capture group +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +abc abc +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq][match(\[dq](ab)(c)\[dq]; \[dq]g\[dq])]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- string: abc + offset: 0 + length: 3 + captures: + - string: ab + offset: 0 + length: 2 + - string: c + offset: 2 + length: 1 +- string: abc + offset: 4 + length: 3 + captures: + - string: ab + offset: 4 + length: 2 + - string: c + offset: 6 + length: 1 +\f[R] +.fi +.SS Match with named capture groups +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +foo bar foo foo foo +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq][match(\[dq]foo (?Pbar)? foo\[dq]; \[dq]g\[dq])]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- string: foo bar foo + offset: 0 + length: 11 + captures: + - string: bar + offset: 4 + length: 3 + name: bar123 +- string: foo foo + offset: 12 + length: 8 + captures: + - string: null + offset: -1 + length: 0 + name: bar123 +\f[R] +.fi +.SS Capture named groups into a map +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +xyzzy-14 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]capture(\[dq](?P[a-z]+)-(?P[0-9]+)\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: xyzzy +n: \[dq]14\[dq] +\f[R] +.fi +.SS Match without global flag +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +cat cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]match(\[dq]cat\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +string: cat +offset: 0 +length: 3 +captures: [] +\f[R] +.fi +.SS Match with global flag +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +cat cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq][match(\[dq]cat\[dq]; \[dq]g\[dq])]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- string: cat + offset: 0 + length: 3 + captures: [] +- string: cat + offset: 4 + length: 3 + captures: [] +\f[R] +.fi +.SS Test using regex +.PP +Like jq\[cq]s equivalent, this works like match but only returns +true/false instead of full match details +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- cat +- dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] | test(\[dq]at\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +true +false +\f[R] +.fi +.SS Substitute / Replace string +.PP +This uses Golang\[cq]s regex, described +here (https://github.com/google/re2/wiki/Syntax). +Note the use of \f[C]|=\f[R] to run in context of the current string +value. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: dogs are great +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a |= sub(\[dq]dogs\[dq], \[dq]cats\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: cats are great +\f[R] +.fi +.SS Substitute / Replace string with regex +.PP +This uses Golang\[cq]s regex, described +here (https://github.com/google/re2/wiki/Syntax). +Note the use of \f[C]|=\f[R] to run in context of the current string +value. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +b: heat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] |= sub(\[dq](a)\[dq], \[dq]${1}r\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: cart +b: heart +\f[R] +.fi +.SS Custom types: that are really strings +.PP +When custom tags are encountered, yq will try to decode the underlying +type. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: !horse cat +b: !goat heat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] |= sub(\[dq](a)\[dq], \[dq]${1}r\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: !horse cart +b: !goat heart +\f[R] +.fi +.SS Split strings +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +cat; meow; 1; ; true +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]split(\[dq]; \[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- cat +- meow +- \[dq]1\[dq] +- \[dq]\[dq] +- \[dq]true\[dq] +\f[R] +.fi +.SS Split strings one match +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +word +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]split(\[dq]; \[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- word +\f[R] +.fi +.SS To string +.PP +Note that you may want to force \f[C]yq\f[R] to leave scalar values +wrapped by passing in \f[C]--unwrapScalar=false\f[R] or \f[C]-r=f\f[R] +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- 1 +- true +- null +- \[ti] +- cat +- an: object +- - array + - 2 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] |= to_string\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- \[dq]1\[dq] +- \[dq]true\[dq] +- \[dq]null\[dq] +- \[dq]\[ti]\[dq] +- cat +- \[dq]an: object\[dq] +- \[dq]- array\[rs]n- 2\[dq] +\f[R] +.fi +.SH Style +.PP +The style operator can be used to get or set the style of nodes +(e.g.\ string style, yaml style). +Use this to control the formatting of the document in yaml. +.SS Update and set style of a particular node (simple) +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + b: thing + c: something +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a.b = \[dq]new\[dq] | .a.b style=\[dq]double\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: \[dq]new\[dq] + c: something +\f[R] +.fi +.SS Update and set style of a particular node using path variables +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + b: thing + c: something +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]with(.a.b ; . = \[dq]new\[dq] | . style=\[dq]double\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: \[dq]new\[dq] + c: something +\f[R] +.fi +.SS Set tagged style +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +b: 5 +c: 3.2 +e: true +f: + - 1 + - 2 + - 3 +g: + something: cool +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].. style=\[dq]tagged\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +!!map +a: !!str cat +b: !!int 5 +c: !!float 3.2 +e: !!bool true +f: !!seq + - !!int 1 + - !!int 2 + - !!int 3 +g: !!map + something: !!str cool +\f[R] +.fi +.SS Set double quote style +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +b: 5 +c: 3.2 +e: true +f: + - 1 + - 2 + - 3 +g: + something: cool +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].. style=\[dq]double\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: \[dq]cat\[dq] +b: \[dq]5\[dq] +c: \[dq]3.2\[dq] +e: \[dq]true\[dq] +f: + - \[dq]1\[dq] + - \[dq]2\[dq] + - \[dq]3\[dq] +g: + something: \[dq]cool\[dq] +\f[R] +.fi +.SS Set double quote style on map keys too +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +b: 5 +c: 3.2 +e: true +f: + - 1 + - 2 + - 3 +g: + something: cool +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]... style=\[dq]double\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +\[dq]a\[dq]: \[dq]cat\[dq] +\[dq]b\[dq]: \[dq]5\[dq] +\[dq]c\[dq]: \[dq]3.2\[dq] +\[dq]e\[dq]: \[dq]true\[dq] +\[dq]f\[dq]: + - \[dq]1\[dq] + - \[dq]2\[dq] + - \[dq]3\[dq] +\[dq]g\[dq]: + \[dq]something\[dq]: \[dq]cool\[dq] +\f[R] +.fi +.SS Set single quote style +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +b: 5 +c: 3.2 +e: true +f: + - 1 + - 2 + - 3 +g: + something: cool +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].. style=\[dq]single\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: \[aq]cat\[aq] +b: \[aq]5\[aq] +c: \[aq]3.2\[aq] +e: \[aq]true\[aq] +f: + - \[aq]1\[aq] + - \[aq]2\[aq] + - \[aq]3\[aq] +g: + something: \[aq]cool\[aq] +\f[R] +.fi +.SS Set literal quote style +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +b: 5 +c: 3.2 +e: true +f: + - 1 + - 2 + - 3 +g: + something: cool +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].. style=\[dq]literal\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: |- + cat +b: |- + 5 +c: |- + 3.2 +e: |- + true +f: + - |- + 1 + - |- + 2 + - |- + 3 +g: + something: |- + cool +\f[R] +.fi +.SS Set folded quote style +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +b: 5 +c: 3.2 +e: true +f: + - 1 + - 2 + - 3 +g: + something: cool +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].. style=\[dq]folded\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: >- + cat +b: >- + 5 +c: >- + 3.2 +e: >- + true +f: + - >- + 1 + - >- + 2 + - >- + 3 +g: + something: >- + cool +\f[R] +.fi +.SS Set flow quote style +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +b: 5 +c: 3.2 +e: true +f: + - 1 + - 2 + - 3 +g: + something: cool +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].. style=\[dq]flow\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +{a: cat, b: 5, c: 3.2, e: true, f: [1, 2, 3], g: {something: cool}} +\f[R] +.fi +.SS Reset style - or pretty print +.PP +Set empty (default) quote style, note the usage of \f[C]...\f[R] to +match keys too. +Note that there is a \f[C]--prettyPrint/-P\f[R] short flag for this. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +{a: cat, \[dq]b\[dq]: 5, \[aq]c\[aq]: 3.2, \[dq]e\[dq]: true, f: [1,2,3], \[dq]g\[dq]: { something: \[dq]cool\[dq]} } +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]... style=\[dq]\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: cat +b: 5 +c: 3.2 +e: true +f: + - 1 + - 2 + - 3 +g: + something: cool +\f[R] +.fi +.SS Set style relatively with assign-update +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: single +b: double +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] style |= .\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: \[aq]single\[aq] +b: \[dq]double\[dq] +\f[R] +.fi +.SS Read style +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +{a: \[dq]cat\[dq], b: \[aq]thing\[aq]} +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].. | style\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +flow +double +single +\f[R] +.fi +.SH Subtract +.PP +You can use subtract to subtract numbers as well as remove elements from +an array. +.SS Array subtraction +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq][1,2] - [2,3]\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- 1 +\f[R] +.fi +.SS Array subtraction with nested array +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq][[1], 1, 2] - [[1], 3]\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- 1 +- 2 +\f[R] +.fi +.SS Array subtraction with nested object +.PP +Note that order of the keys does not matter +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- a: b + c: d +- a: b +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]. - [{\[dq]c\[dq]: \[dq]d\[dq], \[dq]a\[dq]: \[dq]b\[dq]}]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- a: b +\f[R] +.fi +.SS Number subtraction - float +.PP +If the lhs or rhs are floats then the expression will be calculated with +floats. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 3 +b: 4.5 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a = .a - .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: -1.5 +b: 4.5 +\f[R] +.fi +.SS Number subtraction - int +.PP +If both the lhs and rhs are ints then the expression will be calculated +with ints. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 3 +b: 4 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a = .a - .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: -1 +b: 4 +\f[R] +.fi +.SS Decrement numbers +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 3 +b: 5 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] -= 1\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: 2 +b: 4 +\f[R] +.fi +.SS Date subtraction +.PP +You can subtract durations from dates. +Assumes RFC3339 date time format, see date-time +operators (https://mikefarah.gitbook.io/yq/operators/date-time-operators) +for more information. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: 2021-01-01T03:10:00Z +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a -= \[dq]3h10m\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: 2021-01-01T00:00:00Z +\f[R] +.fi +.SS Date subtraction - custom format +.PP +Use with_dtf to specify your datetime format. +See date-time +operators (https://mikefarah.gitbook.io/yq/operators/date-time-operators) +for more information. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: Saturday, 15-Dec-01 at 6:00AM GMT +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]with_dtf(\[dq]Monday, 02-Jan-06 at 3:04PM MST\[dq], .a -= \[dq]3h1m\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: Saturday, 15-Dec-01 at 2:59AM GMT +\f[R] +.fi +.SS Custom types: that are really numbers +.PP +When custom tags are encountered, yq will try to decode the underlying +type. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: !horse 2 +b: !goat 1 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a -= .b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: !horse 1 +b: !goat 1 +\f[R] +.fi +.SH Tag +.PP +The tag operator can be used to get or set the tag of nodes +(e.g.\ \f[C]!!str\f[R], \f[C]!!int\f[R], \f[C]!!bool\f[R]). +.SS Get tag +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +b: 5 +c: 3.2 +e: true +f: [] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].. | tag\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +!!map +!!str +!!int +!!float +!!bool +!!seq +\f[R] +.fi +.SS type is an alias for tag +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +b: 5 +c: 3.2 +e: true +f: [] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].. | type\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +!!map +!!str +!!int +!!float +!!bool +!!seq +\f[R] +.fi +.SS Set custom tag +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: str +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a tag = \[dq]!!mikefarah\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: !!mikefarah str +\f[R] +.fi +.SS Find numbers and convert them to strings +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +b: 5 +c: 3.2 +e: true +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq](.. | select(tag == \[dq]!!int\[dq])) tag= \[dq]!!str\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: cat +b: \[dq]5\[dq] +c: 3.2 +e: true +\f[R] +.fi +.SH To Number +.PP +Parses the input as a number. +yq will try to parse values as an int first, failing that it will try +float. +Values that already ints or floats will be left alone. +.SS Converts strings to numbers +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- \[dq]3\[dq] +- \[dq]3.1\[dq] +- \[dq]-1e3\[dq] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] | to_number\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +3 +3.1 +-1e3 +\f[R] +.fi +.SS Doesn\[cq]t change numbers +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- 3 +- 3.1 +- -1e3 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] | to_number\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +3 +3.1 +-1e3 +\f[R] +.fi +.SS Cannot convert null +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq].a.b | to_number\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +Error: cannot convert node value [null] at path a.b of tag !!null to number +\f[R] +.fi +.SH Traverse (Read) +.PP +This is the simplest (and perhaps most used) operator. +It is used to navigate deeply into yaml structures. +.SS Simple map navigation +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + b: apple +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +b: apple +\f[R] +.fi +.SS Splat +.PP +Often used to pipe children into other operators +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- b: apple +- c: banana +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +b: apple +c: banana +\f[R] +.fi +.SS Optional Splat +.PP +Just like splat, but won\[cq]t error if you run it against scalars +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +\f[R] +.fi +.SS Special characters +.PP +Use quotes with square brackets around path elements with special +characters +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +\[dq]{}\[dq]: frog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[\[dq]{}\[dq]]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +frog +\f[R] +.fi +.SS Nested special characters +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + \[dq]key.withdots\[dq]: + \[dq]another.key\[dq]: apple +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a[\[dq]key.withdots\[dq]][\[dq]another.key\[dq]]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +apple +\f[R] +.fi +.SS Keys with spaces +.PP +Use quotes with square brackets around path elements with special +characters +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +\[dq]red rabbit\[dq]: frog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[\[dq]red rabbit\[dq]]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +frog +\f[R] +.fi +.SS Dynamic keys +.PP +Expressions within [] can be used to dynamically lookup / calculate keys +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +b: apple +apple: crispy yum +banana: soft yum +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[.b]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +crispy yum +\f[R] +.fi +.SS Children don\[cq]t exist +.PP +Nodes are added dynamically while traversing +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +c: banana +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a.b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +null +\f[R] +.fi +.SS Optional identifier +.PP +Like jq, does not output an error when the yaml is not an array or +object as expected +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- 1 +- 2 +- 3 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a?\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +\f[R] +.fi +.SS Wildcard matching +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + cat: apple + mad: things +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a.\[dq]*a*\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +apple +things +\f[R] +.fi +.SS Aliases +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: &cat + c: frog +b: *cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].b\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +*cat +\f[R] +.fi +.SS Traversing aliases with splat +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: &cat + c: frog +b: *cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].b[]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +frog +\f[R] +.fi +.SS Traversing aliases explicitly +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: &cat + c: frog +b: *cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].b.c\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +frog +\f[R] +.fi +.SS Traversing arrays by index +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- 1 +- 2 +- 3 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[0]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +1 +\f[R] +.fi +.SS Traversing nested arrays by index +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +[[], [cat]] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[1][0]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cat +\f[R] +.fi +.SS Maps with numeric keys +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +2: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[2]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cat +\f[R] +.fi +.SS Maps with non existing numeric keys +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: b +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[0]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +null +\f[R] +.fi +.SS Traversing merge anchors +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +foo: &foo + a: foo_a + thing: foo_thing + c: foo_c +bar: &bar + b: bar_b + thing: bar_thing + c: bar_c +foobarList: + b: foobarList_b + !!merge <<: + - *foo + - *bar + c: foobarList_c +foobar: + c: foobar_c + !!merge <<: *foo + thing: foobar_thing +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].foobar.a\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +foo_a +\f[R] +.fi +.SS Traversing merge anchors with override +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +foo: &foo + a: foo_a + thing: foo_thing + c: foo_c +bar: &bar + b: bar_b + thing: bar_thing + c: bar_c +foobarList: + b: foobarList_b + !!merge <<: + - *foo + - *bar + c: foobarList_c +foobar: + c: foobar_c + !!merge <<: *foo + thing: foobar_thing +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].foobar.c\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +foo_c +\f[R] +.fi +.SS Traversing merge anchors with local override +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +foo: &foo + a: foo_a + thing: foo_thing + c: foo_c +bar: &bar + b: bar_b + thing: bar_thing + c: bar_c +foobarList: + b: foobarList_b + !!merge <<: + - *foo + - *bar + c: foobarList_c +foobar: + c: foobar_c + !!merge <<: *foo + thing: foobar_thing +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].foobar.thing\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +foobar_thing +\f[R] +.fi +.SS Splatting merge anchors +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +foo: &foo + a: foo_a + thing: foo_thing + c: foo_c +bar: &bar + b: bar_b + thing: bar_thing + c: bar_c +foobarList: + b: foobarList_b + !!merge <<: + - *foo + - *bar + c: foobarList_c +foobar: + c: foobar_c + !!merge <<: *foo + thing: foobar_thing +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].foobar[]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +foo_c +foo_a +foobar_thing +\f[R] +.fi +.SS Traversing merge anchor lists +.PP +Note that the later merge anchors override previous +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +foo: &foo + a: foo_a + thing: foo_thing + c: foo_c +bar: &bar + b: bar_b + thing: bar_thing + c: bar_c +foobarList: + b: foobarList_b + !!merge <<: + - *foo + - *bar + c: foobarList_c +foobar: + c: foobar_c + !!merge <<: *foo + thing: foobar_thing +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].foobarList.thing\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +bar_thing +\f[R] +.fi +.SS Splatting merge anchor lists +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +foo: &foo + a: foo_a + thing: foo_thing + c: foo_c +bar: &bar + b: bar_b + thing: bar_thing + c: bar_c +foobarList: + b: foobarList_b + !!merge <<: + - *foo + - *bar + c: foobarList_c +foobar: + c: foobar_c + !!merge <<: *foo + thing: foobar_thing +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].foobarList[]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +bar_b +foo_a +bar_thing +foobarList_c +\f[R] +.fi +.SS Select multiple indices +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + - a + - b + - c +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a[0, 2]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a +c +\f[R] +.fi +.SH Union +.PP +This operator is used to combine different results together. +.SS Combine scalars +.PP +Running +.IP +.nf +\f[C] +yq --null-input \[aq]1, true, \[dq]cat\[dq]\[aq] +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +1 +true +cat +\f[R] +.fi +.SS Combine selected paths +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: fieldA +b: fieldB +c: fieldC +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a, .c\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +fieldA +fieldC +\f[R] +.fi +.SH Unique +.PP +This is used to filter out duplicated items in an array. +Note that the original order of the array is maintained. +.SS Unique array of scalars (string/numbers) +.PP +Note that unique maintains the original order of the array. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- 2 +- 1 +- 3 +- 2 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]unique\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- 2 +- 1 +- 3 +\f[R] +.fi +.SS Unique nulls +.PP +Unique works on the node value, so it considers different +representations of nulls to be different +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- \[ti] +- null +- \[ti] +- null +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]unique\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- \[ti] +- null +\f[R] +.fi +.SS Unique all nulls +.PP +Run against the node tag to unique all the nulls +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- \[ti] +- null +- \[ti] +- null +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]unique_by(tag)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- \[ti] +\f[R] +.fi +.SS Unique array objects +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- name: harry + pet: cat +- name: billy + pet: dog +- name: harry + pet: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]unique\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- name: harry + pet: cat +- name: billy + pet: dog +\f[R] +.fi +.SS Unique array of objects by a field +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- name: harry + pet: cat +- name: billy + pet: dog +- name: harry + pet: dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]unique_by(.name)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- name: harry + pet: cat +- name: billy + pet: dog +\f[R] +.fi +.SS Unique array of arrays +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- - cat + - dog +- - cat + - sheep +- - cat + - dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]unique\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- - cat + - dog +- - cat + - sheep +\f[R] +.fi +.SH Variable Operators +.PP +Like the \f[C]jq\f[R] equivalents, variables are sometimes required for +the more complex expressions (or swapping values between fields). +.PP +Note that there is also an additional \f[C]ref\f[R] operator that holds +a reference (instead of a copy) of the path, allowing you to make +multiple changes to the same path. +.SS Single value variable +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a as $foo | $foo\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cat +\f[R] +.fi +.SS Multi value variable +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- cat +- dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] as $foo | $foo\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cat +dog +\f[R] +.fi +.SS Using variables as a lookup +.PP +Example taken from +jq (https://stedolan.github.io/jq/manual/#Variable/SymbolicBindingOperator:...as$identifier%7C...) +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +\[dq]posts\[dq]: + - \[dq]title\[dq]: First post + \[dq]author\[dq]: anon + - \[dq]title\[dq]: A well-written article + \[dq]author\[dq]: person1 +\[dq]realnames\[dq]: + \[dq]anon\[dq]: Anonymous Coward + \[dq]person1\[dq]: Person McPherson +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].realnames as $names | .posts[] | {\[dq]title\[dq]:.title, \[dq]author\[dq]: $names[.author]}\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +title: First post +author: Anonymous Coward +title: A well-written article +author: Person McPherson +\f[R] +.fi +.SS Using variables to swap values +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: a_value +b: b_value +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a as $x | .b as $y | .b = $x | .a = $y\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: b_value +b: a_value +\f[R] +.fi +.SS Use ref to reference a path repeatedly +.PP +Note: You may find the \f[C]with\f[R] operator more useful. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + b: thing + c: something +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].a.b ref $x | $x = \[dq]new\[dq] | $x style=\[dq]double\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: \[dq]new\[dq] + c: something +\f[R] +.fi +.SH With +.PP +Use the \f[C]with\f[R] operator to conveniently make multiple updates to +a deeply nested path, or to update array elements relatively to each +other. +The first argument expression sets the root context, and the second +expression runs against that root context. +.SS Update and style +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + deeply: + nested: value +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]with(.a.deeply.nested; . = \[dq]newValue\[dq] | . style=\[dq]single\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + deeply: + nested: \[aq]newValue\[aq] +\f[R] +.fi +.SS Update multiple deeply nested properties +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +a: + deeply: + nested: value + other: thing +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]with(.a.deeply; .nested = \[dq]newValue\[dq] | .other= \[dq]newThing\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + deeply: + nested: newValue + other: newThing +\f[R] +.fi +.SS Update array elements relatively +.PP +The second expression runs with each element of the array as it\[cq]s +contextual root. +This allows you to make updates relative to the element. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +myArray: + - a: apple + - a: banana +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]with(.myArray[]; .b = .a + \[dq] yum\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +myArray: + - a: apple + b: apple yum + - a: banana + b: banana yum +\f[R] +.fi +.SH JSON +.PP +Encode and decode to and from JSON. +Supports multiple JSON documents in a single file (e.g.\ NDJSON). +.PP +Note that YAML is a superset of (single document) JSON - so you +don\[cq]t have to use the JSON parser to read JSON when there is only +one JSON document in the input. +You will probably want to pretty print the result in this case, to get +idiomatic YAML styling. +.SS Parse json: simple +.PP +JSON is a subset of yaml, so all you need to do is prettify the output +.PP +Given a sample.json file of: +.IP +.nf +\f[C] +{\[dq]cat\[dq]: \[dq]meow\[dq]} +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -p=json sample.json +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cat: meow +\f[R] +.fi +.SS Parse json: complex +.PP +JSON is a subset of yaml, so all you need to do is prettify the output +.PP +Given a sample.json file of: +.IP +.nf +\f[C] +{\[dq]a\[dq]:\[dq]Easy! as one two three\[dq],\[dq]b\[dq]:{\[dq]c\[dq]:2,\[dq]d\[dq]:[3,4]}} +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -p=json sample.json +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: Easy! as one two three +b: + c: 2 + d: + - 3 + - 4 +\f[R] +.fi +.SS Encode json: simple +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +cat: meow +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=json \[aq].\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +{ + \[dq]cat\[dq]: \[dq]meow\[dq] +} +\f[R] +.fi +.SS Encode json: simple - in one line +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +cat: meow # this is a comment, and it will be dropped. +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=json -I=0 \[aq].\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +{\[dq]cat\[dq]:\[dq]meow\[dq]} +\f[R] +.fi +.SS Encode json: comments +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +cat: meow # this is a comment, and it will be dropped. +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=json \[aq].\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +{ + \[dq]cat\[dq]: \[dq]meow\[dq] +} +\f[R] +.fi +.SS Encode json: anchors +.PP +Anchors are dereferenced +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +cat: &ref meow +anotherCat: *ref +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=json \[aq].\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +{ + \[dq]cat\[dq]: \[dq]meow\[dq], + \[dq]anotherCat\[dq]: \[dq]meow\[dq] +} +\f[R] +.fi +.SS Encode json: multiple results +.PP +Each matching node is converted into a json doc. +This is best used with 0 indent (json document per line) +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +things: [{stuff: cool}, {whatever: cat}] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=json -I=0 \[aq].things[]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +{\[dq]stuff\[dq]:\[dq]cool\[dq]} +{\[dq]whatever\[dq]:\[dq]cat\[dq]} +\f[R] +.fi +.SS Roundtrip JSON Lines / NDJSON +.PP +Given a sample.json file of: +.IP +.nf +\f[C] +{\[dq]this\[dq]: \[dq]is a multidoc json file\[dq]} +{\[dq]each\[dq]: [\[dq]line is a valid json document\[dq]]} +{\[dq]a number\[dq]: 4} +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -p=json -o=json -I=0 sample.json +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +{\[dq]this\[dq]:\[dq]is a multidoc json file\[dq]} +{\[dq]each\[dq]:[\[dq]line is a valid json document\[dq]]} +{\[dq]a number\[dq]:4} +\f[R] +.fi +.SS Roundtrip multi-document JSON +.PP +The parser can also handle multiple multi-line json documents in a +single file (despite this not being in the JSON Lines / NDJSON spec). +Typically you would have one entire JSON document per line, but the +parser also supports multiple multi-line json documents +.PP +Given a sample.json file of: +.IP +.nf +\f[C] +{ + \[dq]this\[dq]: \[dq]is a multidoc json file\[dq] +} +{ + \[dq]it\[dq]: [ + \[dq]has\[dq], + \[dq]consecutive\[dq], + \[dq]json documents\[dq] + ] +} +{ + \[dq]a number\[dq]: 4 +} +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -p=json -o=json -I=2 sample.json +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +{ + \[dq]this\[dq]: \[dq]is a multidoc json file\[dq] +} +{ + \[dq]it\[dq]: [ + \[dq]has\[dq], + \[dq]consecutive\[dq], + \[dq]json documents\[dq] + ] +} +{ + \[dq]a number\[dq]: 4 +} +\f[R] +.fi +.SS Update a specific document in a multi-document json +.PP +Documents are indexed by the \f[C]documentIndex\f[R] or \f[C]di\f[R] +operator. +.PP +Given a sample.json file of: +.IP +.nf +\f[C] +{\[dq]this\[dq]: \[dq]is a multidoc json file\[dq]} +{\[dq]each\[dq]: [\[dq]line is a valid json document\[dq]]} +{\[dq]a number\[dq]: 4} +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -p=json -o=json -I=0 \[aq](select(di == 1) | .each ) += \[dq]cool\[dq]\[aq] sample.json +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +{\[dq]this\[dq]:\[dq]is a multidoc json file\[dq]} +{\[dq]each\[dq]:[\[dq]line is a valid json document\[dq],\[dq]cool\[dq]]} +{\[dq]a number\[dq]:4} +\f[R] +.fi +.SS Find and update a specific document in a multi-document json +.PP +Use expressions as you normally would. +.PP +Given a sample.json file of: +.IP +.nf +\f[C] +{\[dq]this\[dq]: \[dq]is a multidoc json file\[dq]} +{\[dq]each\[dq]: [\[dq]line is a valid json document\[dq]]} +{\[dq]a number\[dq]: 4} +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -p=json -o=json -I=0 \[aq](select(has(\[dq]each\[dq])) | .each ) += \[dq]cool\[dq]\[aq] sample.json +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +{\[dq]this\[dq]:\[dq]is a multidoc json file\[dq]} +{\[dq]each\[dq]:[\[dq]line is a valid json document\[dq],\[dq]cool\[dq]]} +{\[dq]a number\[dq]:4} +\f[R] +.fi +.SS Decode JSON Lines / NDJSON +.PP +Given a sample.json file of: +.IP +.nf +\f[C] +{\[dq]this\[dq]: \[dq]is a multidoc json file\[dq]} +{\[dq]each\[dq]: [\[dq]line is a valid json document\[dq]]} +{\[dq]a number\[dq]: 4} +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -p=json sample.json +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +this: is a multidoc json file +--- +each: + - line is a valid json document +--- +a number: 4 +\f[R] +.fi +.SH CSV +.PP +Encode/Decode/Roundtrip CSV and TSV files. +.SS Encode +.PP +Currently supports arrays of homogeneous flat objects, that is: no +nesting and it assumes the \f[I]first\f[R] object has all the keys +required: +.IP +.nf +\f[C] +- name: Bobo + type: dog +- name: Fifi + type: cat +\f[R] +.fi +.PP +As well as arrays of arrays of scalars (strings/numbers/booleans): +.IP +.nf +\f[C] +- [Bobo, dog] +- [Fifi, cat] +\f[R] +.fi +.SS Decode +.PP +Decode assumes the first CSV/TSV row is the header row, and all rows +beneath are the entries. +The data will be coded into an array of objects, using the header rows +as keys. +.IP +.nf +\f[C] +name,type +Bobo,dog +Fifi,cat +\f[R] +.fi +.SS Encode CSV simple +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- [i, like, csv] +- [because, excel, is, cool] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=csv sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +i,like,csv +because,excel,is,cool +\f[R] +.fi +.SS Encode TSV simple +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- [i, like, csv] +- [because, excel, is, cool] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=tsv sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +i like csv +because excel is cool +\f[R] +.fi +.SS Encode array of objects to csv +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- name: Gary + numberOfCats: 1 + likesApples: true + height: 168.8 +- name: Samantha\[aq]s Rabbit + numberOfCats: 2 + likesApples: false + height: -188.8 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=csv sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +name,numberOfCats,likesApples,height +Gary,1,true,168.8 +Samantha\[aq]s Rabbit,2,false,-188.8 +\f[R] +.fi +.SS Encode array of objects to custom csv format +.PP +Add the header row manually, then the we convert each object into an +array of values - resulting in an array of arrays. +Pick the columns and call the header whatever you like. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- name: Gary + numberOfCats: 1 + likesApples: true + height: 168.8 +- name: Samantha\[aq]s Rabbit + numberOfCats: 2 + likesApples: false + height: -188.8 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=csv \[aq][[\[dq]Name\[dq], \[dq]Number of Cats\[dq]]] + [.[] | [.name, .numberOfCats ]]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +Name,Number of Cats +Gary,1 +Samantha\[aq]s Rabbit,2 +\f[R] +.fi +.SS Encode array of objects to csv - missing fields behaviour +.PP +First entry is used to determine the headers, and it is missing +`likesApples', so it is not included in the csv. +Second entry does not have `numberOfCats' so that is blank +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- name: Gary + numberOfCats: 1 + height: 168.8 +- name: Samantha\[aq]s Rabbit + height: -188.8 + likesApples: false +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=csv sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +name,numberOfCats,height +Gary,1,168.8 +Samantha\[aq]s Rabbit,,-188.8 +\f[R] +.fi +.SS Parse CSV into an array of objects +.PP +First row is assumed to be the header row. +By default, entries with YAML/JSON formatting will be parsed! +.PP +Given a sample.csv file of: +.IP +.nf +\f[C] +name,numberOfCats,likesApples,height,facts +Gary,1,true,168.8,cool: true +Samantha\[aq]s Rabbit,2,false,-188.8,tall: indeed +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -p=csv sample.csv +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- name: Gary + numberOfCats: 1 + likesApples: true + height: 168.8 + facts: + cool: true +- name: Samantha\[aq]s Rabbit + numberOfCats: 2 + likesApples: false + height: -188.8 + facts: + tall: indeed +\f[R] +.fi +.SS Parse CSV into an array of objects, no auto-parsing +.PP +First row is assumed to be the header row. +Entries with YAML/JSON will be left as strings. +.PP +Given a sample.csv file of: +.IP +.nf +\f[C] +name,numberOfCats,likesApples,height,facts +Gary,1,true,168.8,cool: true +Samantha\[aq]s Rabbit,2,false,-188.8,tall: indeed +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -p=csv --csv-auto-parse=f sample.csv +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- name: Gary + numberOfCats: 1 + likesApples: true + height: 168.8 + facts: \[aq]cool: true\[aq] +- name: Samantha\[aq]s Rabbit + numberOfCats: 2 + likesApples: false + height: -188.8 + facts: \[aq]tall: indeed\[aq] +\f[R] +.fi +.SS Parse TSV into an array of objects +.PP +First row is assumed to be the header row. +.PP +Given a sample.tsv file of: +.IP +.nf +\f[C] +name numberOfCats likesApples height +Gary 1 true 168.8 +Samantha\[aq]s Rabbit 2 false -188.8 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -p=tsv sample.tsv +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- name: Gary + numberOfCats: 1 + likesApples: true + height: 168.8 +- name: Samantha\[aq]s Rabbit + numberOfCats: 2 + likesApples: false + height: -188.8 +\f[R] +.fi +.SS Round trip +.PP +Given a sample.csv file of: +.IP +.nf +\f[C] +name,numberOfCats,likesApples,height +Gary,1,true,168.8 +Samantha\[aq]s Rabbit,2,false,-188.8 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -p=csv -o=csv \[aq](.[] | select(.name == \[dq]Gary\[dq]) | .numberOfCats) = 3\[aq] sample.csv +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +name,numberOfCats,likesApples,height +Gary,3,true,168.8 +Samantha\[aq]s Rabbit,2,false,-188.8 +\f[R] +.fi +.SH Formatting Expressions +.PP +\f[C]From version v4.41+\f[R] +.PP +You can put expressions into \f[C].yq\f[R] files, use whitespace and +comments to break up complex expressions and explain what\[cq]s going +on. +.SS Using expression files and comments +.PP +Note that you can execute the file directly - but make sure you make the +expression file executable. +.PP +Given a sample.yaml file of: +.IP +.nf +\f[C] +a: + b: old +\f[R] +.fi +.PP +And an `update.yq' expression file of: +.IP +.nf +\f[C] +#! yq + +# This is a yq expression that updates the map +# for several great reasons outlined here. + +\&.a.b = \[dq]new\[dq] # line comment here +| .a.c = \[dq]frog\[dq] + +# Now good things will happen. +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +\&./update.yq sample.yaml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: new + c: frog +\f[R] +.fi +.SS Flags in expression files +.PP +You can specify flags on the shebang line, this only works when +executing the file directly. +.PP +Given a sample.yaml file of: +.IP +.nf +\f[C] +a: + b: old +\f[R] +.fi +.PP +And an `update.yq' expression file of: +.IP +.nf +\f[C] +#! yq -oj + +# This is a yq expression that updates the map +# for several great reasons outlined here. + +\&.a.b = \[dq]new\[dq] # line comment here +| .a.c = \[dq]frog\[dq] + +# Now good things will happen. +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +\&./update.yq sample.yaml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +{ + \[dq]a\[dq]: { + \[dq]b\[dq]: \[dq]new\[dq], + \[dq]c\[dq]: \[dq]frog\[dq] + } +} +\f[R] +.fi +.SS Commenting out yq expressions +.PP +Note that \f[C]c\f[R] is no longer set to `frog'. +In this example we\[cq]re calling yq directly and passing the expression +file into \f[C]--from-file\f[R], this is no different from executing the +expression file directly. +.PP +Given a sample.yaml file of: +.IP +.nf +\f[C] +a: + b: old +\f[R] +.fi +.PP +And an `update.yq' expression file of: +.IP +.nf +\f[C] +#! yq +# This is a yq expression that updates the map +# for several great reasons outlined here. + +\&.a.b = \[dq]new\[dq] # line comment here +# | .a.c = \[dq]frog\[dq] + +# Now good things will happen. +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq --from-file update.yq sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: new +\f[R] +.fi +.SS Basic input example +.PP +Given a sample.lua file of: +.IP +.nf +\f[C] +return { + [\[dq]country\[dq]] = \[dq]Australia\[dq]; -- this place + [\[dq]cities\[dq]] = { + \[dq]Sydney\[dq], + \[dq]Melbourne\[dq], + \[dq]Brisbane\[dq], + \[dq]Perth\[dq], + }; +}; +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -oy \[aq].\[aq] sample.lua +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +country: Australia +cities: + - Sydney + - Melbourne + - Brisbane + - Perth +\f[R] +.fi +.SS Basic output example +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +--- +country: Australia # this place +cities: +- Sydney +- Melbourne +- Brisbane +- Perth +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=lua \[aq].\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +return { + [\[dq]country\[dq]] = \[dq]Australia\[dq]; -- this place + [\[dq]cities\[dq]] = { + \[dq]Sydney\[dq], + \[dq]Melbourne\[dq], + \[dq]Brisbane\[dq], + \[dq]Perth\[dq], + }; +}; +\f[R] +.fi +.SS Unquoted keys +.PP +Uses the \f[C]--lua-unquoted\f[R] option to produce a nicer-looking +output. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +--- +country: Australia # this place +cities: +- Sydney +- Melbourne +- Brisbane +- Perth +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=lua --lua-unquoted \[aq].\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +return { + country = \[dq]Australia\[dq]; -- this place + cities = { + \[dq]Sydney\[dq], + \[dq]Melbourne\[dq], + \[dq]Brisbane\[dq], + \[dq]Perth\[dq], + }; +}; +\f[R] +.fi +.SS Globals +.PP +Uses the \f[C]--lua-globals\f[R] option to export the values into the +global scope. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +--- +country: Australia # this place +cities: +- Sydney +- Melbourne +- Brisbane +- Perth +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=lua --lua-globals \[aq].\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +country = \[dq]Australia\[dq]; -- this place +cities = { + \[dq]Sydney\[dq], + \[dq]Melbourne\[dq], + \[dq]Brisbane\[dq], + \[dq]Perth\[dq], +}; +\f[R] +.fi +.SS Elaborate example +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +--- +hello: world +tables: + like: this + keys: values + ? look: non-string keys + : True +numbers: + - decimal: 12345 + - hex: 0x7fabc123 + - octal: 0o30 + - float: 123.45 + - infinity: .inf + plus_infinity: +.inf + minus_infinity: -.inf + - not: .nan +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=lua \[aq].\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +return { + [\[dq]hello\[dq]] = \[dq]world\[dq]; + [\[dq]tables\[dq]] = { + [\[dq]like\[dq]] = \[dq]this\[dq]; + [\[dq]keys\[dq]] = \[dq]values\[dq]; + [{ + [\[dq]look\[dq]] = \[dq]non-string keys\[dq]; + }] = true; + }; + [\[dq]numbers\[dq]] = { + { + [\[dq]decimal\[dq]] = 12345; + }, + { + [\[dq]hex\[dq]] = 0x7fabc123; + }, + { + [\[dq]octal\[dq]] = 24; + }, + { + [\[dq]float\[dq]] = 123.45; + }, + { + [\[dq]infinity\[dq]] = (1/0); + [\[dq]plus_infinity\[dq]] = (1/0); + [\[dq]minus_infinity\[dq]] = (-1/0); + }, + { + [\[dq]not\[dq]] = (0/0); + }, + }; +}; +\f[R] +.fi +.SH Properties +.PP +Encode/Decode/Roundtrip to/from a property file. +Line comments on value nodes will be copied across. +.PP +By default, empty maps and arrays are not encoded - see below for an +example on how to encode a value for these. +.SS Encode properties +.PP +Note that empty arrays and maps are not encoded by default. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +# block comments come through +person: # neither do comments on maps + name: Mike Wazowski # comments on values appear + pets: + - cat # comments on array values appear + - nested: + - list entry + food: [pizza] # comments on arrays do not +emptyArray: [] +emptyMap: [] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=props sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +# block comments come through +# comments on values appear +person.name = Mike Wazowski + +# comments on array values appear +person.pets.0 = cat +person.pets.1.nested.0 = list entry +person.food.0 = pizza +\f[R] +.fi +.SS Encode properties with array brackets +.PP +Declare the \[en]properties-array-brackets flag to give array paths in +brackets (e.g.\ SpringBoot). +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +# block comments come through +person: # neither do comments on maps + name: Mike Wazowski # comments on values appear + pets: + - cat # comments on array values appear + - nested: + - list entry + food: [pizza] # comments on arrays do not +emptyArray: [] +emptyMap: [] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=props --properties-array-brackets sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +# block comments come through +# comments on values appear +person.name = Mike Wazowski + +# comments on array values appear +person.pets[0] = cat +person.pets[1].nested[0] = list entry +person.food[0] = pizza +\f[R] +.fi +.SS Encode properties - custom separator +.PP +Use the \[en]properties-separator flag to specify your own key/value +separator. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +# block comments come through +person: # neither do comments on maps + name: Mike Wazowski # comments on values appear + pets: + - cat # comments on array values appear + - nested: + - list entry + food: [pizza] # comments on arrays do not +emptyArray: [] +emptyMap: [] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=props --properties-separator=\[dq] :\[at] \[dq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +# block comments come through +# comments on values appear +person.name :\[at] Mike Wazowski + +# comments on array values appear +person.pets.0 :\[at] cat +person.pets.1.nested.0 :\[at] list entry +person.food.0 :\[at] pizza +\f[R] +.fi +.SS Encode properties: scalar encapsulation +.PP +Note that string values with blank characters in them are encapsulated +with double quotes +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +# block comments come through +person: # neither do comments on maps + name: Mike Wazowski # comments on values appear + pets: + - cat # comments on array values appear + - nested: + - list entry + food: [pizza] # comments on arrays do not +emptyArray: [] +emptyMap: [] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=props --unwrapScalar=false sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +# block comments come through +# comments on values appear +person.name = \[dq]Mike Wazowski\[dq] + +# comments on array values appear +person.pets.0 = cat +person.pets.1.nested.0 = \[dq]list entry\[dq] +person.food.0 = pizza +\f[R] +.fi +.SS Encode properties: no comments +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +# block comments come through +person: # neither do comments on maps + name: Mike Wazowski # comments on values appear + pets: + - cat # comments on array values appear + - nested: + - list entry + food: [pizza] # comments on arrays do not +emptyArray: [] +emptyMap: [] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=props \[aq]... comments = \[dq]\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +person.name = Mike Wazowski +person.pets.0 = cat +person.pets.1.nested.0 = list entry +person.food.0 = pizza +\f[R] +.fi +.SS Encode properties: include empty maps and arrays +.PP +Use a yq expression to set the empty maps and sequences to your desired +value. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +# block comments come through +person: # neither do comments on maps + name: Mike Wazowski # comments on values appear + pets: + - cat # comments on array values appear + - nested: + - list entry + food: [pizza] # comments on arrays do not +emptyArray: [] +emptyMap: [] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=props \[aq](.. | select( (tag == \[dq]!!map\[dq] or tag ==\[dq]!!seq\[dq]) and length == 0)) = \[dq]\[dq]\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +# block comments come through +# comments on values appear +person.name = Mike Wazowski + +# comments on array values appear +person.pets.0 = cat +person.pets.1.nested.0 = list entry +person.food.0 = pizza +emptyArray = +emptyMap = +\f[R] +.fi +.SS Decode properties +.PP +Given a sample.properties file of: +.IP +.nf +\f[C] +# block comments come through +# comments on values appear +person.name = Mike Wazowski + +# comments on array values appear +person.pets.0 = cat +person.pets.1.nested.0 = list entry +person.food.0 = pizza +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -p=props sample.properties +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +person: + # block comments come through + # comments on values appear + name: Mike Wazowski + pets: + # comments on array values appear + - cat + - nested: + - list entry + food: + - pizza +\f[R] +.fi +.SS Decode properties: numbers +.PP +All values are assumed to be strings when parsing properties, but you +can use the \f[C]from_yaml\f[R] operator on all the strings values to +autoparse into the correct type. +.PP +Given a sample.properties file of: +.IP +.nf +\f[C] +a.b = 10 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -p=props \[aq] (.. | select(tag == \[dq]!!str\[dq])) |= from_yaml\[aq] sample.properties +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +a: + b: 10 +\f[R] +.fi +.SS Decode properties - array should be a map +.PP +If you have a numeric map key in your property files, use array_to_map +to convert them to maps. +.PP +Given a sample.properties file of: +.IP +.nf +\f[C] +things.10 = mike +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -p=props \[aq].things |= array_to_map\[aq] sample.properties +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +things: + 10: mike +\f[R] +.fi +.SS Roundtrip +.PP +Given a sample.properties file of: +.IP +.nf +\f[C] +# block comments come through +# comments on values appear +person.name = Mike Wazowski + +# comments on array values appear +person.pets.0 = cat +person.pets.1.nested.0 = list entry +person.food.0 = pizza +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -p=props -o=props \[aq].person.pets.0 = \[dq]dog\[dq]\[aq] sample.properties +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +# block comments come through +# comments on values appear +person.name = Mike Wazowski + +# comments on array values appear +person.pets.0 = dog +person.pets.1.nested.0 = list entry +person.food.0 = pizza +\f[R] +.fi +.SH Recipes +.PP +These examples are intended to show how you can use multiple operators +together so you get an idea of how you can perform complex data +manipulation. +.PP +Please see the details operator +docs (https://mikefarah.gitbook.io/yq/operators) for details on each +individual operator. +.SS Find items in an array +.PP +We have an array and we want to find the elements with a particular +name. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- name: Foo + numBuckets: 0 +- name: Bar + numBuckets: 0 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] | select(.name == \[dq]Foo\[dq])\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +name: Foo +numBuckets: 0 +\f[R] +.fi +.SS Explanation: +.IP \[bu] 2 +\f[C].[]\f[R] splats the array, and puts all the items in the context. +.IP \[bu] 2 +These items are then piped (\f[C]|\f[R]) into +\f[C]select(.name == \[dq]Foo\[dq])\f[R] which will select all the nodes +that have a name property set to `Foo'. +.IP \[bu] 2 +See the select (https://mikefarah.gitbook.io/yq/operators/select) +operator for more information. +.SS Find and update items in an array +.PP +We have an array and we want to \f[I]update\f[R] the elements with a +particular name. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- name: Foo + numBuckets: 0 +- name: Bar + numBuckets: 0 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq](.[] | select(.name == \[dq]Foo\[dq]) | .numBuckets) |= . + 1\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- name: Foo + numBuckets: 1 +- name: Bar + numBuckets: 0 +\f[R] +.fi +.SS Explanation: +.IP \[bu] 2 +Following from the example above\f[C].[]\f[R] splats the array, selects +filters the items. +.IP \[bu] 2 +We then pipe (\f[C]|\f[R]) that into \f[C].numBuckets\f[R], which will +select that field from all the matching items +.IP \[bu] 2 +Splat, select and the field are all in brackets, that whole expression +is passed to the \f[C]|=\f[R] operator as the left hand side expression, +with \f[C]. + 1\f[R] as the right hand side expression. +.IP \[bu] 2 +\f[C]|=\f[R] is the operator that updates fields relative to their own +value, which is referenced as dot (\f[C].\f[R]). +.IP \[bu] 2 +The expression \f[C]. + 1\f[R] increments the numBuckets counter. +.IP \[bu] 2 +See the assign (https://mikefarah.gitbook.io/yq/operators/assign-update) +and add (https://mikefarah.gitbook.io/yq/operators/add) operators for +more information. +.SS Deeply prune a tree +.PP +Say we are only interested in child1 and child2, and want to filter +everything else out. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +parentA: + - bob +parentB: + child1: i am child1 + child3: hiya +parentC: + childX: cool + child2: me child2 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]( + .. | # recurse through all the nodes + select(has(\[dq]child1\[dq]) or has(\[dq]child2\[dq])) | # match parents that have either child1 or child2 + (.child1, .child2) | # select those children + select(.) # filter out nulls +) as $i ireduce({}; # using that set of nodes, create a new result map + setpath($i | path; $i) # and put in each node, using its original path +)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +parentB: + child1: i am child1 +parentC: + child2: me child2 +\f[R] +.fi +.SS Explanation: +.IP \[bu] 2 +Find all the matching child1 and child2 nodes +.IP \[bu] 2 +Using ireduce, create a new map using just those nodes +.IP \[bu] 2 +Set each node into the new map using its original path +.SS Multiple or complex updates to items in an array +.PP +We have an array and we want to \f[I]update\f[R] the elements with a +particular name in reference to its type. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +myArray: + - name: Foo + type: cat + - name: Bar + type: dog +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq]with(.myArray[]; .name = .name + \[dq] - \[dq] + .type)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +myArray: + - name: Foo - cat + type: cat + - name: Bar - dog + type: dog +\f[R] +.fi +.SS Explanation: +.IP \[bu] 2 +The with operator will effectively loop through each given item in the +first given expression, and run the second expression against it. +.IP \[bu] 2 +\f[C].myArray[]\f[R] splats the array in \f[C]myArray\f[R]. +So \f[C]with\f[R] will run against each item in that array +.IP \[bu] 2 +\f[C].name = .name + \[dq] - \[dq] + .type\f[R] this expression is run +against every item, updating the name to be a concatenation of the +original name as well as the type. +.IP \[bu] 2 +See the with (https://mikefarah.gitbook.io/yq/operators/with) operator +for more information and examples. +.SS Sort an array by a field +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +myArray: + - name: Foo + numBuckets: 1 + - name: Bar + numBuckets: 0 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].myArray |= sort_by(.numBuckets)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +myArray: + - name: Bar + numBuckets: 0 + - name: Foo + numBuckets: 1 +\f[R] +.fi +.SS Explanation: +.IP \[bu] 2 +We want to resort \f[C].myArray\f[R]. +.IP \[bu] 2 +\f[C]sort_by\f[R] works by piping an array into it, and it pipes out a +sorted array. +.IP \[bu] 2 +So, we use \f[C]|=\f[R] to update \f[C].myArray\f[R]. +This is the same as doing +\f[C].myArray = (.myArray | sort_by(.numBuckets))\f[R] +.SS Filter, flatten, sort and unique +.PP +Lets find the unique set of names from the document. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +- type: foo + names: + - Fred + - Catherine +- type: bar + names: + - Zelda +- type: foo + names: Fred +- type: foo + names: Ava +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq][.[] | select(.type == \[dq]foo\[dq]) | .names] | flatten | sort | unique\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- Ava +- Catherine +- Fred +\f[R] +.fi +.SS Explanation: +.IP \[bu] 2 +\f[C].[] | select(.type == \[dq]foo\[dq]) | .names\f[R] will select the +array elements of type \[lq]foo\[rq] +.IP \[bu] 2 +Splat \f[C].[]\f[R] will unwrap the array and match all the items. +We need to do this so we can work on the child items, for instance, +filter items out using the \f[C]select\f[R] operator. +.IP \[bu] 2 +But we still want the final results back into an array. +So after we\[cq]re doing working on the children, we wrap everything +back into an array using square brackets around the expression. +\f[C][.[] | select(.type == \[dq]foo\[dq]) | .names]\f[R] +.IP \[bu] 2 +Now have have an array of all the `names' values. +Which includes arrays of strings as well as strings on their own. +.IP \[bu] 2 +Pipe \f[C]|\f[R] this array through \f[C]flatten\f[R]. +This will flatten nested arrays. +So now we have a flat list of all the name value strings +.IP \[bu] 2 +Next we pipe \f[C]|\f[R] that through \f[C]sort\f[R] and then +\f[C]unique\f[R] to get a sorted, unique list of the names! +.IP \[bu] 2 +See the flatten (https://mikefarah.gitbook.io/yq/operators/flatten), +sort (https://mikefarah.gitbook.io/yq/operators/sort) and +unique (https://mikefarah.gitbook.io/yq/operators/unique) for more +information and examples. +.SS Export as environment variables (script), or any custom format +.PP +Given a yaml document, lets output a script that will configure +environment variables with that data. +This same approach can be used for exporting into custom formats. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +var0: string0 +var1: string1 +fruit: + - apple + - banana + - peach +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].[] |( + ( select(kind == \[dq]scalar\[dq]) | key + \[dq]=\[aq]\[rs]\[aq]\[aq]\[dq] + . + \[dq]\[aq]\[rs]\[aq]\[aq]\[dq]), + ( select(kind == \[dq]seq\[dq]) | key + \[dq]=(\[dq] + (map(\[dq]\[aq]\[rs]\[aq]\[aq]\[dq] + . + \[dq]\[aq]\[rs]\[aq]\[aq]\[dq]) | join(\[dq],\[dq])) + \[dq])\[dq]) +)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +var0=\[aq]string0\[aq] +var1=\[aq]string1\[aq] +fruit=(\[aq]apple\[aq],\[aq]banana\[aq],\[aq]peach\[aq]) +\f[R] +.fi +.SS Explanation: +.IP \[bu] 2 +\f[C].[]\f[R] matches all top level elements +.IP \[bu] 2 +We need a string expression for each of the different types that will +produce the bash syntax, we\[cq]ll use the union operator, to join them +together +.IP \[bu] 2 +Scalars, we just need the key and quoted value: +\f[C]( select(kind == \[dq]scalar\[dq]) | key + \[dq]=\[aq]\[dq] + . + \[dq]\[aq]\[dq])\f[R] +.IP \[bu] 2 +Sequences (or arrays) are trickier, we need to quote each value and +\f[C]join\f[R] them with \f[C],\f[R]: +\f[C]map(\[dq]\[aq]\[dq] + . + \[dq]\[aq]\[dq]) | join(\[dq],\[dq])\f[R] +.SS Custom format with nested data +.PP +Like the previous example, but lets handle nested data structures. +In this custom example, we\[cq]re going to join the property paths with +_. +The important thing to keep in mind is that our expression is not +recursive (despite the data structure being so). +Instead we match \f[I]all\f[R] elements on the tree and operate on them. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +simple: string0 +simpleArray: + - apple + - banana + - peach +deep: + property: value + array: + - cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].. |( + ( select(kind == \[dq]scalar\[dq] and parent | kind != \[dq]seq\[dq]) | (path | join(\[dq]_\[dq])) + \[dq]=\[aq]\[rs]\[aq]\[aq]\[dq] + . + \[dq]\[aq]\[rs]\[aq]\[aq]\[dq]), + ( select(kind == \[dq]seq\[dq]) | (path | join(\[dq]_\[dq])) + \[dq]=(\[dq] + (map(\[dq]\[aq]\[rs]\[aq]\[aq]\[dq] + . + \[dq]\[aq]\[rs]\[aq]\[aq]\[dq]) | join(\[dq],\[dq])) + \[dq])\[dq]) +)\[aq] sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +simple=\[aq]string0\[aq] +deep_property=\[aq]value\[aq] +simpleArray=(\[aq]apple\[aq],\[aq]banana\[aq],\[aq]peach\[aq]) +deep_array=(\[aq]cat\[aq]) +\f[R] +.fi +.SS Explanation: +.IP \[bu] 2 +You\[cq]ll need to understand how the previous example works to +understand this extension. +.IP \[bu] 2 +\f[C]..\f[R] matches \f[I]all\f[R] elements, instead of \f[C].[]\f[R] +from the previous example that just matches top level elements. +.IP \[bu] 2 +Like before, we need a string expression for each of the different types +that will produce the bash syntax, we\[cq]ll use the union operator, to +join them together +.IP \[bu] 2 +This time, however, our expression matches every node in the data +structure. +.IP \[bu] 2 +We only want to print scalars that are not in arrays (because we handle +the separately), so well add +\f[C]and parent | kind != \[dq]seq\[dq]\f[R] to the select operator +expression for scalars +.IP \[bu] 2 +We don\[cq]t just want the key any more, we want the full path. +So instead of \f[C]key\f[R] we have \f[C]path | join(\[dq]_\[dq])\f[R] +.IP \[bu] 2 +The expression for sequences follows the same logic +.SS Encode shell variables +.PP +Note that comments are dropped and values will be enclosed in single +quotes as needed. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +# comment +name: Mike Wazowski +eyes: + color: turquoise + number: 1 +friends: + - James P. Sullivan + - Celia Mae +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=shell sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +name=\[aq]Mike Wazowski\[aq] +eyes_color=turquoise +eyes_number=1 +friends_0=\[aq]James P. Sullivan\[aq] +friends_1=\[aq]Celia Mae\[aq] +\f[R] +.fi +.SS Encode shell variables: illegal variable names as key. +.PP +Keys that would be illegal as variable keys are adapted. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +ascii_=_symbols: replaced with _ +\[dq]ascii_ _controls\[dq]: dropped (this example uses \[rs]t) +nonascii_\[u05D0]_characters: dropped +effort_expe\[~n]ded_t\[`o]_preserve_accented_latin_letters: moderate (via unicode NFKD) +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=shell sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +ascii___symbols=\[aq]replaced with _\[aq] +ascii__controls=\[aq]dropped (this example uses \[rs]t)\[aq] +nonascii__characters=dropped +effort_expended_to_preserve_accented_latin_letters=\[aq]moderate (via unicode NFKD)\[aq] +\f[R] +.fi +.SS Encode shell variables: empty values, arrays and maps +.PP +Empty values are encoded to empty variables, but empty arrays and maps +are skipped. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +empty: + value: + array: [] + map: {} +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=shell sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +empty_value= +\f[R] +.fi +.SS Encode shell variables: single quotes in values +.PP +Single quotes in values are encoded as `\[lq]'\[lq]\[cq] (close single +quote, double-quoted single quote, open single quote). +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +name: Miles O\[aq]Brien +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=shell sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +name=\[aq]Miles O\[aq]\[dq]\[aq]\[dq]\[aq]Brien\[aq] +\f[R] +.fi +.SH TOML +.PP +Decode from TOML. +Note that \f[C]yq\f[R] does not yet support outputting in TOML format +(and therefore it cannot roundtrip) +.SS Parse: Simple +.PP +Given a sample.toml file of: +.IP +.nf +\f[C] +A = \[dq]hello\[dq] +B = 12 +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -oy \[aq].\[aq] sample.toml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +A: hello +B: 12 +\f[R] +.fi +.SS Parse: Deep paths +.PP +Given a sample.toml file of: +.IP +.nf +\f[C] +person.name = \[dq]hello\[dq] +person.address = \[dq]12 cat st\[dq] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -oy \[aq].\[aq] sample.toml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +person: + name: hello + address: 12 cat st +\f[R] +.fi +.SS Encode: Scalar +.PP +Given a sample.toml file of: +.IP +.nf +\f[C] +person.name = \[dq]hello\[dq] +person.address = \[dq]12 cat st\[dq] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].person.name\[aq] sample.toml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +hello +\f[R] +.fi +.SS Parse: inline table +.PP +Given a sample.toml file of: +.IP +.nf +\f[C] +name = { first = \[dq]Tom\[dq], last = \[dq]Preston-Werner\[dq] } +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -oy \[aq].\[aq] sample.toml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +name: + first: Tom + last: Preston-Werner +\f[R] +.fi +.SS Parse: Array Table +.PP +Given a sample.toml file of: +.IP +.nf +\f[C] +[owner.contact] +name = \[dq]Tom Preston-Werner\[dq] +age = 36 + +[[owner.addresses]] +street = \[dq]first street\[dq] +suburb = \[dq]ok\[dq] + +[[owner.addresses]] +street = \[dq]second street\[dq] +suburb = \[dq]nice\[dq] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -oy \[aq].\[aq] sample.toml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +owner: + contact: + name: Tom Preston-Werner + age: 36 + addresses: + - street: first street + suburb: ok + - street: second street + suburb: nice +\f[R] +.fi +.SS Parse: Empty Table +.PP +Given a sample.toml file of: +.IP +.nf +\f[C] +[dependencies] +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -oy \[aq].\[aq] sample.toml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +dependencies: {} +\f[R] +.fi +.SH XML +.PP +Encode and decode to and from XML. +Whitespace is not conserved for round trips - but the order of the +fields are. +.PP +Consecutive xml nodes with the same name are assumed to be arrays. +.PP +XML content data, attributes processing instructions and directives are +all created as plain fields. +.PP +This can be controlled by: +.PP +.TS +tab(@); +l l l. +T{ +Flag +T}@T{ +Default +T}@T{ +Sample XML +T} +_ +T{ +\f[C]--xml-attribute-prefix\f[R] +T}@T{ +\f[C]+\f[R] (changing to \f[C]+\[at]\f[R] soon) +T}@T{ +Legs in \f[C]\f[R] +T} +T{ +\f[C]--xml-content-name\f[R] +T}@T{ +\f[C]+content\f[R] +T}@T{ +Meow in \f[C]Meow true\f[R] +T} +T{ +\f[C]--xml-directive-name\f[R] +T}@T{ +\f[C]+directive\f[R] +T}@T{ +\f[C]\f[R] +T} +T{ +\f[C]--xml-proc-inst-prefix\f[R] +T}@T{ +\f[C]+p_\f[R] +T}@T{ +\f[C]\f[R] +T} +.TE +.PP +{% hint style=\[lq]warning\[rq] %} Default Attribute Prefix will be +changing in v4.30! In order to avoid name conflicts (e.g.\ having an +attribute named \[lq]content\[rq] will create a field that clashes with +the default content name of \[lq]+content\[rq]) the attribute prefix +will be changing to \[lq]+\[at]\[rq]. +.PP +This will affect users that have not set their own prefix and are not +roundtripping XML changes. +.PP +{% endhint %} +.SS Encoder / Decoder flag options +.PP +In addition to the above flags, there are the following xml +encoder/decoder options controlled by flags: +.PP +.TS +tab(@); +lw(23.3n) lw(23.3n) lw(23.3n). +T{ +Flag +T}@T{ +Default +T}@T{ +Description +T} +_ +T{ +\f[C]--xml-strict-mode\f[R] +T}@T{ +false +T}@T{ +Strict mode enforces the requirements of the XML specification. +When switched off the parser allows input containing common mistakes. +See the Golang xml decoder (https://pkg.go.dev/encoding/xml#Decoder) for +more details. +T} +T{ +\f[C]--xml-keep-namespace\f[R] +T}@T{ +true +T}@T{ +Keeps the namespace of attributes +T} +T{ +\f[C]--xml-raw-token\f[R] +T}@T{ +true +T}@T{ +Does not verify that start and end elements match and does not translate +name space prefixes to their corresponding URLs. +T} +T{ +\f[C]--xml-skip-proc-inst\f[R] +T}@T{ +false +T}@T{ +Skips over processing instructions, +e.g.\ \f[C]\f[R] +T} +T{ +\f[C]--xml-skip-directives\f[R] +T}@T{ +false +T}@T{ +Skips over directives, +e.g.\ \f[C]\f[R] +T} +.TE +.PP +See below for examples +.SS Parse xml: simple +.PP +Notice how all the values are strings, see the next example on how you +can fix that. +.PP +Given a sample.xml file of: +.IP +.nf +\f[C] + + + meow + 4 + true + +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -oy \[aq].\[aq] sample.xml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] ++p_xml: version=\[dq]1.0\[dq] encoding=\[dq]UTF-8\[dq] +cat: + says: meow + legs: \[dq]4\[dq] + cute: \[dq]true\[dq] +\f[R] +.fi +.SS Parse xml: number +.PP +All values are assumed to be strings when parsing XML, but you can use +the \f[C]from_yaml\f[R] operator on all the strings values to autoparse +into the correct type. +.PP +Given a sample.xml file of: +.IP +.nf +\f[C] + + + meow + 4 + true + +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -oy \[aq] (.. | select(tag == \[dq]!!str\[dq])) |= from_yaml\[aq] sample.xml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] ++p_xml: version=\[dq]1.0\[dq] encoding=\[dq]UTF-8\[dq] +cat: + says: meow + legs: 4 + cute: true +\f[R] +.fi +.SS Parse xml: array +.PP +Consecutive nodes with identical xml names are assumed to be arrays. +.PP +Given a sample.xml file of: +.IP +.nf +\f[C] + +cat +goat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -oy \[aq].\[aq] sample.xml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] ++p_xml: version=\[dq]1.0\[dq] encoding=\[dq]UTF-8\[dq] +animal: + - cat + - goat +\f[R] +.fi +.SS Parse xml: force as an array +.PP +In XML, if your array has a single item, then yq doesn\[cq]t know its an +array. +This is how you can consistently force it to be an array. +This handles the 3 scenarios of having nothing in the array, having a +single item and having multiple. +.PP +Given a sample.xml file of: +.IP +.nf +\f[C] +cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -oy \[aq].zoo.animal |= ([] + .)\[aq] sample.xml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +zoo: + animal: + - cat +\f[R] +.fi +.SS Parse xml: force all as an array +.PP +Given a sample.xml file of: +.IP +.nf +\f[C] +boing +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -oy \[aq].. |= [] + .\[aq] sample.xml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +- zoo: + - thing: + - frog: + - boing +\f[R] +.fi +.SS Parse xml: attributes +.PP +Attributes are converted to fields, with the default attribute prefix +`+'. +Use \[cq]\[en]xml-attribute-prefix\[ga] to set your own. +.PP +Given a sample.xml file of: +.IP +.nf +\f[C] + + + 7 + +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -oy \[aq].\[aq] sample.xml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] ++p_xml: version=\[dq]1.0\[dq] encoding=\[dq]UTF-8\[dq] +cat: + +\[at]legs: \[dq]4\[dq] + legs: \[dq]7\[dq] +\f[R] +.fi +.SS Parse xml: attributes with content +.PP +Content is added as a field, using the default content name of +\f[C]+content\f[R]. +Use \f[C]--xml-content-name\f[R] to set your own. +.PP +Given a sample.xml file of: +.IP +.nf +\f[C] + +meow +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -oy \[aq].\[aq] sample.xml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] ++p_xml: version=\[dq]1.0\[dq] encoding=\[dq]UTF-8\[dq] +cat: + +content: meow + +\[at]legs: \[dq]4\[dq] +\f[R] +.fi +.SS Parse xml: content split between comments/children +.PP +Multiple content texts are collected into a sequence. +.PP +Given a sample.xml file of: +.IP +.nf +\f[C] + value anotherValue frog cool! +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -oy \[aq].\[aq] sample.xml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +root: + +content: # comment + - value + - anotherValue + - cool! + a: frog +\f[R] +.fi +.SS Parse xml: custom dtd +.PP +DTD entities are processed as directives. +.PP +Given a sample.xml file of: +.IP +.nf +\f[C] + + + +]> + + &writer;©right; + +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].\[aq] sample.xml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] + + + +]> + + &writer;&copyright; + +\f[R] +.fi +.SS Parse xml: skip custom dtd +.PP +DTDs are directives, skip over directives to skip DTDs. +.PP +Given a sample.xml file of: +.IP +.nf +\f[C] + + + +]> + + &writer;©right; + +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq --xml-skip-directives \[aq].\[aq] sample.xml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] + + + &writer;&copyright; + +\f[R] +.fi +.SS Parse xml: with comments +.PP +A best attempt is made to preserve comments. +.PP +Given a sample.xml file of: +.IP +.nf +\f[C] + + + + 3 + + + + z + + + + + + +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -oy \[aq].\[aq] sample.xml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +# before cat +cat: + # in cat before + x: \[dq]3\[dq] # multi + # line comment + # for x + # before y + + y: + # in y before + # in d before + d: z # in d after + # in y after + # in_cat_after +# after cat +\f[R] +.fi +.SS Parse xml: keep attribute namespace +.PP +Defaults to true +.PP +Given a sample.xml file of: +.IP +.nf +\f[C] + + +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq --xml-keep-namespace=false \[aq].\[aq] sample.xml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] + + +\f[R] +.fi +.PP +instead of +.IP +.nf +\f[C] + + +\f[R] +.fi +.SS Parse xml: keep raw attribute namespace +.PP +Defaults to true +.PP +Given a sample.xml file of: +.IP +.nf +\f[C] + + +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq --xml-raw-token=false \[aq].\[aq] sample.xml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] + + +\f[R] +.fi +.PP +instead of +.IP +.nf +\f[C] + + +\f[R] +.fi +.SS Encode xml: simple +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +cat: purrs +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=xml sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +purrs +\f[R] +.fi +.SS Encode xml: array +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +pets: + cat: + - purrs + - meows +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=xml sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] + + purrs + meows + +\f[R] +.fi +.SS Encode xml: attributes +.PP +Fields with the matching xml-attribute-prefix are assumed to be +attributes. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +cat: + +\[at]name: tiger + meows: true +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=xml sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] + + true + +\f[R] +.fi +.SS Encode xml: attributes with content +.PP +Fields with the matching xml-content-name is assumed to be content. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +cat: + +\[at]name: tiger + +content: cool +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=xml sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] +cool +\f[R] +.fi +.SS Encode xml: comments +.PP +A best attempt is made to copy comments to xml. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] +# +# header comment +# above_cat +# +cat: # inline_cat + # above_array + array: # inline_array + - val1 # inline_val1 + # above_val2 + - val2 # inline_val2 +# below_cat +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=xml sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] + + + + val1 + val2 + +\f[R] +.fi +.SS Encode: doctype and xml declaration +.PP +Use the special xml names to add/modify proc instructions and +directives. +.PP +Given a sample.yml file of: +.IP +.nf +\f[C] ++p_xml: version=\[dq]1.0\[dq] ++directive: \[aq]DOCTYPE config SYSTEM \[dq]/etc/iwatch/iwatch.dtd\[dq] \[aq] +apple: + +p_coolioo: version=\[dq]1.0\[dq] + +directive: \[aq]CATYPE meow purr puss \[aq] + b: things +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq -o=xml sample.yml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] + + + + things + +\f[R] +.fi +.SS Round trip: with comments +.PP +A best effort is made, but comment positions and white space are not +preserved perfectly. +.PP +Given a sample.xml file of: +.IP +.nf +\f[C] + + + + 3 + + + + z + + + + + + +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].\[aq] sample.xml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] + + + 3 + + z + + +\f[R] +.fi +.SS Roundtrip: with doctype and declaration +.PP +yq parses XML proc instructions and directives into nodes. +Unfortunately the underlying XML parser loses whitespace information. +.PP +Given a sample.xml file of: +.IP +.nf +\f[C] + + + + + + things + +\f[R] +.fi +.PP +then +.IP +.nf +\f[C] +yq \[aq].\[aq] sample.xml +\f[R] +.fi +.PP +will output +.IP +.nf +\f[C] + + + + things + +\f[R] +.fi +.SH AUTHORS +Mike Farah. diff --git a/backing-services/grafana/.helmignore b/backing-services/grafana/.helmignore new file mode 100644 index 0000000..f0c1319 --- /dev/null +++ b/backing-services/grafana/.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/backing-services/grafana/Chart.lock b/backing-services/grafana/Chart.lock new file mode 100644 index 0000000..4dc1279 --- /dev/null +++ b/backing-services/grafana/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + version: 2.14.0 +digest: sha256:48db3c388ecbd5be84bd65f85c2247c466c99cbe3badaa1e7b4e1ce5814d8149 +generated: "2023-12-19T17:49:07.683877863Z" diff --git a/backing-services/grafana/Chart.yaml b/backing-services/grafana/Chart.yaml new file mode 100644 index 0000000..09a9459 --- /dev/null +++ b/backing-services/grafana/Chart.yaml @@ -0,0 +1,34 @@ +# Copyright VMware, Inc. +# SPDX-License-Identifier: APACHE-2.0 + +annotations: + category: Analytics + licenses: Apache-2.0 + images: | + - name: grafana + image: docker.io/bitnami/grafana:10.2.3-debian-11-r0 + - name: os-shell + image: docker.io/bitnami/os-shell:11-debian-11-r92 +apiVersion: v2 +appVersion: 10.2.3 +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + tags: + - bitnami-common + version: 2.x.x +description: Grafana is an open source metric analytics and visualization suite for visualizing time series data that supports various types of data sources. +home: https://bitnami.com +icon: https://bitnami.com/assets/stacks/grafana/img/grafana-stack-220x234.png +keywords: +- analytics +- monitoring +- metrics +- logs +maintainers: +- name: VMware, Inc. + url: https://github.com/bitnami/charts +name: grafana +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/grafana +version: 9.6.6 diff --git a/backing-services/grafana/README.md b/backing-services/grafana/README.md new file mode 100644 index 0000000..2ed2ec1 --- /dev/null +++ b/backing-services/grafana/README.md @@ -0,0 +1,715 @@ + + +# Bitnami package for Grafana + +Grafana is an open source metric analytics and visualization suite for visualizing time series data that supports various types of data sources. + +[Overview of Grafana](https://grafana.com/) + +Trademarks: This software listing is packaged by Bitnami. The respective trademarks mentioned in the offering are owned by the respective companies, and use of them does not imply any affiliation or endorsement. + +## TL;DR + +```console +helm install my-release oci://registry-1.docker.io/bitnamicharts/grafana +``` + +Looking to use Grafana in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the enterprise edition of Bitnami Application Catalog. + +## Introduction + +This chart bootstraps a [grafana](https://github.com/bitnami/containers/tree/main/bitnami/grafana) deployment on a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ +- PV provisioner support in the underlying infrastructure +- ReadWriteMany volumes for deployment scaling + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```console +helm install my-release oci://REGISTRY_NAME/REPOSITORY_NAME/grafana +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +These commands deploy grafana 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. Use the option `--purge` to delete all persistent volumes too. + +## Differences between the Bitnami Grafana chart and the Bitnami Grafana Operator chart + +In the Bitnami catalog we offer both the bitnami/grafana and bitnami/grafana-operator charts. Each solution covers different needs and use cases. + +The *bitnami/grafana* chart deploys a single Grafana installation using a Kubernetes Deployment object (together with Services, PVCs, ConfigMaps, etc.). The figure below shows the deployed objects in the cluster after executing *helm install*: + +```text + +--------------+ +-----+ + | | | | + Service & Ingress | Grafana +<------------+ PVC | +<-------------------+ | | | + | Deployment | +-----+ + | | + +-----------+--+ + ^ +------------+ + | | | + +----------------+ Configmaps | + | Secrets | + | | + +------------+ + +``` + +Its lifecycle is managed using Helm and, at the Grafana container level, the following operations are automated: persistence management, configuration based on environment variables and plugin initialization. The chart also allows deploying dashboards and data sources using ConfigMaps. The Deployments do not require any ServiceAccounts with special RBAC privileges so this solution would fit better in more restricted Kubernetes installations. + +The *bitnami/grafana-operator* chart deploys a Grafana Operator installation using a Kubernetes Deployment. The figure below shows the Grafana operator deployment after executing *helm install*: + +```text ++--------------------+ +| | +---------------+ +| Grafana Operator | | | +| | | RBAC | +| Deployment | | Privileges | +| | | | ++-------+------------+ +-------+-------+ + ^ | + | +-----------------+ | + +---+ Service Account +<----+ + +-----------------+ +``` + +The operator will extend the Kubernetes API with the following objects: *Grafana*, *GrafanaDashboards* and *GrafanaDataSources*. From that moment, the user will be able to deploy objects of these kinds and the previously deployed Operator will take care of deploying all the required Deployments, ConfigMaps and Services for running a Grafana instance. Its lifecycle is managed using *kubectl* on the Grafana, GrafanaDashboards and GrafanaDataSource objects. The following figure shows the deployed objects after + deploying a *Grafana* object using *kubectl*: + +```text ++--------------------+ +| | +---------------+ +| Grafana Operator | | | +| | | RBAC | +| Deployment | | Privileges | +| | | | ++--+----+------------+ +-------+-------+ + | ^ | + | | +-----------------+ | + | +---+ Service Account +<----+ + | +-----------------+ + | + | + | + | + | Grafana + | +---------------------------------------------------------------------------+ + | | | + | | +--------------+ +-----+ | + | | | | | | | + +-------------------->+ Service & Ingress | Grafana +<------------+ PVC | | + | <-------------------+ | | | | + | | Deployment | +-----+ | + | | | | + | +-----------+--+ | + | ^ +------------+ | + | | | | | + | +----------------+ Configmaps | | + | | Secrets | | + | | | | + | +------------+ | + | | + +---------------------------------------------------------------------------+ + +``` + +This solution allows to easily deploy multiple Grafana instances compared to the *bitnami/grafana* chart. As the operator automatically deploys Grafana installations, the Grafana Operator pods will require a ServiceAccount with privileges to create and destroy mulitple Kubernetes objects. This may be problematic for Kubernetes clusters with strict role-based access policies. + +## Parameters + +### Global parameters + +| Name | Description | Value | +| ------------------------- | ----------------------------------------------- | ----- | +| `global.imageRegistry` | Global Docker image registry | `""` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | +| `global.storageClass` | Global StorageClass for Persistent Volume(s) | `""` | + +### Common parameters + +| Name | Description | Value | +| ------------------- | --------------------------------------------------------------------------------------- | --------------- | +| `kubeVersion` | Force target Kubernetes version (using Helm capabilities if not set) | `""` | +| `extraDeploy` | Array of extra objects to deploy with the release | `[]` | +| `nameOverride` | String to partially override grafana.fullname template (will maintain the release name) | `""` | +| `fullnameOverride` | String to fully override grafana.fullname template | `""` | +| `clusterDomain` | Default Kubernetes cluster domain | `cluster.local` | +| `commonLabels` | Labels to add to all deployed objects | `{}` | +| `commonAnnotations` | Annotations to add to all deployed objects | `{}` | + +### Grafana parameters + +| Name | Description | Value | +| ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- | +| `image.registry` | Grafana image registry | `REGISTRY_NAME` | +| `image.repository` | Grafana image repository | `REPOSITORY_NAME/grafana` | +| `image.digest` | Grafana image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `image.pullPolicy` | Grafana image pull policy | `IfNotPresent` | +| `image.pullSecrets` | Grafana image pull secrets | `[]` | +| `admin.user` | Grafana admin username | `admin` | +| `admin.password` | Admin password. If a password is not provided a random password will be generated | `""` | +| `admin.existingSecret` | Name of the existing secret containing admin password | `""` | +| `admin.existingSecretPasswordKey` | Password key on the existing secret | `password` | +| `smtp.enabled` | Enable SMTP configuration | `false` | +| `smtp.user` | SMTP user | `user` | +| `smtp.password` | SMTP password | `password` | +| `smtp.host` | Custom host for the smtp server | `""` | +| `smtp.fromAddress` | From address | `""` | +| `smtp.fromName` | From name | `""` | +| `smtp.skipVerify` | Enable skip verify | `false` | +| `smtp.existingSecret` | Name of existing secret containing SMTP credentials (user and password) | `""` | +| `smtp.existingSecretUserKey` | User key on the existing secret | `user` | +| `smtp.existingSecretPasswordKey` | Password key on the existing secret | `password` | +| `plugins` | Grafana plugins to be installed in deployment time separated by commas | `""` | +| `ldap.enabled` | Enable LDAP for Grafana | `false` | +| `ldap.allowSignUp` | Allows LDAP sign up for Grafana | `false` | +| `ldap.configuration` | Specify content for ldap.toml configuration file | `""` | +| `ldap.configMapName` | Name of the ConfigMap with the ldap.toml configuration file for Grafana | `""` | +| `ldap.secretName` | Name of the Secret with the ldap.toml configuration file for Grafana | `""` | +| `ldap.uri` | Server URI, eg. ldap://ldap_server:389 | `""` | +| `ldap.binddn` | DN of the account used to search in the LDAP server. | `""` | +| `ldap.bindpw` | Password for binddn account. | `""` | +| `ldap.basedn` | Base DN path where binddn account will search for the users. | `""` | +| `ldap.searchAttribute` | Field used to match with the user name (uid, samAccountName, cn, etc). This value will be ignored if 'ldap.searchFilter' is set | `uid` | +| `ldap.searchFilter` | User search filter, for example "(cn=%s)" or "(sAMAccountName=%s)" or "(|(sAMAccountName=%s)(userPrincipalName=%s)" | `""` | +| `ldap.extraConfiguration` | Extra ldap configuration. | `""` | +| `ldap.tls.enabled` | Enabled TLS configuration. | `false` | +| `ldap.tls.startTls` | Use STARTTLS instead of LDAPS. | `false` | +| `ldap.tls.skipVerify` | Skip any SSL verification (hostanames or certificates) | `false` | +| `ldap.tls.certificatesMountPath` | Where LDAP certifcates are mounted. | `/opt/bitnami/grafana/conf/ldap/` | +| `ldap.tls.certificatesSecret` | Secret with LDAP certificates. | `""` | +| `ldap.tls.CAFilename` | CA certificate filename. Should match with the CA entry key in the ldap.tls.certificatesSecret. | `""` | +| `ldap.tls.certFilename` | Client certificate filename to authenticate against the LDAP server. Should match with certificate the entry key in the ldap.tls.certificatesSecret. | `""` | +| `ldap.tls.certKeyFilename` | Client Key filename to authenticate against the LDAP server. Should match with certificate the entry key in the ldap.tls.certificatesSecret. | `""` | +| `imageRenderer.enabled` | Enable using a remote rendering service to render PNG images | `false` | +| `imageRenderer.serverURL` | URL of the remote rendering service | `""` | +| `imageRenderer.callbackURL` | URL of the callback service | `""` | +| `config.useGrafanaIniFile` | Allows to load a `grafana.ini` file | `false` | +| `config.grafanaIniConfigMap` | Name of the ConfigMap containing the `grafana.ini` file | `""` | +| `config.grafanaIniSecret` | Name of the Secret containing the `grafana.ini` file | `""` | +| `dashboardsProvider.enabled` | Enable the use of a Grafana dashboard provider | `false` | +| `dashboardsProvider.configMapName` | Name of a ConfigMap containing a custom dashboard provider | `""` | +| `dashboardsConfigMaps` | Array with the names of a series of ConfigMaps containing dashboards files | `[]` | +| `datasources.secretName` | The name of an externally-managed secret containing custom datasource files. | `""` | +| `datasources.secretDefinition` | The contents of a secret defining a custom datasource file. Only used if datasources.secretName is empty or not defined. | `{}` | +| `notifiers.configMapName` | Name of a ConfigMap containing Grafana notifiers configuration | `""` | +| `alerting.configMapName` | Name of a ConfigMap containing Grafana alerting configuration | `""` | + +### Grafana Deployment parameters + +| Name | Description | Value | +| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ---------------- | +| `grafana.replicaCount` | Number of Grafana nodes | `1` | +| `grafana.updateStrategy.type` | Set up update strategy for Grafana installation. | `RollingUpdate` | +| `grafana.hostAliases` | Add deployment host aliases | `[]` | +| `grafana.schedulerName` | Alternative scheduler | `""` | +| `grafana.terminationGracePeriodSeconds` | In seconds, time the given to the Grafana pod needs to terminate gracefully | `""` | +| `grafana.priorityClassName` | Priority class name | `""` | +| `grafana.podLabels` | Extra labels for Grafana pods | `{}` | +| `grafana.podAnnotations` | Grafana Pod annotations | `{}` | +| `grafana.podAffinityPreset` | Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `grafana.podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `grafana.containerPorts.grafana` | Grafana container port | `3000` | +| `grafana.extraPorts` | Extra ports for Grafana deployment | `[]` | +| `grafana.nodeAffinityPreset.type` | Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `grafana.nodeAffinityPreset.key` | Node label key to match Ignored if `affinity` is set. | `""` | +| `grafana.nodeAffinityPreset.values` | Node label values to match. Ignored if `affinity` is set. | `[]` | +| `grafana.affinity` | Affinity for pod assignment | `{}` | +| `grafana.nodeSelector` | Node labels for pod assignment | `{}` | +| `grafana.tolerations` | Tolerations for pod assignment | `[]` | +| `grafana.topologySpreadConstraints` | Topology spread constraints rely on node labels to identify the topology domain(s) that each Node is in | `[]` | +| `grafana.podSecurityContext.enabled` | Enable securityContext on for Grafana deployment | `true` | +| `grafana.podSecurityContext.fsGroup` | Group to configure permissions for volumes | `1001` | +| `grafana.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `grafana.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `grafana.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `grafana.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `grafana.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `false` | +| `grafana.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `grafana.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `grafana.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `grafana.resources.limits` | The resources limits for Grafana containers | `{}` | +| `grafana.resources.requests` | The requested resources for Grafana containers | `{}` | +| `grafana.livenessProbe.enabled` | Enable livenessProbe | `true` | +| `grafana.livenessProbe.path` | Path for livenessProbe | `/api/health` | +| `grafana.livenessProbe.scheme` | Scheme for livenessProbe | `HTTP` | +| `grafana.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `120` | +| `grafana.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `grafana.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `grafana.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `grafana.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `grafana.readinessProbe.enabled` | Enable readinessProbe | `true` | +| `grafana.readinessProbe.path` | Path for readinessProbe | `/api/health` | +| `grafana.readinessProbe.scheme` | Scheme for readinessProbe | `HTTP` | +| `grafana.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `30` | +| `grafana.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `grafana.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` | +| `grafana.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `grafana.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `grafana.startupProbe.enabled` | Enable startupProbe | `false` | +| `grafana.startupProbe.path` | Path for readinessProbe | `/api/health` | +| `grafana.startupProbe.scheme` | Scheme for readinessProbe | `HTTP` | +| `grafana.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `30` | +| `grafana.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `grafana.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `grafana.startupProbe.failureThreshold` | Failure threshold for startupProbe | `6` | +| `grafana.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `grafana.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `grafana.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `grafana.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `grafana.lifecycleHooks` | for the Grafana container(s) to automate configuration before or after startup | `{}` | +| `grafana.sidecars` | Attach additional sidecar containers to the Grafana pod | `[]` | +| `grafana.initContainers` | Add additional init containers to the Grafana pod(s) | `[]` | +| `grafana.extraVolumes` | Additional volumes for the Grafana pod | `[]` | +| `grafana.extraVolumeMounts` | Additional volume mounts for the Grafana container | `[]` | +| `grafana.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for Grafana nodes | `""` | +| `grafana.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for Grafana nodes | `""` | +| `grafana.extraEnvVars` | Array containing extra env vars to configure Grafana | `[]` | +| `grafana.extraConfigmaps` | Array to mount extra ConfigMaps to configure Grafana | `[]` | +| `grafana.command` | Override default container command (useful when using custom images) | `[]` | +| `grafana.args` | Override default container args (useful when using custom images) | `[]` | + +### Persistence parameters + +| Name | Description | Value | +| --------------------------- | --------------------------------------------------------------------------------------------------------- | --------------- | +| `persistence.enabled` | Enable persistence | `true` | +| `persistence.annotations` | Persistent Volume Claim annotations | `{}` | +| `persistence.accessMode` | Persistent Volume Access Mode | `ReadWriteOnce` | +| `persistence.accessModes` | Persistent Volume Access Modes | `[]` | +| `persistence.storageClass` | Storage class to use with the PVC | `""` | +| `persistence.existingClaim` | If you want to reuse an existing claim, you can pass the name of the PVC using the existingClaim variable | `""` | +| `persistence.size` | Size for the PV | `10Gi` | + +### RBAC parameters + +| Name | Description | Value | +| --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ------- | +| `serviceAccount.create` | Specifies whether a ServiceAccount should be created | `true` | +| `serviceAccount.name` | The name of the ServiceAccount to use. If not set and create is true, a name is generated using the fullname template | `""` | +| `serviceAccount.annotations` | Annotations to add to the ServiceAccount Metadata | `{}` | +| `serviceAccount.automountServiceAccountToken` | Automount service account token for the application controller service account | `false` | + +### Traffic exposure parameters + +| Name | Description | Value | +| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | +| `service.type` | Kubernetes Service type | `ClusterIP` | +| `service.clusterIP` | Grafana service Cluster IP | `""` | +| `service.ports.grafana` | Grafana service port | `3000` | +| `service.nodePorts.grafana` | Specify the nodePort value for the LoadBalancer and NodePort service types | `""` | +| `service.loadBalancerIP` | loadBalancerIP if Grafana service type is `LoadBalancer` (optional, cloud specific) | `""` | +| `service.loadBalancerClass` | loadBalancerClass if Grafana service type is `LoadBalancer` (optional, cloud specific) | `""` | +| `service.loadBalancerSourceRanges` | loadBalancerSourceRanges if Grafana service type is `LoadBalancer` (optional, cloud specific) | `[]` | +| `service.annotations` | Provide any additional annotations which may be required. | `{}` | +| `service.externalTrafficPolicy` | Grafana service external traffic policy | `Cluster` | +| `service.extraPorts` | Extra port to expose on Grafana service | `[]` | +| `service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` | +| `service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `ingress.enabled` | Set to true to enable ingress record generation | `false` | +| `ingress.pathType` | Ingress Path type | `ImplementationSpecific` | +| `ingress.apiVersion` | Override API Version (automatically detected if not set) | `""` | +| `ingress.hostname` | When the ingress is enabled, a host pointing to this will be created | `grafana.local` | +| `ingress.path` | Default path for the ingress resource | `/` | +| `ingress.annotations` | Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. | `{}` | +| `ingress.tls` | Enable TLS configuration for the hostname defined at ingress.hostname parameter | `false` | +| `ingress.extraHosts` | The list of additional hostnames to be covered with this ingress record. | `[]` | +| `ingress.extraPaths` | Any additional arbitrary paths that may need to be added to the ingress under the main host. | `[]` | +| `ingress.extraTls` | The tls configuration for additional hostnames to be covered with this ingress record. | `[]` | +| `ingress.secrets` | If you're providing your own certificates, please use this to add the certificates as secrets | `[]` | +| `ingress.secrets` | It is also possible to create and manage the certificates outside of this helm chart | `[]` | +| `ingress.selfSigned` | Create a TLS secret for this ingress record using self-signed certificates generated by Helm | `false` | +| `ingress.ingressClassName` | IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+) | `""` | +| `ingress.extraRules` | Additional rules to be covered with this ingress record | `[]` | + +### Metrics parameters + +| Name | Description | Value | +| ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `metrics.enabled` | Enable the export of Prometheus metrics | `false` | +| `metrics.service.annotations` | Annotations for Prometheus metrics service | `{}` | +| `metrics.serviceMonitor.enabled` | if `true`, creates a Prometheus Operator ServiceMonitor (also requires `metrics.enabled` to be `true`) | `false` | +| `metrics.serviceMonitor.namespace` | Namespace in which Prometheus is running | `""` | +| `metrics.serviceMonitor.interval` | Interval at which metrics should be scraped. | `""` | +| `metrics.serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended | `""` | +| `metrics.serviceMonitor.selector` | Prometheus instance selector labels | `{}` | +| `metrics.serviceMonitor.relabelings` | RelabelConfigs to apply to samples before scraping | `[]` | +| `metrics.serviceMonitor.metricRelabelings` | MetricRelabelConfigs to apply to samples before ingestion | `[]` | +| `metrics.serviceMonitor.honorLabels` | Labels to honor to add to the scrape endpoint | `false` | +| `metrics.serviceMonitor.labels` | Additional custom labels for the ServiceMonitor | `{}` | +| `metrics.serviceMonitor.jobLabel` | The name of the label on the target service to use as the job name in prometheus. | `""` | +| `metrics.prometheusRule.enabled` | if `true`, creates a Prometheus Operator PrometheusRule (also requires `metrics.enabled` to be `true` and `metrics.prometheusRule.rules`) | `false` | +| `metrics.prometheusRule.namespace` | Namespace for the PrometheusRule Resource (defaults to the Release Namespace) | `""` | +| `metrics.prometheusRule.additionalLabels` | Additional labels that can be used so PrometheusRule will be discovered by Prometheus | `{}` | +| `metrics.prometheusRule.rules` | PrometheusRule rules to configure | `[]` | + +### Volume permissions init Container Parameters + +| Name | Description | Value | +| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------ | -------------------------- | +| `volumePermissions.enabled` | Enable init container that changes the owner/group of the PV mount point to `runAsUser:fsGroup` | `false` | +| `volumePermissions.image.registry` | OS Shell + Utility image registry | `REGISTRY_NAME` | +| `volumePermissions.image.repository` | OS Shell + Utility image repository | `REPOSITORY_NAME/os-shell` | +| `volumePermissions.image.digest` | OS Shell + Utility image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `volumePermissions.image.pullPolicy` | OS Shell + Utility image pull policy | `IfNotPresent` | +| `volumePermissions.image.pullSecrets` | OS Shell + Utility image pull secrets | `[]` | +| `volumePermissions.resources.limits` | The resources limits for the init container | `{}` | +| `volumePermissions.resources.requests` | The requested resources for the init container | `{}` | +| `volumePermissions.containerSecurityContext.runAsUser` | Set init container's Security Context runAsUser | `0` | + +### Diagnostic Mode Parameters + +| Name | Description | Value | +| ------------------------ | --------------------------------------------------------------------------------------- | -------------- | +| `diagnosticMode.enabled` | Enable diagnostic mode (all probes will be disabled and the command will be overridden) | `false` | +| `diagnosticMode.command` | Command to override all containers in the deployment | `["sleep"]` | +| `diagnosticMode.args` | Args to override all containers in the deployment | `["infinity"]` | + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +helm install my-release \ + --set admin.user=admin-user oci://REGISTRY_NAME/REPOSITORY_NAME/grafana +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The above command sets the Grafana admin user to `admin-user`. + +> NOTE: Once this chart is deployed, it is not possible to change the application's access credentials, such as usernames or passwords, using Helm. To change these application credentials after deployment, delete any persistent volumes (PVs) used by the chart and re-deploy it, or use the application's built-in administrative tools if available. + +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 oci://REGISTRY_NAME/REPOSITORY_NAME/grafana +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> **Tip**: You can use the default [values.yaml](https://github.com/bitnami/charts/tree/main/bitnami/grafana/values.yaml) + +## Configuration and installation details + +### [Rolling VS Immutable tags](https://docs.bitnami.com/tutorials/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. + +### Using custom configuration + +Grafana supports multiples configuration files. Using kubernetes you can mount a file using a ConfigMap or a Secret. For example, to mount a custom `grafana.ini` file or `custom.ini` file you can create a ConfigMap like the following: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: myconfig +data: + grafana.ini: |- + # Raw text of the file +``` + +And now you need to pass the ConfigMap name, to the corresponding parameters: `config.useGrafanaIniFile=true` and `config.grafanaIniConfigMap=myconfig`. + +To provide dashboards on deployment time, Grafana needs a dashboards provider and the dashboards themselves. +A default provider is created if enabled, or you can mount your own provider using a ConfigMap, but have in mind that the path to the dashboard folder must be `/opt/bitnami/grafana/dashboards`. + + 1. To create a dashboard, it is needed to have a datasource for it. The datasources must be created mounting a secret with all the datasource files in it. In this case, it is not a ConfigMap because the datasource could contain sensitive information. + 2. To load the dashboards themselves you need to create a ConfigMap for each one containing the `json` file that defines the dashboard and set the array with the ConfigMap names into the `dashboardsConfigMaps` parameter. +Note the difference between the datasources and the dashboards creation. For the datasources we can use just one secret with all of the files, while for the dashboards we need one ConfigMap per file. + +For example, create the dashboard ConfigMap(s) and datasource Secret as described below: + +```console +kubectl create secret generic datasource-secret --from-file=datasource-secret.yaml +kubectl create configmap my-dashboard-1 --from-file=my-dashboard-1.json +kubectl create configmap my-dashboard-2 --from-file=my-dashboard-2.json +``` + +> Note: the commands above assume you had previously exported your dashboards in the JSON files: *my-dashboard-1.json* and *my-dashboard-2.json* +> Note: the commands above assume you had previously created a datasource config file *datasource-secret.yaml*. Find an example at + +Once you have them, use the following parameters to deploy Grafana with 2 custom dashboards: + +```console +dashboardsProvider.enabled=true +datasources.secretName=datasource-secret +dashboardsConfigMaps[0].configMapName=my-dashboard-1 +dashboardsConfigMaps[0].fileName=my-dashboard-1.json +dashboardsConfigMaps[1].configMapName=my-dashboard-2 +dashboardsConfigMaps[1].fileName=my-dashboard-2.json +``` + +More info at [Grafana documentation](https://grafana.com/docs/grafana/latest/administration/provisioning/#dashboards). + +### LDAP configuration + +To enable LDAP authentication it is necessary to provide a ConfigMap with the Grafana LDAP configuration file. For instance: + +**configmap.yaml**: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: ldap-config +data: + ldap.toml: |- + [[servers]] + # Ldap server host (specify multiple hosts space separated) + host = "ldap" + # Default port is 389 or 636 if use_ssl = true + port = 389 + # Set to true if ldap server supports TLS + use_ssl = false + # Set to true if connect ldap server with STARTTLS pattern (create connection in insecure, then upgrade to secure connection with TLS) + start_tls = false + # set to true if you want to skip ssl cert validation + ssl_skip_verify = false + # set to the path to your root CA certificate or leave unset to use system defaults + # root_ca_cert = "/path/to/certificate.crt" + # Authentication against LDAP servers requiring client certificates + # client_cert = "/path/to/client.crt" + # client_key = "/path/to/client.key" + + # Search user bind dn + bind_dn = "cn=admin,dc=example,dc=org" + # Search user bind password + # If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;""" + bind_password = 'admin' + + # User search filter, for example "(cn=%s)" or "(sAMAccountName=%s)" or "(uid=%s)" + # Allow login from email or username, example "(|(sAMAccountName=%s)(userPrincipalName=%s))" + search_filter = "(uid=%s)" + + # An array of base dns to search through + search_base_dns = ["ou=People,dc=support,dc=example,dc=org"] + + # group_search_filter = "(&(objectClass=posixGroup)(memberUid=%s))" + # group_search_filter_user_attribute = "distinguishedName" + # group_search_base_dns = ["ou=groups,dc=grafana,dc=org"] + + # Specify names of the ldap attributes your ldap uses + [servers.attributes] + name = "givenName" + surname = "sn" + username = "cn" + member_of = "memberOf" + email = "email" +``` + +Create the ConfigMap into the cluster and deploy the Grafana Helm Chart using the existing ConfigMap and the following parameters: + +```console +ldap.enabled=true +ldap.configMapName=ldap-config +ldap.allowSignUp=true +``` + +### Installing Grafana Image Renderer Plugin + +In order to install the [Grafana Image Renderer Plugin](https://github.com/grafana/grafana-image-renderer) so you rely on it to render images and save memory on Grafana pods, follow the steps below: + +1. Create a Grafana Image Renderer deployment and service using the K8s manifests below: + +```yaml +# deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: grafana-image-renderer + namespace: default + labels: + app.kubernetes.io/name: grafana-image-renderer + app.kubernetes.io/instance: grafana-image-renderer + app.kubernetes.io/component: image-renderer-plugin + app.kubernetes.io/part-of: grafana +spec: + replicas: 1 + strategy: + type: RollingUpdate + selector: + matchLabels: + app.kubernetes.io/name: grafana-image-renderer + app.kubernetes.io/instance: grafana-image-renderer + app.kubernetes.io/component: image-renderer-plugin + template: + metadata: + labels: + app.kubernetes.io/name: grafana-image-renderer + app.kubernetes.io/instance: grafana-image-renderer + app.kubernetes.io/component: image-renderer-plugin + app.kubernetes.io/part-of: grafana + spec: + securityContext: + fsGroup: 1001 + runAsNonRoot: true + runAsUser: 1001 + containers: + - name: grafana-image-renderer + image: docker.io/bitnami/grafana-image-renderer:3 + securityContext: + runAsUser: 1001 + env: + - name: HTTP_HOST + value: "::" + - name: HTTP_PORT + value: "8080" + ports: + - name: http + containerPort: 8080 + protocol: TCP +# service.yaml +apiVersion: v1 +kind: Service +metadata: + name: grafana-image-renderer + namespace: default + labels: + app.kubernetes.io/name: grafana-image-renderer + app.kubernetes.io/instance: grafana-image-renderer + app.kubernetes.io/component: image-renderer-plugin + app.kubernetes.io/part-of: grafana +spec: + type: ClusterIP + sessionAffinity: None + ports: + - port: 8080 + targetPort: http + protocol: TCP + name: http + selector: + app.kubernetes.io/name: grafana-image-renderer + app.kubernetes.io/instance: grafana-image-renderer + app.kubernetes.io/component: image-renderer-plugin +``` + +1. Upgrade your chart release adding the following block to your `values.yaml` file: + +```yaml +imageRenderer: + enabled: true + serverURL: "http://grafana-image-renderer.default.svc.cluster.local:8080/render" + callbackURL: "http://grafana.default.svc.cluster.local:3000/" +``` + +> Note: the steps above assume an installation in the `default` namespace. If you are installing the chart in a different namespace, adjust the manifests and the `serverURL` & `callbackURL` values accordingly. + +### Supporting HA (High Availability) + +To support HA Grafana just need an external database where store dashboards, users and other persistent data. +To configure the external database provide a configuration file containing the [database section](https://grafana.com/docs/installation/configuration/#database) + +More information about Grafana HA [here](https://grafana.com/docs/tutorials/ha_setup/) + +### Setting Pod's affinity + +This chart allows you to set your custom affinity using the `affinity` parameter. Find more information about Pod's affinity in the [kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). + +As an alternative, you can use of the preset configurations for pod affinity, pod anti-affinity, and node affinity available at the [bitnami/common](https://github.com/bitnami/charts/tree/main/bitnami/common#affinities) chart. To do so, set the `podAffinityPreset`, `podAntiAffinityPreset`, or `nodeAffinityPreset` parameters. + +## Persistence + +The [Bitnami Grafana](https://github.com/bitnami/containers/tree/main/bitnami/grafana) image stores the Grafana data and configurations at the `/opt/bitnami/grafana/data` 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. + +## Troubleshooting + +Find more information about how to deal with common errors related to Bitnami's Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues). + +## Upgrading + +### To 9.4.0 + +This version stops shipping the Grafana Image Renderer in the chart. In order to use this plugin, refer to the [Installing Grafana Image Renderer Plugin](#installing-grafana-image-renderer-plugin) instructions. + +### To 8.0.0 + +This major release only bumps the Grafana version to 9.x. No major issues are expected during the upgrade. See the upstream changelog for more info about the changes included in this new major version of the application + +### To 7.0.0 + +This major release renames several values in this chart and adds missing features, in order to be inline with the rest of assets in the Bitnami charts repository. + +Since the volume access mode when persistence is enabled is `ReadWriteOnce` in order to upgrade the deployment you will need to either use the `Recreate` strategy or delete the old deployment. + +```console +kubectl delete deployment +helm upgrade oci://REGISTRY_NAME/REPOSITORY_NAME/grafana +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +### To 4.1.0 + +This version also introduces `bitnami/common`, a [library chart](https://helm.sh/docs/topics/library_charts/#helm) as a dependency. More documentation about this new utility could be found [here](https://github.com/bitnami/charts/tree/main/bitnami/common#bitnami-common-library-chart). Please, make sure that you have updated the chart dependencies before executing any upgrade. + +### To 4.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +#### What changes were introduced in this major version? + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts + +#### Considerations when upgrading to this version + +- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues +- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore +- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 + +#### Useful links + +- +- +- + +### To 3.0.0 + +Deployment label selector is immutable after it gets created, so you cannot "upgrade". + +In the deployment label selectors of the resources were updated to add the component name. Resulting in compatibility breakage. + +In order to "upgrade" from a previous version, you will need to [uninstall](#uninstalling-the-chart) the existing chart manually. + +This major version signifies this change. + +## License + +Copyright © 2024 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/backing-services/grafana/charts/common-2.14.0.tgz b/backing-services/grafana/charts/common-2.14.0.tgz new file mode 100644 index 0000000..83a8b3e Binary files /dev/null and b/backing-services/grafana/charts/common-2.14.0.tgz differ diff --git a/backing-services/grafana/hospital-bahman-production.values.yaml b/backing-services/grafana/hospital-bahman-production.values.yaml new file mode 100644 index 0000000..e308112 --- /dev/null +++ b/backing-services/grafana/hospital-bahman-production.values.yaml @@ -0,0 +1,18 @@ +image: + registry: 172.16.16.1:30516 + repository: bitnami/grafana + tag: 10.2.3-debian-11-r0 + +volumePermissions: + enabled: false + image: + registry: 172.16.16.1:30516 + repository: bitnami/os-shell + tag: 11-debian-11-r92 + +admin: + user: "admin" + password: "Tavana123$" + +service: + type: NodePort \ No newline at end of file diff --git a/backing-services/grafana/templates/NOTES.txt b/backing-services/grafana/templates/NOTES.txt new file mode 100644 index 0000000..d98b0a5 --- /dev/null +++ b/backing-services/grafana/templates/NOTES.txt @@ -0,0 +1,33 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +** Please be patient while the chart is being deployed ** + +1. Get the application URL by running these commands: + +{{- if .Values.ingress.enabled }} + {{ ternary "https" "http" .Values.ingress.tls }}://{{ .Values.ingress.hostname }}{{ .Values.ingress.path }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "common.names.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "common.names.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "common.names.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ .Values.service.ports.grafana }} +{{- else if contains "ClusterIP" .Values.service.type }} + echo "Browse to http://127.0.0.1:8080" + kubectl port-forward svc/{{ include "common.names.fullname" . }} 8080:{{ .Values.service.ports.grafana }} & +{{- end }} + +2. Get the admin credentials: + + echo "User: {{ .Values.admin.user }}" + echo "Password: $(kubectl get secret {{ include "grafana.adminSecretName" . }} --namespace {{ .Release.Namespace }} -o jsonpath="{.data.{{ include "grafana.adminSecretPasswordKey" . }}}" | base64 -d)" + +{{- include "common.warnings.rollingTag" .Values.image }} +{{- include "common.warnings.rollingTag" .Values.volumePermissions.image }} +{{ include "grafana.validateValues" . }} +{{ include "grafana.validateValues.database" . }} \ No newline at end of file diff --git a/backing-services/grafana/templates/_helpers.tpl b/backing-services/grafana/templates/_helpers.tpl new file mode 100644 index 0000000..97a5397 --- /dev/null +++ b/backing-services/grafana/templates/_helpers.tpl @@ -0,0 +1,245 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the proper Grafana image name +*/}} +{{- define "grafana.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper image name (for the init container volume-permissions image) +*/}} +{{- define "volumePermissions.image" -}} +{{- include "common.images.image" ( dict "imageRoot" .Values.volumePermissions.image "global" .Values.global ) -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "grafana.imagePullSecrets" -}} +{{- include "common.images.renderPullSecrets" (dict "images" (list .Values.image) "context" $) -}} +{{- end }} + +{{/* +Return the proper Storage Class +*/}} +{{- define "grafana.storageClass" -}} +{{- include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the Grafana admin credentials secret +*/}} +{{- define "grafana.adminSecretName" -}} +{{- if .Values.admin.existingSecret -}} + {{- printf "%s" (tpl .Values.admin.existingSecret $) -}} +{{- else -}} + {{- printf "%s-admin" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return the Grafana admin password key +*/}} +{{- define "grafana.adminSecretPasswordKey" -}} +{{- if and .Values.admin.existingSecret .Values.admin.existingSecretPasswordKey -}} + {{- printf "%s" (tpl .Values.admin.existingSecretPasswordKey $) -}} +{{- else -}} + {{- printf "GF_SECURITY_ADMIN_PASSWORD" -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a secret object should be created +*/}} +{{- define "grafana.createAdminSecret" -}} +{{- if not .Values.admin.existingSecret }} + {{- true -}} +{{- else -}} +{{- end -}} +{{- end -}} + +{{/* +Return the Grafana SMTP credentials secret +*/}} +{{- define "grafana.smtpSecretName" -}} +{{- if .Values.smtp.existingSecret }} + {{- printf "%s" (tpl .Values.smtp.existingSecret $) -}} +{{- else -}} + {{- printf "%s-smtp" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return the Grafana SMTP user key +*/}} +{{- define "grafana.smtpSecretUserKey" -}} +{{- if and .Values.smtp.existingSecret .Values.smtp.existingSecretUserKey -}} + {{- printf "%s" (tpl .Values.smtp.existingSecretUserKey $) -}} +{{- else -}} + {{- printf "GF_SMTP_USER" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the Grafana SMTP password key +*/}} +{{- define "grafana.smtpSecretPasswordKey" -}} +{{- if and .Values.smtp.existingSecret .Values.smtp.existingSecretPasswordKey -}} + {{- printf "%s" (tpl .Values.smtp.existingSecretPasswordKey $) -}} +{{- else -}} + {{- printf "GF_SMTP_PASSWORD" -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a secret object should be created +*/}} +{{- define "grafana.createSMTPSecret" -}} +{{- if and .Values.smtp.enabled (not .Values.smtp.existingSecret) }} + {{- true -}} +{{- else -}} +{{- end -}} +{{- end -}} + +{{/* +Returns the proper service account name depending if an explicit service account name is set +in the values file. If the name is not set it will default to either common.names.fullname if serviceAccount.create +is true or default otherwise. +*/}} +{{- define "grafana.serviceAccountName" -}} + {{- if .Values.serviceAccount.create -}} + {{ default (include "common.names.fullname" .) .Values.serviceAccount.name }} + {{- else -}} + {{ default "default" .Values.serviceAccount.name }} + {{- end -}} +{{- end -}} + +{{/* +Return LDAP configuration generated from ldap properties. +*/}} +{{- define "grafana.ldap.config" -}} +{{- $hostPort := get (urlParse (required "You must set ldap.uri" .Values.ldap.uri)) "host" -}} +[[servers]] +# Ldap server host (specify multiple hosts space separated) +host = {{ index (splitList ":" $hostPort) 0 | quote }} +# Default port is 389 or 636 if use_ssl = true +port = {{ index (splitList ":" $hostPort) 1 | default 389 }} +# Set to true if LDAP server should use an encrypted TLS connection (either with STARTTLS or LDAPS) +{{- if .Values.ldap.tls.enabled }} +use_ssl = {{ .Values.ldap.tls.enabled }} +ssl_skip_verify = {{ .Values.ldap.tls.skipVerify }} +# If set to true, use LDAP with STARTTLS instead of LDAPS +start_tls = {{ .Values.ldap.tls.startTls }} +{{- if .Values.ldap.tls.CAFilename }} +# set to the path to your root CA certificate or leave unset to use system defaults +root_ca_cert = {{ printf "%s/%s" .Values.ldap.tls.certificatesMountPath .Values.ldap.tls.CAFilename | quote }} +{{- end }} +{{- if .Values.ldap.tls.certFilename }} +# Authentication against LDAP servers requiring client certificates +client_cert = {{ printf "%s/%s" .Values.ldap.tls.certificatesMountPath .Values.ldap.tls.certFilename | quote }} +client_key = {{ printf "%s/%s" .Values.ldap.tls.certificatesMountPath (required "ldap.tls.certKeyFilename is required when ldap.tls.certFilename is defined" .Values.ldap.tls.certKeyFilename) | quote }} +{{- end }} +{{- end }} +{{- if .Values.ldap.binddn }} +# Search user bind dn +bind_dn = {{ .Values.ldap.binddn | quote }} +{{- end }} +{{- if .Values.ldap.bindpw }} +# Search user bind password +# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;""" +bind_password = {{ .Values.ldap.bindpw | quote }} +{{- end }} + +# User search filter, for example "(cn=%s)" or "(sAMAccountName=%s)" or "(uid=%s)" +# Allow login from email or username, example "(|(sAMAccountName=%s)(userPrincipalName=%s))" +{{- if .Values.ldap.searchFilter }} +search_filter = {{ .Values.ldap.searchFilter | quote }} +{{- else if .Values.ldap.searchAttribute }} +search_filter = "({{ .Values.ldap.searchAttribute }}=%s)" +{{- end }} +# An array of base dns to search through +search_base_dns = [{{ (required "You must set ldap.basedn" .Values.ldap.basedn) | quote }}] + +{{ .Values.ldap.extraConfiguration }} +{{- end -}} + +{{/* +Validate values for Grafana. +*/}} +{{- define "grafana.validateValues" -}} +# Note: Do not include grafana.validateValues.database here. See https://github.com/bitnami/charts/issues/20629 +{{- $messages := list -}} +{{- $messages := append $messages (include "grafana.validateValues.configmapsOrSecrets" .) -}} +{{- $messages := append $messages (include "grafana.validateValues.ldap.configuration" .) -}} +{{- $messages := append $messages (include "grafana.validateValues.ldap.configmapsecret" .) -}} +{{- $messages := append $messages (include "grafana.validateValues.ldap.tls" .) -}} +{{- $messages := append $messages (include "grafana.validateValues.imageRenderer" .) -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}} +{{- end -}} +{{- end -}} + +{{/* Validate values of Grafana - A ConfigMap or Secret name must be provided when loading a custom grafana.ini file */}} +{{- define "grafana.validateValues.configmapsOrSecrets" -}} +{{- if and .Values.config.useGrafanaIniFile (not .Values.config.grafanaIniSecret) (not .Values.config.grafanaIniConfigMap) -}} +grafana: config.useGrafanaIniFile config.grafanaIniSecret and config.grafanaIniConfigMap + You enabled config.useGrafanaIniFile but did not specify config.grafanaIniSecret nor config.grafanaIniConfigMap +{{- end -}} +{{- end -}} + +{{/* Validate values of Grafana - A custom ldap.toml file must be provided when enabling LDAP */}} +{{- define "grafana.validateValues.ldap.configuration" -}} +{{- if and .Values.ldap.enabled (empty .Values.ldap.uri) (empty .Values.ldap.basedn) (empty .Values.ldap.configuration) (empty .Values.ldap.configMapName) (empty .Values.ldap.secretName) -}} +grafana: ldap.enabled ldap.uri ldap.basedn ldap.configuration ldap.configMapName and ldap.secretName + You must provide the uri and basedn of your LDAP Sever (--set ldap.uri="aaa" --set ldap.basedn="bbb") + or the content of your custom ldap.toml file when enabling LDAP (--set ldap.configuration="xxx") + As an alternative, you can set the name of an existing ConfigMap (--set ldap.configMapName="yyy") or + an an existing Secret (--set ldap.secretName="zzz") containging the custom ldap.toml file. +{{- end -}} +{{- end -}} + +{{/* Validate values of Grafana - Only a ConfigMap or Secret name must be provided when loading a custom ldap.toml file */}} +{{- define "grafana.validateValues.ldap.configmapsecret" -}} +{{- if and .Values.ldap.enabled (not (empty .Values.ldap.configMapName)) (not (empty .Values.ldap.secretName)) -}} +grafana: ldap.enabled ldap.configMapName and ldap.secretName + You cannot load a custom ldap.toml file both from a ConfigMap and a Secret simultaneously +{{- end -}} +{{- end -}} + +{{/* Validate values of Grafana - LDAP TLS validation */}} +{{- define "grafana.validateValues.ldap.tls" -}} +{{- if and .Values.ldap.enabled .Values.ldap.tls.enabled (empty .Values.ldap.tls.certificatesSecret) (or (not (empty .Values.ldap.tls.CAFilename)) (not (empty .Values.ldap.tls.certFilename)) (not (empty .Values.ldap.tls.certKeyFilename))) -}} +grafana: ldap.enabled ldap.tls.enabled ldap.tls.certificatesSecret ldap.tls.CAFilename ldap.tls.certFilename and ldap.tls.certKeyFilename + You must set ldap.tls.certificatesSecret if you want to specify any certificate for LDAP TLS connection +{{- end -}} +{{- end -}} + +{{/* Validate values of Grafana - Requirements to use an external database */}} +{{- define "grafana.validateValues.database" -}} +{{- $replicaCount := int .Values.grafana.replicaCount }} +{{- if gt $replicaCount 1 -}} +grafana: replicaCount + Using more than one replica requires using an external database to share data between Grafana instances. + By default Grafana uses an internal sqlite3 per instance but you can configure an external MySQL or PostgreSQL. + Please, ensure you provide a configuration file configuring the external database to share data between replicas. +{{- end -}} +{{- end -}} + +{{/* Validate values of Grafana - Requirements to use Grafana Image Renderer */}} +{{- define "grafana.validateValues.imageRenderer" -}} +{{- if and .Values.imageRenderer.enabled (or (empty .Values.imageRenderer.serverURL) (empty .Values.imageRenderer.callbackURL)) -}} +grafana: imageRenderer.enabled imageRenderer.serverURL and imageRenderer.callbackURL + You must provide the serverURL and callbackURL for Grafana Image Renderer when enabling it. + (--set imageRenderer.serverURL="http://image-renderer-url/render" --set imageRenderer.callbackURL="http://grafana-url:3000/") +{{- end -}} +{{- end -}} diff --git a/backing-services/grafana/templates/configmap.yaml b/backing-services/grafana/templates/configmap.yaml new file mode 100644 index 0000000..ca219db --- /dev/null +++ b/backing-services/grafana/templates/configmap.yaml @@ -0,0 +1,34 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "common.names.fullname" . }}-envvars + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: grafana + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + GF_SECURITY_ADMIN_USER: {{ .Values.admin.user | quote }} + {{- if .Values.imageRenderer.enabled }} + GF_RENDERING_SERVER_URL: {{ .Values.imageRenderer.serverURL | quote }} + GF_RENDERING_CALLBACK_URL: {{ .Values.imageRenderer.callbackURL | quote }} + {{- end }} + {{- if .Values.plugins }} + GF_INSTALL_PLUGINS: {{ .Values.plugins | quote }} + {{- else }} + GF_INSTALL_PLUGINS: "" + {{- end }} + GF_PATHS_PLUGINS: "/opt/bitnami/grafana/data/plugins" + GF_AUTH_LDAP_ENABLED: {{ .Values.ldap.enabled | quote }} + GF_AUTH_LDAP_CONFIG_FILE: "/opt/bitnami/grafana/conf/ldap.toml" + GF_AUTH_LDAP_ALLOW_SIGN_UP: {{ .Values.ldap.allowSignUp | quote }} + GF_PATHS_PROVISIONING: "/opt/bitnami/grafana/conf/provisioning" + GF_PATHS_CONFIG: "/opt/bitnami/grafana/conf/grafana.ini" + GF_PATHS_DATA: "/opt/bitnami/grafana/data" + GF_PATHS_LOGS: "/opt/bitnami/grafana/logs" diff --git a/backing-services/grafana/templates/dashboard-provider.yaml b/backing-services/grafana/templates/dashboard-provider.yaml new file mode 100644 index 0000000..3ce1d6a --- /dev/null +++ b/backing-services/grafana/templates/dashboard-provider.yaml @@ -0,0 +1,43 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.dashboardsProvider.enabled (not .Values.dashboardsProvider.configMapName) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "common.names.fullname" . }}-provider + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: grafana + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + default-provider.yaml: |- + apiVersion: 1 + + providers: + # an unique provider name + - name: 'default-provider' + # org id. will default to orgId 1 if not specified + orgId: 1 + # name of the dashboard folder. Required + folder: dashboards + # folder UID. will be automatically generated if not specified + folderUid: '' + # provider type. Required + type: file + # disable dashboard deletion + disableDeletion: false + # enable dashboard editing + editable: true + # how often Grafana will scan for changed dashboards + updateIntervalSeconds: 10 + options: + # path to dashboard files on disk. Required + path: /opt/bitnami/grafana/dashboards + # enable folders creation for dashboards + #foldersFromFilesStructure: true +{{- end }} diff --git a/backing-services/grafana/templates/datasources-secret.yaml b/backing-services/grafana/templates/datasources-secret.yaml new file mode 100644 index 0000000..45913e4 --- /dev/null +++ b/backing-services/grafana/templates/datasources-secret.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.datasources.secretDefinition }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }}-datasources + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: grafana + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + datasources.yaml: {{ include "common.tplvalues.render" ( dict "value" .Values.datasources.secretDefinition "context" $ ) | b64enc | nindent 4 }} +{{- end }} diff --git a/backing-services/grafana/templates/deployment.yaml b/backing-services/grafana/templates/deployment.yaml new file mode 100644 index 0000000..8104aa5 --- /dev/null +++ b/backing-services/grafana/templates/deployment.yaml @@ -0,0 +1,354 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} +kind: Deployment +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: grafana + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.grafana.replicaCount }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.grafana.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: grafana + {{- if .Values.grafana.updateStrategy }} + strategy: {{ include "common.tplvalues.render" (dict "value" .Values.grafana.updateStrategy "context" $) | nindent 4 }} + {{- end }} + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: grafana + annotations: + {{- if (include "grafana.createAdminSecret" .) }} + checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} + {{- end }} + {{- if (include "grafana.createSMTPSecret" .) }} + checksum/smtp-secret: {{ include (print $.Template.BasePath "/smtp-secret.yaml") . | sha256sum }} + {{- end }} + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + checksum/dashboard-provider: {{ include (print $.Template.BasePath "/dashboard-provider.yaml") . | sha256sum }} + {{- if and .Values.ldap.enabled (or (not (empty .Values.ldap.configuration)) (not (empty .Values.ldap.uri))) (empty .Values.ldap.configMapName) (empty .Values.ldap.secretName) }} + checksum/ldap: {{ include (print $.Template.BasePath "/ldap-secret.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.grafana.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.grafana.podAnnotations "context" $) | nindent 8 }} + {{- end }} + spec: + {{- include "grafana.imagePullSecrets" . | nindent 6 }} + {{- if .Values.grafana.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.grafana.hostAliases "context" $) | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "grafana.serviceAccountName" . }} + {{- if .Values.grafana.schedulerName }} + schedulerName: {{ .Values.grafana.schedulerName | quote }} + {{- end }} + {{- if .Values.grafana.priorityClassName }} + priorityClassName: {{ .Values.grafana.priorityClassName | quote }} + {{- end }} + {{- if .Values.grafana.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.grafana.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.grafana.podAffinityPreset "component" "grafana" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.grafana.podAntiAffinityPreset "component" "grafana" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.grafana.nodeAffinityPreset.type "key" .Values.grafana.nodeAffinityPreset.key "values" .Values.grafana.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.grafana.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.grafana.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.grafana.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.grafana.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.grafana.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.grafana.topologySpreadConstraints "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.grafana.podSecurityContext.enabled }} + securityContext: {{- omit .Values.grafana.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.grafana.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.grafana.terminationGracePeriodSeconds }} + {{- end }} + initContainers: + {{- if .Values.volumePermissions.enabled }} + - name: volume-permissions + image: {{ include "volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + args: + - -ec + - | + mkdir -p /bitnami/grafana + find /bitnami/grafana -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | xargs -r chown -R {{ .Values.grafana.containerSecurityContext.runAsUser }}:{{ .Values.grafana.podSecurityContext.fsGroup }} + securityContext: {{- include "common.tplvalues.render" (dict "value" .Values.volumePermissions.containerSecurityContext "context" $) | nindent 12 }} + {{- if .Values.volumePermissions.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.volumePermissions.resources "context" $) | nindent 12 }} + {{- end }} + volumeMounts: + - name: data + mountPath: /bitnami/grafana + {{- end }} + {{- if .Values.grafana.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.grafana.initContainers "context" $) | nindent 8 }} + {{- end }} + containers: + - name: grafana + image: {{ include "grafana.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.grafana.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.grafana.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.grafana.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.grafana.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.grafana.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.grafana.args "context" $) | nindent 12 }} + {{- end }} + envFrom: + - configMapRef: + name: {{ include "common.names.fullname" . }}-envvars + {{- if .Values.grafana.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.grafana.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.grafana.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.grafana.extraEnvVarsSecret "context" $) }} + {{- end }} + env: + - name: GF_SECURITY_ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "grafana.adminSecretName" . }} + key: {{ include "grafana.adminSecretPasswordKey" . }} + {{- if .Values.smtp.enabled }} + - name: GF_SMTP_ENABLED + value: "true" + {{- if .Values.smtp.host }} + - name: GF_SMTP_HOST + value: {{ .Values.smtp.host }} + {{- end }} + {{- if .Values.smtp.fromAddress }} + - name: GF_SMTP_FROM_ADDRESS + value: {{ .Values.smtp.fromAddress }} + {{- end }} + {{- if .Values.smtp.fromName }} + - name: GF_SMTP_FROM_NAME + value: {{ .Values.smtp.fromName }} + {{- end }} + {{- if .Values.smtp.skipVerify }} + - name: GF_SMTP_SKIP_VERIFY + value: "{{ .Values.smtp.skipVerify }}" + {{- end }} + - name: GF_SMTP_USER + valueFrom: + secretKeyRef: + name: {{ include "grafana.smtpSecretName" . }} + key: {{ include "grafana.smtpSecretUserKey" . }} + - name: GF_SMTP_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "grafana.smtpSecretName" . }} + key: {{ include "grafana.smtpSecretPasswordKey" . }} + {{- end }} + {{- if .Values.grafana.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.grafana.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + volumeMounts: + {{- if .Values.config.useGrafanaIniFile }} + - name: grafana-ini + mountPath: /opt/bitnami/grafana/conf/grafana.ini + subPath: grafana.ini + {{- end }} + - name: data + mountPath: /opt/bitnami/grafana/data + {{- if .Values.dashboardsProvider.enabled }} + - name: dashboards-provider + mountPath: /opt/bitnami/grafana/conf/provisioning/dashboards + {{- end }} + {{- range .Values.dashboardsConfigMaps }} + - name: {{ include "common.tplvalues.render" ( dict "value" .configMapName "context" $ ) }} + {{- if .folderName }} + mountPath: /opt/bitnami/grafana/dashboards/{{ .folderName }}/{{ .fileName }} + {{- else }} + mountPath: /opt/bitnami/grafana/dashboards/{{ .fileName }} + {{- end }} + subPath: {{ .fileName }} + {{- end }} + {{- if or (.Values.datasources.secretName) (.Values.datasources.secretDefinition) }} + - name: datasources + mountPath: /opt/bitnami/grafana/conf/provisioning/datasources + {{- end }} + {{- if .Values.notifiers.configMapName }} + - name: notifiers + mountPath: /opt/bitnami/grafana/conf/provisioning/notifiers + {{- end }} + {{- if .Values.alerting.configMapName }} + - name: alerting + mountPath: /opt/bitnami/grafana/conf/provisioning/alerting + {{- end }} + {{- if .Values.ldap.enabled }} + - name: ldap + mountPath: /opt/bitnami/grafana/conf/ldap.toml + subPath: ldap.toml + {{- end }} + {{- if and .Values.ldap.tls.enabled .Values.ldap.tls.certificatesSecret }} + - name: ldap-tls + mountPath: {{ .Values.ldap.tls.certificatesMountPath }} + {{- end }} + {{- range .Values.grafana.extraConfigmaps }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath | default "" }} + readOnly: {{ .readOnly }} + {{- end }} + {{- if .Values.grafana.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.grafana.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + ports: + - name: dashboard + containerPort: {{ .Values.grafana.containerPorts.grafana }} + protocol: TCP + {{- if .Values.grafana.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.grafana.extraPorts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.grafana.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.grafana.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.grafana.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: {{ .Values.grafana.livenessProbe.path }} + port: dashboard + scheme: {{ .Values.grafana.livenessProbe.scheme }} + initialDelaySeconds: {{ .Values.grafana.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.grafana.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.grafana.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.grafana.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.grafana.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.grafana.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.grafana.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.grafana.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: {{ .Values.grafana.readinessProbe.path }} + port: dashboard + scheme: {{ .Values.grafana.readinessProbe.scheme }} + initialDelaySeconds: {{ .Values.grafana.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.grafana.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.grafana.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.grafana.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.grafana.readinessProbe.failureThreshold }} + {{- end }} + {{- if .Values.grafana.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.grafana.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.grafana.startupProbe.enabled }} + startupProbe: + httpGet: + path: {{ .Values.grafana.startupProbe.path }} + port: dashboard + scheme: {{ .Values.grafana.startupProbe.scheme }} + initialDelaySeconds: {{ .Values.grafana.startupProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.grafana.startupProbe.periodSeconds }} + timeoutSeconds: {{ .Values.grafana.startupProbe.timeoutSeconds }} + successThreshold: {{ .Values.grafana.startupProbe.successThreshold }} + failureThreshold: {{ .Values.grafana.startupProbe.failureThreshold }} + {{- end }} + {{- if .Values.grafana.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.grafana.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.grafana.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.grafana.resources "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.grafana.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.grafana.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: data + {{- if .Values.persistence.enabled }} + persistentVolumeClaim: + claimName: {{ .Values.persistence.existingClaim | default (include "common.names.fullname" .) }} + {{- else }} + emptyDir: {} + {{- end }} + {{- if .Values.ldap.enabled }} + - name: ldap + {{- if not (empty .Values.ldap.configMapName) }} + configMap: + name: {{ .Values.ldap.configMapName }} + {{- else if not (empty .Values.ldap.secretName) }} + secret: + secretName: {{ .Values.ldap.secretName }} + {{- else }} + secret: + secretName: {{ printf "%s-ldap-conf" (include "common.names.fullname" .) }} + {{- end }} + {{- end }} + {{- if .Values.dashboardsProvider.enabled }} + - name: dashboards-provider + configMap: + {{- if .Values.dashboardsProvider.configMapName }} + name: {{ include "common.tplvalues.render" ( dict "value" .Values.dashboardsProvider.configMapName "context" $) }} + {{- else }} + name: {{ include "common.names.fullname" . }}-provider + {{- end }} + {{- end }} + {{- range .Values.dashboardsConfigMaps }} + - name: {{ include "common.tplvalues.render" ( dict "value" .configMapName "context" $ ) }} + configMap: + name: {{ include "common.tplvalues.render" ( dict "value" .configMapName "context" $ ) }} + {{- end }} + {{- if .Values.datasources.secretName }} + - name: datasources + secret: + secretName: {{ .Values.datasources.secretName }} + {{- else if .Values.datasources.secretDefinition }} + - name: datasources + secret: + secretName: {{ include "common.names.fullname" . }}-datasources + {{- end }} + {{- if .Values.notifiers.configMapName }} + - name: notifiers + configMap: + name: {{ .Values.notifiers.configMapName }} + {{- end }} + {{- if .Values.alerting.configMapName }} + - name: alerting + configMap: + name: {{ .Values.alerting.configMapName }} + {{- end }} + {{- if .Values.config.useGrafanaIniFile }} + - name: grafana-ini + {{- if .Values.config.grafanaIniConfigMap }} + configMap: + name: {{ .Values.config.grafanaIniConfigMap }} + {{- else if .Values.config.grafanaIniSecret }} + secret: + secretName: {{ .Values.config.grafanaIniSecret }} + {{- end }} + {{- end }} + {{- if and .Values.ldap.tls.enabled .Values.ldap.tls.certificatesSecret }} + - name: ldap-tls + secret: + secretName: {{ .Values.ldap.tls.certificatesSecret }} + {{- end }} + {{- range .Values.grafana.extraConfigmaps }} + - name: {{ .name }} + configMap: + name: {{ .name }} + {{- end }} + {{- if .Values.grafana.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.grafana.extraVolumes "context" $) | nindent 8 }} + {{- end }} diff --git a/backing-services/grafana/templates/extra-list.yaml b/backing-services/grafana/templates/extra-list.yaml new file mode 100644 index 0000000..2d35a58 --- /dev/null +++ b/backing-services/grafana/templates/extra-list.yaml @@ -0,0 +1,9 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/backing-services/grafana/templates/ingress.yaml b/backing-services/grafana/templates/ingress.yaml new file mode 100644 index 0000000..3fc9a0f --- /dev/null +++ b/backing-services/grafana/templates/ingress.yaml @@ -0,0 +1,66 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.ingress.enabled -}} +apiVersion: {{ include "common.capabilities.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: grafana + annotations: + {{- if .Values.ingress.certManager }} + kubernetes.io/tls-acme: "true" + {{- end }} + {{- if or .Values.ingress.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.ingress.annotations .Values.commonAnnotations ) "context" . ) }} + {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.ingressClassName (eq "true" (include "common.ingress.supportsIngressClassname" .)) }} + ingressClassName: {{ .Values.ingress.ingressClassName | quote }} + {{- end }} + rules: + {{- if .Values.ingress.hostname }} + - http: + paths: + {{- if .Values.ingress.extraPaths }} + {{- toYaml .Values.ingress.extraPaths | nindent 10 }} + {{- end }} + - path: {{ .Values.ingress.path }} + {{- if eq "true" (include "common.ingress.supportsPathType" .) }} + pathType: {{ .Values.ingress.pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" .) "servicePort" "http" "context" $) | nindent 14 }} + {{- if ne .Values.ingress.hostname "*" }} + host: {{ include "common.tplvalues.render" (dict "value" .Values.ingress.hostname "context" $) }} + {{- end }} + {{- end }} + {{- range .Values.ingress.extraHosts }} + - host: {{ .name | quote }} + http: + paths: + - path: {{ default "/" .path }} + {{- if eq "true" (include "common.ingress.supportsPathType" $) }} + pathType: {{ default "ImplementationSpecific" .pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" $) "servicePort" "http" "context" $) | nindent 14 }} + {{- end }} + {{- if .Values.ingress.extraRules }} + {{- include "common.tplvalues.render" (dict "value" .Values.ingress.extraRules "context" $) | nindent 4 }} + {{- end }} + {{- if or (and .Values.ingress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.ingress.annotations )) .Values.ingress.selfSigned)) .Values.ingress.extraTls }} + tls: + {{- if and .Values.ingress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.ingress.annotations )) .Values.ingress.selfSigned) }} + - hosts: + - {{ .Values.ingress.hostname | quote }} + secretName: {{ printf "%s-tls" .Values.ingress.hostname }} + {{- end }} + {{- if .Values.ingress.extraTls }} + {{- include "common.tplvalues.render" ( dict "value" .Values.ingress.extraTls "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/grafana/templates/ldap-secret.yaml b/backing-services/grafana/templates/ldap-secret.yaml new file mode 100644 index 0000000..f14ae7f --- /dev/null +++ b/backing-services/grafana/templates/ldap-secret.yaml @@ -0,0 +1,25 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.ldap.enabled (or (not (empty .Values.ldap.configuration)) (not (empty .Values.ldap.uri))) (empty .Values.ldap.configMapName) (empty .Values.ldap.secretName) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ printf "%s-ldap-conf" (include "common.names.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: grafana + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + {{if .Values.ldap.configuration }} + ldap.toml: |- + {{- include "common.tplvalues.render" (dict "value" .Values.ldap.configuration "context" $) | b64enc | nindent 4 }} + {{- else }} + ldap.toml: |- + {{- include "grafana.ldap.config" . | b64enc | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/grafana/templates/prometheusrules.yaml b/backing-services/grafana/templates/prometheusrules.yaml new file mode 100644 index 0000000..84927a2 --- /dev/null +++ b/backing-services/grafana/templates/prometheusrules.yaml @@ -0,0 +1,24 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ default .Release.Namespace .Values.metrics.prometheusRule.namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: metrics + {{- if .Values.metrics.prometheusRule.additionalLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.prometheusRule.additionalLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + groups: + - name: {{ include "common.names.fullname" . }} + rules: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.prometheusRule.rules "context" $ ) | nindent 6 }} +{{- end }} diff --git a/backing-services/grafana/templates/pvc.yaml b/backing-services/grafana/templates/pvc.yaml new file mode 100644 index 0000000..70dd987 --- /dev/null +++ b/backing-services/grafana/templates/pvc.yaml @@ -0,0 +1,31 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: grafana + {{- if or .Values.persistence.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.persistence.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + accessModes: + {{- if not (empty .Values.persistence.accessModes) }} + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + {{- else }} + - {{ .Values.persistence.accessMode | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{ include "grafana.storageClass" . }} +{{- end -}} diff --git a/backing-services/grafana/templates/secret.yaml b/backing-services/grafana/templates/secret.yaml new file mode 100644 index 0000000..a6c5cf3 --- /dev/null +++ b/backing-services/grafana/templates/secret.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "grafana.createAdminSecret" .) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }}-admin + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: grafana + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + GF_SECURITY_ADMIN_PASSWORD: {{ ternary (randAlphaNum 10) .Values.admin.password (empty .Values.admin.password) | b64enc | quote }} +{{- end }} diff --git a/backing-services/grafana/templates/service.yaml b/backing-services/grafana/templates/service.yaml new file mode 100644 index 0000000..4120acf --- /dev/null +++ b/backing-services/grafana/templates/service.yaml @@ -0,0 +1,61 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: grafana + {{- if or (and .Values.metrics.enabled .Values.metrics.service.annotations) .Values.service.annotations .Values.commonAnnotations }} + annotations: + {{- if or .Values.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.service.annotations .Values.commonAnnotations ) "context" . ) }} + {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.service.annotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.service.annotations "context" $) | nindent 4 }} + {{- end }} + {{- end }} +spec: + type: {{ .Values.service.type }} + {{- if and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerClass)) }} + loadBalancerClass: {{ .Values.service.loadBalancerClass }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ .Values.service.loadBalancerSourceRanges }} + {{- end }} + {{- if and .Values.service.clusterIP (eq .Values.service.type "ClusterIP") }} + clusterIP: {{ .Values.service.clusterIP }} + {{- end }} + {{- if or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if .Values.service.sessionAffinity }} + sessionAffinity: {{ .Values.service.sessionAffinity }} + {{- end }} + {{- if .Values.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + ports: + - port: {{ .Values.service.ports.grafana }} + targetPort: dashboard + protocol: TCP + name: http + {{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.grafana)) }} + nodePort: {{ .Values.service.nodePorts.grafana }} + {{- else if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.grafana.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: grafana diff --git a/backing-services/grafana/templates/serviceaccount.yaml b/backing-services/grafana/templates/serviceaccount.yaml new file mode 100644 index 0000000..5dfefe1 --- /dev/null +++ b/backing-services/grafana/templates/serviceaccount.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "grafana.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +secrets: + - name: {{ include "common.names.fullname" . }}-admin + {{- if .Values.datasources.secretName }} + - name: {{ .Values.datasources.secretName }} + {{- else if .Values.datasources.secretDefinition }} + - name: {{ include "common.names.fullname" . }}-datasources + {{- end }} + {{- if (include "grafana.createSMTPSecret" .) }} + - name: {{ include "common.names.fullname" . }}-smtp + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/backing-services/grafana/templates/servicemonitor.yaml b/backing-services/grafana/templates/servicemonitor.yaml new file mode 100644 index 0000000..65aeb0c --- /dev/null +++ b/backing-services/grafana/templates/servicemonitor.yaml @@ -0,0 +1,50 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ default .Release.Namespace .Values.metrics.serviceMonitor.namespace | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.serviceMonitor.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + {{- if .Values.metrics.serviceMonitor.additionalLabels }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.serviceMonitor.additionalLabels "context" $) | nindent 4 }} + {{- end }} + app.kubernetes.io/component: grafana + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.metrics.serviceMonitor.jobLabel }} + jobLabel: {{ .Values.metrics.serviceMonitor.jobLabel }} + {{- end }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + {{- if .Values.metrics.serviceMonitor.selector }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.serviceMonitor.selector "context" $) | nindent 6 }} + {{- end }} + app.kubernetes.io/component: grafana + endpoints: + - port: http + path: "/metrics" + {{- if .Values.metrics.serviceMonitor.interval }} + interval: {{ .Values.metrics.serviceMonitor.interval }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} + {{- end }} + honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }} + {{- if .Values.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.metricRelabelings "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.relabelings }} + relabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.relabelings "context" $) | nindent 8 }} + {{- end }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace | quote }} +{{- end }} diff --git a/backing-services/grafana/templates/smtp-secret.yaml b/backing-services/grafana/templates/smtp-secret.yaml new file mode 100644 index 0000000..33aeb57 --- /dev/null +++ b/backing-services/grafana/templates/smtp-secret.yaml @@ -0,0 +1,21 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "grafana.createSMTPSecret" .) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }}-smtp + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: grafana + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + GF_SMTP_USER: {{ .Values.smtp.user | b64enc | quote }} + GF_SMTP_PASSWORD: {{ .Values.smtp.password | b64enc | quote }} +{{- end }} diff --git a/backing-services/grafana/templates/tls-secret.yaml b/backing-services/grafana/templates/tls-secret.yaml new file mode 100644 index 0000000..c25cb95 --- /dev/null +++ b/backing-services/grafana/templates/tls-secret.yaml @@ -0,0 +1,46 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.ingress.enabled }} +{{- if .Values.ingress.secrets }} +{{- range .Values.ingress.secrets }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .name }} + namespace: {{ $.Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $.Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: grafana + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ .certificate | b64enc }} + tls.key: {{ .key | b64enc }} +--- +{{- end }} +{{- end }} +{{- if and .Values.ingress.tls .Values.ingress.selfSigned }} +{{- $secretName := printf "%s-tls" .Values.ingress.hostname }} +{{- $ca := genCA "grafana-ca" 365 }} +{{- $cert := genSignedCert .Values.ingress.hostname nil (list .Values.ingress.hostname) 365 $ca }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: grafana + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.crt" "defaultValue" $cert.Cert "context" $) }} + tls.key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.key" "defaultValue" $cert.Key "context" $) }} + ca.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }} +{{- end }} +{{- end }} diff --git a/backing-services/grafana/values.yaml b/backing-services/grafana/values.yaml new file mode 100644 index 0000000..d6b337f --- /dev/null +++ b/backing-services/grafana/values.yaml @@ -0,0 +1,919 @@ +# Copyright VMware, Inc. +# SPDX-License-Identifier: APACHE-2.0 + +## @section Global parameters +## 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, imagePullSecrets and storageClass + +## @param global.imageRegistry Global Docker image registry +## @param global.imagePullSecrets Global Docker registry secret names as an array +## @param global.storageClass Global StorageClass for Persistent Volume(s) +## +global: + imageRegistry: "" + ## E.g. + ## imagePullSecrets: + ## - myRegistryKeySecretName + ## + imagePullSecrets: [] + storageClass: "" + +## @section Common parameters + +## @param kubeVersion Force target Kubernetes version (using Helm capabilities if not set) +## +kubeVersion: "" +## @param extraDeploy Array of extra objects to deploy with the release +## +extraDeploy: [] +## @param nameOverride String to partially override grafana.fullname template (will maintain the release name) +## +nameOverride: "" +## @param fullnameOverride String to fully override grafana.fullname template +## +fullnameOverride: "" +## @param clusterDomain Default Kubernetes cluster domain +## +clusterDomain: cluster.local +## @param commonLabels Labels to add to all deployed objects +## +commonLabels: {} +## @param commonAnnotations Annotations to add to all deployed objects +## +commonAnnotations: {} + +## @section Grafana parameters + +## Bitnami Grafana image version +## ref: https://hub.docker.com/r/bitnami/grafana/tags/ +## @param image.registry [default: REGISTRY_NAME] Grafana image registry +## @param image.repository [default: REPOSITORY_NAME/grafana] Grafana image repository +## @skip image.tag Grafana image tag (immutable tags are recommended) +## @param image.digest Grafana image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag +## @param image.pullPolicy Grafana image pull policy +## @param image.pullSecrets Grafana image pull secrets +## +image: + registry: docker.io + repository: bitnami/grafana + tag: 10.2.3-debian-11-r0 + digest: "" + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://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 + pullSecrets: [] +## Admin credentials configuration +## +admin: + ## @param admin.user Grafana admin username + ## + user: "admin" + ## @param admin.password Admin password. If a password is not provided a random password will be generated + ## + password: "" + ## @param admin.existingSecret Name of the existing secret containing admin password + ## + existingSecret: "" + ## @param admin.existingSecretPasswordKey Password key on the existing secret + ## + existingSecretPasswordKey: password +## SMTP configuration +## +smtp: + ## @param smtp.enabled Enable SMTP configuration + ## + enabled: false + ## @param smtp.user SMTP user + ## + user: user + ## @param smtp.password SMTP password + ## + password: password + ## @param smtp.host Custom host for the smtp server + ## e.g: + ## host: mysmtphost.com + ## + host: "" + ## @param smtp.fromAddress From address + ## + fromAddress: "" + ## @param smtp.fromName From name + ## + fromName: "" + ## @param smtp.skipVerify Enable skip verify + ## + skipVerify: "false" + ## @param smtp.existingSecret Name of existing secret containing SMTP credentials (user and password) + ## + existingSecret: "" + ## @param smtp.existingSecretUserKey User key on the existing secret + ## + existingSecretUserKey: user + ## @param smtp.existingSecretPasswordKey Password key on the existing secret + ## + existingSecretPasswordKey: password +## @param plugins Grafana plugins to be installed in deployment time separated by commas +## Specify plugins as a list separated by commas ( you will need to scape them when specifying from command line ) +## Example: +## plugins: grafana-kubernetes-app,grafana-example-app +## +plugins: "" +## Ldap configuration for Grafana +## +ldap: + ## @param ldap.enabled Enable LDAP for Grafana + ## + enabled: false + ## @param ldap.allowSignUp Allows LDAP sign up for Grafana + ## + allowSignUp: false + ## @param ldap.configuration Specify content for ldap.toml configuration file + ## e.g: + ## configuration: |- + ## [[servers]] + ## host = "127.0.0.1" + ## port = 389 + ## use_ssl = false + ## ... + ## + configuration: "" + ## @param ldap.configMapName Name of the ConfigMap with the ldap.toml configuration file for Grafana + ## NOTE: When it's set the ldap.configuration parameter is ignored + ## + configMapName: "" + ## @param ldap.secretName Name of the Secret with the ldap.toml configuration file for Grafana + ## NOTE: When it's set the ldap.configuration parameter is ignored + ## + secretName: "" + ## @param ldap.uri Server URI, eg. ldap://ldap_server:389 + ## + uri: "" + ## @param ldap.binddn DN of the account used to search in the LDAP server. + ## + binddn: "" + ## @param ldap.bindpw Password for binddn account. + ## + bindpw: "" + ## @param ldap.basedn Base DN path where binddn account will search for the users. + ## + basedn: "" + ## @param ldap.searchAttribute Field used to match with the user name (uid, samAccountName, cn, etc). This value will be ignored if 'ldap.searchFilter' is set + ## + searchAttribute: "uid" + ## @param ldap.searchFilter User search filter, for example "(cn=%s)" or "(sAMAccountName=%s)" or "(|(sAMAccountName=%s)(userPrincipalName=%s)" + ## + searchFilter: "" + ## @param ldap.extraConfiguration Extra ldap configuration. + ## Example: + ## extraConfiguration: |- + ## # set to true if you want to skip SSL cert validation + ## ssl_skip_verify = false + ## # group_search_filter = "(&(objectClass=posixGroup)(memberUid=%s))" + ## # group_search_filter_user_attribute = "distinguishedName" + ## # group_search_base_dns = ["ou=groups,dc=grafana,dc=org"] + ## # Specify names of the LDAP attributes your LDAP uses + ## [servers.attributes] + ## # member_of = "memberOf" + ## # email = "email" + ## + extraConfiguration: "" + ## @param ldap.tls.enabled Enabled TLS configuration. + ## @param ldap.tls.startTls Use STARTTLS instead of LDAPS. + ## @param ldap.tls.skipVerify Skip any SSL verification (hostanames or certificates) + ## @param ldap.tls.certificatesMountPath Where LDAP certifcates are mounted. + ## @param ldap.tls.certificatesSecret Secret with LDAP certificates. + ## @param ldap.tls.CAFilename CA certificate filename. Should match with the CA entry key in the ldap.tls.certificatesSecret. + ## @param ldap.tls.certFilename Client certificate filename to authenticate against the LDAP server. Should match with certificate the entry key in the ldap.tls.certificatesSecret. + ## @param ldap.tls.certKeyFilename Client Key filename to authenticate against the LDAP server. Should match with certificate the entry key in the ldap.tls.certificatesSecret. + ## + tls: + enabled: false + startTls: false + skipVerify: false + certificatesMountPath: /opt/bitnami/grafana/conf/ldap/ + certificatesSecret: "" + CAFilename: "" + certFilename: "" + certKeyFilename: "" +## Grafana Image Renderer configuration for Grafana +## +imageRenderer: + ## @param imageRenderer.enabled Enable using a remote rendering service to render PNG images + ## + enabled: false + ## @param imageRenderer.serverURL URL of the remote rendering service + ## + serverURL: "" + ## @param imageRenderer.callbackURL URL of the callback service + ## + callbackURL: "" + +## Parameters to override the default grafana.ini file. +## It is needed to create a configmap or a secret containing the grafana.ini file. +## @param config.useGrafanaIniFile Allows to load a `grafana.ini` file +## @param config.grafanaIniConfigMap Name of the ConfigMap containing the `grafana.ini` file +## @param config.grafanaIniSecret Name of the Secret containing the `grafana.ini` file +## +config: + useGrafanaIniFile: false + grafanaIniConfigMap: "" + grafanaIniSecret: "" +## Create dasboard provider to load dashboards, a default one is created to load dashboards +## from "/opt/bitnami/grafana/dashboards" +## @param dashboardsProvider.enabled Enable the use of a Grafana dashboard provider +## @param dashboardsProvider.configMapName Name of a ConfigMap containing a custom dashboard provider +## +dashboardsProvider: + enabled: false + ## Important to set the Path to "/opt/bitnami/grafana/dashboards" + ## Evaluated as a template. + ## + configMapName: "" +## @param dashboardsConfigMaps Array with the names of a series of ConfigMaps containing dashboards files +## They will be mounted by the default dashboard provider if it is enabled +## Use an array with the configMap names. +## In order to use subfolders, uncomment "#foldersFromFilesStructure: true" line in default provider config. or create your own dashboard provider. +## Example: +## dashboardsConfigMaps: +## - configMapName: mydashboard +## folderName: foo +## fileName: mydashboard.json +## - configMapName: myotherdashboard +## folderName: bar +## fileName: myotherdashboard.json +## +dashboardsConfigMaps: [] +## Import datasources from an externally-managed secret, or a secret definition set via Helm values. +## +datasources: + ## @param datasources.secretName The name of an externally-managed secret containing custom datasource files. + ## + secretName: "" + ## @param datasources.secretDefinition The contents of a secret defining a custom datasource file. Only used if datasources.secretName is empty or not defined. + ## Example: + ## secretDefinition: + ## apiVersion: 1 + ## datasources: + ## - name: Prometheus + ## type: prometheus + ## url: http://prometheus-prometheus-server + ## access: proxy + ## isDefault: true + ## + secretDefinition: {} + +## Create notifiers from a configMap +## The notifiersName must contain the files +## @param notifiers.configMapName Name of a ConfigMap containing Grafana notifiers configuration +## +notifiers: + configMapName: "" + +## Create alerting rules, contact points, notification policies, templates, and mute timings from a configMap +## @param alerting.configMapName Name of a ConfigMap containing Grafana alerting configuration +## +alerting: + configMapName: "" + +## @section Grafana Deployment parameters + +grafana: + ## @param grafana.replicaCount Number of Grafana nodes + ## + replicaCount: 1 + ## @param grafana.updateStrategy.type Set up update strategy for Grafana installation. + ## Set to Recreate if you use persistent volume that cannot be mounted by more than one pods to make sure the pods is destroyed first. + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy + ## Example: + ## updateStrategy: + ## type: RollingUpdate + ## rollingUpdate: + ## maxSurge: 25% + ## maxUnavailable: 25% + ## + updateStrategy: + type: RollingUpdate + ## @param grafana.hostAliases Add deployment host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param grafana.schedulerName Alternative scheduler + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param grafana.terminationGracePeriodSeconds In seconds, time the given to the Grafana pod needs to terminate gracefully + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods + ## + terminationGracePeriodSeconds: "" + ## @param grafana.priorityClassName Priority class name + ## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ + ## + priorityClassName: "" + ## @param grafana.podLabels Extra labels for Grafana pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param grafana.podAnnotations Grafana Pod annotations + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param grafana.podAffinityPreset Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param grafana.podAntiAffinityPreset Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## @param grafana.containerPorts.grafana Grafana container port + ## + containerPorts: + grafana: 3000 + ## @param grafana.extraPorts Extra ports for Grafana deployment + ## + extraPorts: [] + ## Node affinity preset + ## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## @param grafana.nodeAffinityPreset.type Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## @param grafana.nodeAffinityPreset.key Node label key to match Ignored if `affinity` is set. + ## @param grafana.nodeAffinityPreset.values Node label values to match. Ignored if `affinity` is set. + ## + nodeAffinityPreset: + type: "" + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param grafana.affinity Affinity for pod assignment + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## Note: podAffinityPreset, podAntiAffinityPreset, and nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## @param grafana.nodeSelector Node labels for pod assignment + ## Ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + ## @param grafana.tolerations Tolerations for pod assignment + ## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param grafana.topologySpreadConstraints Topology spread constraints rely on node labels to identify the topology domain(s) that each Node is in + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## + ## topologySpreadConstraints: + ## - maxSkew: 1 + ## topologyKey: failure-domain.beta.kubernetes.io/zone + ## whenUnsatisfiable: DoNotSchedule + ## + topologySpreadConstraints: [] + ## @param grafana.podSecurityContext.enabled Enable securityContext on for Grafana deployment + ## @param grafana.podSecurityContext.fsGroup Group to configure permissions for volumes + ## + podSecurityContext: + enabled: true + fsGroup: 1001 + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param grafana.containerSecurityContext.enabled Enabled containers' Security Context + ## @param grafana.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param grafana.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param grafana.containerSecurityContext.privileged Set container's Security Context privileged + ## @param grafana.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param grafana.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param grafana.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param grafana.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: false + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## Grafana containers' resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-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:'. + ## @param grafana.resources.limits The resources limits for Grafana containers + ## @param grafana.resources.requests The requested resources for Grafana containers + ## + resources: + ## Example: + ## limits: + ## cpu: 500m + ## memory: 1Gi + limits: {} + ## Examples: + ## requests: + ## cpu: 250m + ## memory: 256Mi + requests: {} + ## Grafana containers' liveness probe + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param grafana.livenessProbe.enabled Enable livenessProbe + ## @param grafana.livenessProbe.path Path for livenessProbe + ## @param grafana.livenessProbe.scheme Scheme for livenessProbe + ## @param grafana.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param grafana.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param grafana.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param grafana.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param grafana.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + path: /api/health + scheme: HTTP + initialDelaySeconds: 120 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## Grafana containers' readinessProbe probe + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param grafana.readinessProbe.enabled Enable readinessProbe + ## @param grafana.readinessProbe.path Path for readinessProbe + ## @param grafana.readinessProbe.scheme Scheme for readinessProbe + ## @param grafana.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param grafana.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param grafana.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param grafana.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param grafana.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + path: /api/health + scheme: HTTP + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param grafana.startupProbe.enabled Enable startupProbe + ## @param grafana.startupProbe.path Path for readinessProbe + ## @param grafana.startupProbe.scheme Scheme for readinessProbe + ## @param grafana.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param grafana.startupProbe.periodSeconds Period seconds for startupProbe + ## @param grafana.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param grafana.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param grafana.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + path: /api/health + scheme: HTTP + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param grafana.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param grafana.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param grafana.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param grafana.lifecycleHooks for the Grafana container(s) to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param grafana.sidecars Attach additional sidecar containers to the Grafana pod + ## Example: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param grafana.initContainers Add additional init containers to the Grafana pod(s) + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + ## e.g: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## command: ['sh', '-c', 'echo "hello world"'] + ## + initContainers: [] + ## @param grafana.extraVolumes Additional volumes for the Grafana pod + ## Example: + ## extraVolumes: + ## - name: my-volume + ## emptyDir: {} + ## + extraVolumes: [] + ## @param grafana.extraVolumeMounts Additional volume mounts for the Grafana container + ## Example: + ## extraVolumeMounts: + ## - name: my-volume + ## mountPath: /opt/bitnami/grafana/my-stuff + ## + extraVolumeMounts: [] + ## @param grafana.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for Grafana nodes + ## + extraEnvVarsCM: "" + ## @param grafana.extraEnvVarsSecret Name of existing Secret containing extra env vars for Grafana nodes + ## + extraEnvVarsSecret: "" + ## @param grafana.extraEnvVars Array containing extra env vars to configure Grafana + ## For example: + ## extraEnvVars: + ## - name: GF_DEFAULT_INSTANCE_NAME + ## value: my-instance + ## + extraEnvVars: [] + ## @param grafana.extraConfigmaps Array to mount extra ConfigMaps to configure Grafana + ## For example: + ## extraConfigmaps: + ## - name: myconfigmap + ## mountPath: /opt/bitnami/desired-path + ## subPath: file-name.extension (optional) + ## readOnly: true + ## + extraConfigmaps: [] + ## @param grafana.command Override default container command (useful when using custom images) + ## + command: [] + ## @param grafana.args Override default container args (useful when using custom images) + ## + args: [] + +## @section Persistence parameters + +## Enable persistence using Persistent Volume Claims +## ref: https://kubernetes.io/docs/user-guide/persistent-volumes/ +## @param persistence.enabled Enable persistence +## @param persistence.annotations Persistent Volume Claim annotations +## @param persistence.accessMode Persistent Volume Access Mode +## @param persistence.accessModes Persistent Volume Access Modes +## @param persistence.storageClass Storage class to use with the PVC +## @param persistence.existingClaim If you want to reuse an existing claim, you can pass the name of the PVC using the existingClaim variable +## @param persistence.size Size for the PV +## +persistence: + enabled: true + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + storageClass: "" + annotations: {} + existingClaim: "" + accessMode: ReadWriteOnce + accessModes: [] + size: 10Gi + +## @section RBAC parameters + +## @param serviceAccount.create Specifies whether a ServiceAccount should be created +## @param serviceAccount.name The name of the ServiceAccount to use. If not set and create is true, a name is generated using the fullname template +## @param serviceAccount.annotations Annotations to add to the ServiceAccount Metadata +## @param serviceAccount.automountServiceAccountToken Automount service account token for the application controller service account +serviceAccount: + create: true + name: "" + annotations: {} + automountServiceAccountToken: false + +## @section Traffic exposure parameters + +## Service parameters +## +service: + ## @param service.type Kubernetes Service type + ## + type: ClusterIP + ## @param service.clusterIP Grafana service Cluster IP + ## e.g.: + ## clusterIP: None + ## + clusterIP: "" + ## @param service.ports.grafana Grafana service port + ## + ports: + grafana: 3000 + ## @param service.nodePorts.grafana Specify the nodePort value for the LoadBalancer and NodePort service types + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + nodePorts: + grafana: "" + ## @param service.loadBalancerIP loadBalancerIP if Grafana service type is `LoadBalancer` (optional, cloud specific) + ## ref: https://kubernetes.io/docs/user-guide/services/#type-loadbalancer + ## + loadBalancerIP: "" + ## @param service.loadBalancerClass loadBalancerClass if Grafana service type is `LoadBalancer` (optional, cloud specific) + ## ref: https://kubernetes.io/docs/user-guide/services/#type-loadbalancer + ## + loadBalancerClass: "" + ## @param service.loadBalancerSourceRanges loadBalancerSourceRanges if Grafana service type is `LoadBalancer` (optional, cloud specific) + ## ref: https://kubernetes.io/docs/user-guide/services/#type-loadbalancer + ## e.g: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param service.annotations Provide any additional annotations which may be required. + ## This can be used to set the LoadBalancer service type to internal only. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + annotations: {} + ## @param service.externalTrafficPolicy Grafana service external traffic policy + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param service.extraPorts Extra port to expose on Grafana service + ## + extraPorts: [] + ## @param service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} +## Configure the ingress resource that allows you to access the +## Grafana installation. Set up the URL +## ref: https://kubernetes.io/docs/user-guide/ingress/ +## +ingress: + ## @param ingress.enabled Set to true to enable ingress record generation + ## + enabled: false + ## DEPRECATED: Use ingress.annotations instead of ingress.certManager + ## certManager: false + ## + + ## @param ingress.pathType Ingress Path type + ## + pathType: ImplementationSpecific + ## @param ingress.apiVersion Override API Version (automatically detected if not set) + ## + apiVersion: "" + ## @param ingress.hostname When the ingress is enabled, a host pointing to this will be created + ## + hostname: grafana.local + ## @param ingress.path Default path for the ingress resource + ## The Path to Grafana. You may need to set this to '/*' in order to use this with ALB ingress controllers. + ## + path: / + ## @param ingress.annotations Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. + ## For a full list of possible ingress annotations, please see + ## ref: https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md + ## Use this parameter to set the required annotations for cert-manager, see + ## ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations + ## + ## e.g: + ## annotations: + ## kubernetes.io/ingress.class: nginx + ## cert-manager.io/cluster-issuer: cluster-issuer-name + ## + annotations: {} + ## @param ingress.tls Enable TLS configuration for the hostname defined at ingress.hostname parameter + ## TLS certificates will be retrieved from a TLS secret with name: {{- printf "%s-tls" .Values.ingress.hostname }} + ## You can use the ingress.secrets parameter to create this TLS secret or relay on cert-manager to create it + ## + tls: false + ## @param ingress.extraHosts The list of additional hostnames to be covered with this ingress record. + ## Most likely the hostname above will be enough, but in the event more hosts are needed, this is an array + ## extraHosts: + ## - name: grafana.local + ## path: / + ## + extraHosts: [] + ## @param ingress.extraPaths Any additional arbitrary paths that may need to be added to the ingress under the main host. + ## For example: The ALB ingress controller requires a special rule for handling SSL redirection. + ## extraPaths: + ## - path: /* + ## backend: + ## serviceName: ssl-redirect + ## servicePort: use-annotation + ## + extraPaths: [] + ## @param ingress.extraTls The tls configuration for additional hostnames to be covered with this ingress record. + ## see: https://kubernetes.io/docs/concepts/services-networking/ingress/#tls + ## extraTls: + ## - hosts: + ## - grafana.local + ## secretName: grafana.local-tls + ## + extraTls: [] + ## @param ingress.secrets If you're providing your own certificates, please use this to add the certificates as secrets + ## key and certificate should start with -----BEGIN CERTIFICATE----- or + ## -----BEGIN RSA PRIVATE KEY----- + ## + ## name should line up with a tlsSecret set further up + ## If you're using cert-manager, this is unneeded, as it will create the secret for you if it is not set + ## + ## @param ingress.secrets It is also possible to create and manage the certificates outside of this helm chart + ## Please see README.md for more information + ## e.g: + ## - name: grafana.local-tls + ## key: + ## certificate: + ## + secrets: [] + ## @param ingress.selfSigned Create a TLS secret for this ingress record using self-signed certificates generated by Helm + ## + selfSigned: false + ## @param ingress.ingressClassName IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+) + ingressClassName: "" + ## @param ingress.extraRules Additional rules to be covered with this ingress record + ## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-rules + ## e.g: + ## extraRules: + ## - host: example.local + ## http: + ## path: / + ## backend: + ## service: + ## name: example-svc + ## port: + ## name: http + ## + extraRules: [] + +## @section Metrics parameters + +## Prometheus metrics +## +metrics: + ## @param metrics.enabled Enable the export of Prometheus metrics + ## + enabled: false + ## Prometheus Operator ServiceMonitor configuration + ## @param metrics.service.annotations [object] Annotations for Prometheus metrics service + ## + service: + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "3000" + prometheus.io/path: "/metrics" + serviceMonitor: + ## @param metrics.serviceMonitor.enabled if `true`, creates a Prometheus Operator ServiceMonitor (also requires `metrics.enabled` to be `true`) + ## + enabled: false + ## @param metrics.serviceMonitor.namespace Namespace in which Prometheus is running + ## + namespace: "" + ## @param metrics.serviceMonitor.interval Interval at which metrics should be scraped. + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint + ## e.g: + ## interval: 10s + ## + interval: "" + ## @param metrics.serviceMonitor.scrapeTimeout Timeout after which the scrape is ended + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint + ## e.g: + ## scrapeTimeout: 10s + ## + scrapeTimeout: "" + ## @param metrics.serviceMonitor.selector Prometheus instance selector labels + ## ref: https://github.com/bitnami/charts/tree/main/bitnami/prometheus-operator#prometheus-configuration + ## e.g: + ## selector: + ## prometheus: my-prometheus + ## + selector: {} + ## @param metrics.serviceMonitor.relabelings RelabelConfigs to apply to samples before scraping + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#relabelconfig + ## + relabelings: [] + ## @param metrics.serviceMonitor.metricRelabelings MetricRelabelConfigs to apply to samples before ingestion + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#relabelconfig + ## + metricRelabelings: [] + ## @param metrics.serviceMonitor.honorLabels Labels to honor to add to the scrape endpoint + ## + honorLabels: false + ## DEPRECATED metrics.serviceMonitor.additionalLabels - It will be removed in a future release, please use metrics.serviceMonitor.labels instead + ## @param metrics.serviceMonitor.labels Additional custom labels for the ServiceMonitor + ## + labels: {} + ## @param metrics.serviceMonitor.jobLabel The name of the label on the target service to use as the job name in prometheus. + ## + jobLabel: "" + ## Prometheus Operator PrometheusRule configuration + ## + prometheusRule: + ## @param metrics.prometheusRule.enabled if `true`, creates a Prometheus Operator PrometheusRule (also requires `metrics.enabled` to be `true` and `metrics.prometheusRule.rules`) + ## + enabled: false + ## @param metrics.prometheusRule.namespace Namespace for the PrometheusRule Resource (defaults to the Release Namespace) + ## + namespace: "" + ## @param metrics.prometheusRule.additionalLabels Additional labels that can be used so PrometheusRule will be discovered by Prometheus + ## + additionalLabels: {} + ## @param metrics.prometheusRule.rules PrometheusRule rules to configure + ## e.g: + ## - alert: Grafana-Down + ## annotations: + ## message: 'Grafana instance is down' + ## summary: Grafana instance is down + ## expr: absent(up{job="grafana"} == 1) + ## labels: + ## severity: warning + ## service: grafana + ## for: 5m + ## + rules: [] + +## @section Volume permissions init Container Parameters + +## 'volumePermissions' init container parameters +## Changes the owner and group of the persistent volume mount point to runAsUser:fsGroup values +## based on the `grafana:podSecurityContext`/`grafana:containerSecurityContext`` parameters +## May require setting `grafana:podSecurityContext:runAsNonRoot` to false +## +volumePermissions: + ## @param volumePermissions.enabled Enable init container that changes the owner/group of the PV mount point to `runAsUser:fsGroup` + ## + enabled: false + ## OS Shell + Utility image + ## ref: https://hub.docker.com/r/bitnami/os-shell/tags/ + ## @param volumePermissions.image.registry [default: REGISTRY_NAME] OS Shell + Utility image registry + ## @param volumePermissions.image.repository [default: REPOSITORY_NAME/os-shell] OS Shell + Utility image repository + ## @skip volumePermissions.image.tag OS Shell + Utility image tag (immutable tags are recommended) + ## @param volumePermissions.image.digest OS Shell + Utility image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param volumePermissions.image.pullPolicy OS Shell + Utility image pull policy + ## @param volumePermissions.image.pullSecrets OS Shell + Utility image pull secrets + ## + image: + registry: docker.io + repository: bitnami/os-shell + tag: 11-debian-11-r92 + digest: "" + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Init container's resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param volumePermissions.resources.limits The resources limits for the init container + ## @param volumePermissions.resources.requests The requested resources for the init container + ## + resources: + limits: {} + requests: {} + ## Init container Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param volumePermissions.containerSecurityContext.runAsUser Set init container's Security Context runAsUser + ## NOTE: when runAsUser is set to special value "auto", init container will try to chown the + ## data folder to auto-determined user&group, using commands: `id -u`:`id -G | cut -d" " -f2` + ## "auto" is especially useful for OpenShift which has scc with dynamic user ids (and 0 is not allowed) + ## + containerSecurityContext: + runAsUser: 0 + +## @section Diagnostic Mode Parameters + +## Enable diagnostic mode in the deployment +## +diagnosticMode: + ## @param diagnosticMode.enabled Enable diagnostic mode (all probes will be disabled and the command will be overridden) + ## + enabled: false + ## @param diagnosticMode.command Command to override all containers in the deployment + ## + command: + - sleep + ## @param diagnosticMode.args Args to override all containers in the deployment + ## + args: + - infinity diff --git a/backing-services/ingress-nginx/.helmignore b/backing-services/ingress-nginx/.helmignore new file mode 100644 index 0000000..109b408 --- /dev/null +++ b/backing-services/ingress-nginx/.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 +.vscode/ +__snapshot__ diff --git a/backing-services/ingress-nginx/Chart.yaml b/backing-services/ingress-nginx/Chart.yaml new file mode 100644 index 0000000..1f01284 --- /dev/null +++ b/backing-services/ingress-nginx/Chart.yaml @@ -0,0 +1,25 @@ +annotations: + artifacthub.io/changes: | + - Update Ingress-Nginx version controller-v1.11.3 + artifacthub.io/prerelease: "false" +apiVersion: v2 +appVersion: 1.11.3 +description: Ingress controller for Kubernetes using NGINX as a reverse proxy and + load balancer +home: https://github.com/kubernetes/ingress-nginx +icon: https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Nginx_logo.svg/500px-Nginx_logo.svg.png +keywords: +- ingress +- nginx +kubeVersion: '>=1.21.0-0' +maintainers: +- name: cpanato +- name: Gacko +- name: puerco +- name: rikatz +- name: strongjz +- name: tao12345666333 +name: ingress-nginx +sources: +- https://github.com/kubernetes/ingress-nginx +version: 4.11.3 diff --git a/backing-services/ingress-nginx/OWNERS b/backing-services/ingress-nginx/OWNERS new file mode 100644 index 0000000..d588ede --- /dev/null +++ b/backing-services/ingress-nginx/OWNERS @@ -0,0 +1,10 @@ +# See the OWNERS docs: https://www.kubernetes.dev/docs/guide/owners + +approvers: +- ingress-nginx-helm-maintainers + +reviewers: +- ingress-nginx-helm-reviewers + +labels: +- area/helm diff --git a/backing-services/ingress-nginx/README.md b/backing-services/ingress-nginx/README.md new file mode 100644 index 0000000..f70bd0a --- /dev/null +++ b/backing-services/ingress-nginx/README.md @@ -0,0 +1,559 @@ +# ingress-nginx + +[ingress-nginx](https://github.com/kubernetes/ingress-nginx) Ingress controller for Kubernetes using NGINX as a reverse proxy and load balancer + +![Version: 4.11.3](https://img.shields.io/badge/Version-4.11.3-informational?style=flat-square) ![AppVersion: 1.11.3](https://img.shields.io/badge/AppVersion-1.11.3-informational?style=flat-square) + +To use, add `ingressClassName: nginx` spec field or the `kubernetes.io/ingress.class: nginx` annotation to your Ingress resources. + +This chart bootstraps an ingress-nginx deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +## Requirements + +Kubernetes: `>=1.21.0-0` + +## Get Repo Info + +```console +helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx +helm repo update +``` + +## Install Chart + +**Important:** only helm3 is supported + +```console +helm install [RELEASE_NAME] ingress-nginx/ingress-nginx +``` + +The command deploys ingress-nginx on the Kubernetes cluster in the default configuration. + +_See [configuration](#configuration) below._ + +_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._ + +## Uninstall Chart + +```console +helm uninstall [RELEASE_NAME] +``` + +This removes all the Kubernetes components associated with the chart and deletes the release. + +_See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command documentation._ + +## Upgrading Chart + +```console +helm upgrade [RELEASE_NAME] [CHART] --install +``` + +_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._ + +### Migrating from stable/nginx-ingress + +There are two main ways to migrate a release from `stable/nginx-ingress` to `ingress-nginx/ingress-nginx` chart: + +1. For Nginx Ingress controllers used for non-critical services, the easiest method is to [uninstall](#uninstall-chart) the old release and [install](#install-chart) the new one +1. For critical services in production that require zero-downtime, you will want to: + 1. [Install](#install-chart) a second Ingress controller + 1. Redirect your DNS traffic from the old controller to the new controller + 1. Log traffic from both controllers during this changeover + 1. [Uninstall](#uninstall-chart) the old controller once traffic has fully drained from it + +Note that there are some different and upgraded configurations between the two charts, described by Rimas Mocevicius from JFrog in the "Upgrading to ingress-nginx Helm chart" section of [Migrating from Helm chart nginx-ingress to ingress-nginx](https://rimusz.net/migrating-to-ingress-nginx). As the `ingress-nginx/ingress-nginx` chart continues to update, you will want to check current differences by running [helm configuration](#configuration) commands on both charts. + +## Configuration + +See [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing). To see all configurable options with detailed comments, visit the chart's [values.yaml](./values.yaml), or run these configuration commands: + +```console +helm show values ingress-nginx/ingress-nginx +``` + +### PodDisruptionBudget + +Note that the PodDisruptionBudget resource will only be defined if the replicaCount is greater than one, +else it would make it impossible to evacuate a node. See [gh issue #7127](https://github.com/helm/charts/issues/7127) for more info. + +### Prometheus Metrics + +The Ingress-Nginx Controller can export Prometheus metrics, by setting `controller.metrics.enabled` to `true`. + +You can add Prometheus annotations to the metrics service using `controller.metrics.service.annotations`. +Alternatively, if you use the Prometheus Operator, you can enable ServiceMonitor creation using `controller.metrics.serviceMonitor.enabled`. And set `controller.metrics.serviceMonitor.additionalLabels.release="prometheus"`. "release=prometheus" should match the label configured in the prometheus servicemonitor ( see `kubectl get servicemonitor prometheus-kube-prom-prometheus -oyaml -n prometheus`) + +### ingress-nginx nginx\_status page/stats server + +Previous versions of this chart had a `controller.stats.*` configuration block, which is now obsolete due to the following changes in Ingress-Nginx Controller: + +- In [0.16.1](https://github.com/kubernetes/ingress-nginx/blob/main/Changelog.md#0161), the vts (virtual host traffic status) dashboard was removed +- In [0.23.0](https://github.com/kubernetes/ingress-nginx/blob/main/Changelog.md#0230), the status page at port 18080 is now a unix socket webserver only available at localhost. + You can use `curl --unix-socket /tmp/nginx-status-server.sock http://localhost/nginx_status` inside the controller container to access it locally, or use the snippet from [nginx-ingress changelog](https://github.com/kubernetes/ingress-nginx/blob/main/Changelog.md#0230) to re-enable the http server + +### ExternalDNS Service Configuration + +Add an [ExternalDNS](https://github.com/kubernetes-sigs/external-dns) annotation to the LoadBalancer service: + +```yaml +controller: + service: + annotations: + external-dns.alpha.kubernetes.io/hostname: kubernetes-example.com. +``` + +### AWS L7 ELB with SSL Termination + +Annotate the controller as shown in the [nginx-ingress l7 patch](https://github.com/kubernetes/ingress-nginx/blob/ab3a789caae65eec4ad6e3b46b19750b481b6bce/deploy/aws/l7/service-l7.yaml): + +```yaml +controller: + service: + targetPorts: + http: http + https: http + annotations: + service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:XX-XXXX-X:XXXXXXXXX:certificate/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX + service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http" + service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https" + service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: '3600' +``` + +### Additional Internal Load Balancer + +This setup is useful when you need both external and internal load balancers but don't want to have multiple ingress controllers and multiple ingress objects per application. + +By default, the ingress object will point to the external load balancer address, but if correctly configured, you can make use of the internal one if the URL you are looking up resolves to the internal load balancer's URL. + +You'll need to set both the following values: + +`controller.service.internal.enabled` +`controller.service.internal.annotations` + +If one of them is missing the internal load balancer will not be deployed. Example you may have `controller.service.internal.enabled=true` but no annotations set, in this case no action will be taken. + +`controller.service.internal.annotations` varies with the cloud service you're using. + +Example for AWS: + +```yaml +controller: + service: + internal: + enabled: true + annotations: + # Create internal NLB + service.beta.kubernetes.io/aws-load-balancer-scheme: "internal" + # Create internal ELB(Deprecated) + # service.beta.kubernetes.io/aws-load-balancer-internal: "true" + # Any other annotation can be declared here. +``` + +Example for GCE: + +```yaml +controller: + service: + internal: + enabled: true + annotations: + # Create internal LB. More information: https://cloud.google.com/kubernetes-engine/docs/how-to/internal-load-balancing + # For GKE versions 1.17 and later + networking.gke.io/load-balancer-type: "Internal" + # For earlier versions + # cloud.google.com/load-balancer-type: "Internal" + + # Any other annotation can be declared here. +``` + +Example for Azure: + +```yaml +controller: + service: + annotations: + # Create internal LB + service.beta.kubernetes.io/azure-load-balancer-internal: "true" + # Any other annotation can be declared here. +``` + +Example for Oracle Cloud Infrastructure: + +```yaml +controller: + service: + annotations: + # Create internal LB + service.beta.kubernetes.io/oci-load-balancer-internal: "true" + # Any other annotation can be declared here. +``` + +The load balancer annotations of more cloud service providers can be found: [Internal load balancer](https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer). + +An use case for this scenario is having a split-view DNS setup where the public zone CNAME records point to the external balancer URL while the private zone CNAME records point to the internal balancer URL. This way, you only need one ingress kubernetes object. + +Optionally you can set `controller.service.loadBalancerIP` if you need a static IP for the resulting `LoadBalancer`. + +### Ingress Admission Webhooks + +With nginx-ingress-controller version 0.25+, the Ingress-Nginx Controller pod exposes an endpoint that will integrate with the `validatingwebhookconfiguration` Kubernetes feature to prevent bad ingress from being added to the cluster. +**This feature is enabled by default since 0.31.0.** + +With nginx-ingress-controller in 0.25.* work only with kubernetes 1.14+, 0.26 fix [this issue](https://github.com/kubernetes/ingress-nginx/pull/4521) + +#### How the Chart Configures the Hooks +A validating and configuration requires the endpoint to which the request is sent to use TLS. It is possible to set up custom certificates to do this, but in most cases, a self-signed certificate is enough. The setup of this component requires some more complex orchestration when using helm. The steps are created to be idempotent and to allow turning the feature on and off without running into helm quirks. + +1. A pre-install hook provisions a certificate into the same namespace using a format compatible with provisioning using end user certificates. If the certificate already exists, the hook exits. +2. The Ingress-Nginx Controller pod is configured to use a TLS proxy container, which will load that certificate. +3. Validating and Mutating webhook configurations are created in the cluster. +4. A post-install hook reads the CA from the secret created by step 1 and patches the Validating and Mutating webhook configurations. This process will allow a custom CA provisioned by some other process to also be patched into the webhook configurations. The chosen failure policy is also patched into the webhook configurations + +#### Alternatives +It should be possible to use [cert-manager/cert-manager](https://github.com/cert-manager/cert-manager) if a more complete solution is required. + +You can enable automatic self-signed TLS certificate provisioning via cert-manager by setting the `controller.admissionWebhooks.certManager.enabled` value to true. + +Please ensure that cert-manager is correctly installed and configured. + +### Helm Error When Upgrading: spec.clusterIP: Invalid value: "" + +If you are upgrading this chart from a version between 0.31.0 and 1.2.2 then you may get an error like this: + +```console +Error: UPGRADE FAILED: Service "?????-controller" is invalid: spec.clusterIP: Invalid value: "": field is immutable +``` + +Detail of how and why are in [this issue](https://github.com/helm/charts/pull/13646) but to resolve this you can set `xxxx.service.omitClusterIP` to `true` where `xxxx` is the service referenced in the error. + +As of version `1.26.0` of this chart, by simply not providing any clusterIP value, `invalid: spec.clusterIP: Invalid value: "": field is immutable` will no longer occur since `clusterIP: ""` will not be rendered. + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| commonLabels | object | `{}` | | +| controller.addHeaders | object | `{}` | Will add custom headers before sending response traffic to the client according to: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#add-headers | +| controller.admissionWebhooks.annotations | object | `{}` | | +| controller.admissionWebhooks.certManager.admissionCert.duration | string | `""` | | +| controller.admissionWebhooks.certManager.enabled | bool | `false` | | +| controller.admissionWebhooks.certManager.rootCert.duration | string | `""` | | +| controller.admissionWebhooks.certificate | string | `"/usr/local/certificates/cert"` | | +| controller.admissionWebhooks.createSecretJob.name | string | `"create"` | | +| controller.admissionWebhooks.createSecretJob.resources | object | `{}` | | +| controller.admissionWebhooks.createSecretJob.securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"readOnlyRootFilesystem":true,"runAsNonRoot":true,"runAsUser":65532,"seccompProfile":{"type":"RuntimeDefault"}}` | Security context for secret creation containers | +| controller.admissionWebhooks.enabled | bool | `true` | | +| controller.admissionWebhooks.existingPsp | string | `""` | Use an existing PSP instead of creating one | +| controller.admissionWebhooks.extraEnvs | list | `[]` | Additional environment variables to set | +| controller.admissionWebhooks.failurePolicy | string | `"Fail"` | Admission Webhook failure policy to use | +| controller.admissionWebhooks.key | string | `"/usr/local/certificates/key"` | | +| controller.admissionWebhooks.labels | object | `{}` | Labels to be added to admission webhooks | +| controller.admissionWebhooks.name | string | `"admission"` | | +| controller.admissionWebhooks.namespaceSelector | object | `{}` | | +| controller.admissionWebhooks.objectSelector | object | `{}` | | +| controller.admissionWebhooks.patch.enabled | bool | `true` | | +| controller.admissionWebhooks.patch.image.digest | string | `"sha256:a9f03b34a3cbfbb26d103a14046ab2c5130a80c3d69d526ff8063d2b37b9fd3f"` | | +| controller.admissionWebhooks.patch.image.image | string | `"ingress-nginx/kube-webhook-certgen"` | | +| controller.admissionWebhooks.patch.image.pullPolicy | string | `"IfNotPresent"` | | +| controller.admissionWebhooks.patch.image.registry | string | `"registry.k8s.io"` | | +| controller.admissionWebhooks.patch.image.tag | string | `"v1.4.4"` | | +| controller.admissionWebhooks.patch.labels | object | `{}` | Labels to be added to patch job resources | +| controller.admissionWebhooks.patch.networkPolicy.enabled | bool | `false` | Enable 'networkPolicy' or not | +| controller.admissionWebhooks.patch.nodeSelector."kubernetes.io/os" | string | `"linux"` | | +| controller.admissionWebhooks.patch.podAnnotations | object | `{}` | | +| controller.admissionWebhooks.patch.priorityClassName | string | `""` | Provide a priority class name to the webhook patching job # | +| controller.admissionWebhooks.patch.rbac | object | `{"create":true}` | Admission webhook patch job RBAC | +| controller.admissionWebhooks.patch.rbac.create | bool | `true` | Create RBAC or not | +| controller.admissionWebhooks.patch.securityContext | object | `{}` | Security context for secret creation & webhook patch pods | +| controller.admissionWebhooks.patch.serviceAccount | object | `{"automountServiceAccountToken":true,"create":true,"name":""}` | Admission webhook patch job service account | +| controller.admissionWebhooks.patch.serviceAccount.automountServiceAccountToken | bool | `true` | Auto-mount service account token or not | +| controller.admissionWebhooks.patch.serviceAccount.create | bool | `true` | Create a service account or not | +| controller.admissionWebhooks.patch.serviceAccount.name | string | `""` | Custom service account name | +| controller.admissionWebhooks.patch.tolerations | list | `[]` | | +| controller.admissionWebhooks.patchWebhookJob.name | string | `"patch"` | | +| controller.admissionWebhooks.patchWebhookJob.resources | object | `{}` | | +| controller.admissionWebhooks.patchWebhookJob.securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"readOnlyRootFilesystem":true,"runAsNonRoot":true,"runAsUser":65532,"seccompProfile":{"type":"RuntimeDefault"}}` | Security context for webhook patch containers | +| controller.admissionWebhooks.port | int | `8443` | | +| controller.admissionWebhooks.service.annotations | object | `{}` | | +| controller.admissionWebhooks.service.externalIPs | list | `[]` | | +| controller.admissionWebhooks.service.loadBalancerSourceRanges | list | `[]` | | +| controller.admissionWebhooks.service.servicePort | int | `443` | | +| controller.admissionWebhooks.service.type | string | `"ClusterIP"` | | +| controller.affinity | object | `{}` | Affinity and anti-affinity rules for server scheduling to nodes # Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity # | +| controller.allowSnippetAnnotations | bool | `false` | This configuration defines if Ingress Controller should allow users to set their own *-snippet annotations, otherwise this is forbidden / dropped when users add those annotations. Global snippets in ConfigMap are still respected | +| controller.annotations | object | `{}` | Annotations to be added to the controller Deployment or DaemonSet # | +| controller.autoscaling.annotations | object | `{}` | | +| controller.autoscaling.behavior | object | `{}` | | +| controller.autoscaling.enabled | bool | `false` | | +| controller.autoscaling.maxReplicas | int | `11` | | +| controller.autoscaling.minReplicas | int | `1` | | +| controller.autoscaling.targetCPUUtilizationPercentage | int | `50` | | +| controller.autoscaling.targetMemoryUtilizationPercentage | int | `50` | | +| controller.autoscalingTemplate | list | `[]` | | +| controller.config | object | `{}` | Global configuration passed to the ConfigMap consumed by the controller. Values may contain Helm templates. Ref.: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/ | +| controller.configAnnotations | object | `{}` | Annotations to be added to the controller config configuration configmap. | +| controller.configMapNamespace | string | `""` | Allows customization of the configmap / nginx-configmap namespace; defaults to $(POD_NAMESPACE) | +| controller.containerName | string | `"controller"` | Configures the controller container name | +| controller.containerPort | object | `{"http":80,"https":443}` | Configures the ports that the nginx-controller listens on | +| controller.containerSecurityContext | object | `{}` | Security context for controller containers | +| controller.customTemplate.configMapKey | string | `""` | | +| controller.customTemplate.configMapName | string | `""` | | +| controller.disableLeaderElection | bool | `false` | This configuration disable Nginx Controller Leader Election | +| controller.dnsConfig | object | `{}` | Optionally customize the pod dnsConfig. | +| controller.dnsPolicy | string | `"ClusterFirst"` | Optionally change this to ClusterFirstWithHostNet in case you have 'hostNetwork: true'. By default, while using host network, name resolution uses the host's DNS. If you wish nginx-controller to keep resolving names inside the k8s network, use ClusterFirstWithHostNet. | +| controller.electionID | string | `""` | Election ID to use for status update, by default it uses the controller name combined with a suffix of 'leader' | +| controller.electionTTL | string | `""` | Duration a leader election is valid before it's getting re-elected, e.g. `15s`, `10m` or `1h`. (Default: 30s) | +| controller.enableAnnotationValidations | bool | `false` | | +| controller.enableMimalloc | bool | `true` | Enable mimalloc as a drop-in replacement for malloc. # ref: https://github.com/microsoft/mimalloc # | +| controller.enableTopologyAwareRouting | bool | `false` | This configuration enables Topology Aware Routing feature, used together with service annotation service.kubernetes.io/topology-mode="auto" Defaults to false | +| controller.existingPsp | string | `""` | Use an existing PSP instead of creating one | +| controller.extraArgs | object | `{}` | Additional command line arguments to pass to Ingress-Nginx Controller E.g. to specify the default SSL certificate you can use | +| controller.extraContainers | list | `[]` | Additional containers to be added to the controller pod. See https://github.com/lemonldap-ng-controller/lemonldap-ng-controller as example. | +| controller.extraEnvs | list | `[]` | Additional environment variables to set | +| controller.extraInitContainers | list | `[]` | Containers, which are run before the app containers are started. | +| controller.extraModules | list | `[]` | Modules, which are mounted into the core nginx image. See values.yaml for a sample to add opentelemetry module | +| controller.extraVolumeMounts | list | `[]` | Additional volumeMounts to the controller main container. | +| controller.extraVolumes | list | `[]` | Additional volumes to the controller pod. | +| controller.healthCheckHost | string | `""` | Address to bind the health check endpoint. It is better to set this option to the internal node address if the Ingress-Nginx Controller is running in the `hostNetwork: true` mode. | +| controller.healthCheckPath | string | `"/healthz"` | Path of the health check endpoint. All requests received on the port defined by the healthz-port parameter are forwarded internally to this path. | +| controller.hostAliases | list | `[]` | Optionally customize the pod hostAliases. | +| controller.hostNetwork | bool | `false` | Required for use with CNI based kubernetes installations (such as ones set up by kubeadm), since CNI and hostport don't mix yet. Can be deprecated once https://github.com/kubernetes/kubernetes/issues/23920 is merged | +| controller.hostPort.enabled | bool | `false` | Enable 'hostPort' or not | +| controller.hostPort.ports.http | int | `80` | 'hostPort' http port | +| controller.hostPort.ports.https | int | `443` | 'hostPort' https port | +| controller.hostname | object | `{}` | Optionally customize the pod hostname. | +| controller.image.allowPrivilegeEscalation | bool | `false` | | +| controller.image.chroot | bool | `false` | | +| controller.image.digest | string | `"sha256:d56f135b6462cfc476447cfe564b83a45e8bb7da2774963b00d12161112270b7"` | | +| controller.image.digestChroot | string | `"sha256:22701f0fc0f2dd209ef782f4e281bfe2d8cccd50ededa00aec88e0cdbe7edd14"` | | +| controller.image.image | string | `"ingress-nginx/controller"` | | +| controller.image.pullPolicy | string | `"IfNotPresent"` | | +| controller.image.readOnlyRootFilesystem | bool | `false` | | +| controller.image.registry | string | `"registry.k8s.io"` | | +| controller.image.runAsNonRoot | bool | `true` | | +| controller.image.runAsUser | int | `101` | | +| controller.image.seccompProfile.type | string | `"RuntimeDefault"` | | +| controller.image.tag | string | `"v1.11.3"` | | +| controller.ingressClass | string | `"nginx"` | For backwards compatibility with ingress.class annotation, use ingressClass. Algorithm is as follows, first ingressClassName is considered, if not present, controller looks for ingress.class annotation | +| controller.ingressClassByName | bool | `false` | Process IngressClass per name (additionally as per spec.controller). | +| controller.ingressClassResource | object | `{"aliases":[],"annotations":{},"controllerValue":"k8s.io/ingress-nginx","default":false,"enabled":true,"name":"nginx","parameters":{}}` | This section refers to the creation of the IngressClass resource. IngressClasses are immutable and cannot be changed after creation. We do not support namespaced IngressClasses, yet, so a ClusterRole and a ClusterRoleBinding is required. | +| controller.ingressClassResource.aliases | list | `[]` | Aliases of this IngressClass. Creates copies with identical settings but the respective alias as name. Useful for development environments with only one Ingress Controller but production-like Ingress resources. `default` gets enabled on the original IngressClass only. | +| controller.ingressClassResource.annotations | object | `{}` | Annotations to be added to the IngressClass resource. | +| controller.ingressClassResource.controllerValue | string | `"k8s.io/ingress-nginx"` | Controller of the IngressClass. An Ingress Controller looks for IngressClasses it should reconcile by this value. This value is also being set as the `--controller-class` argument of this Ingress Controller. Ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class | +| controller.ingressClassResource.default | bool | `false` | If true, Ingresses without `ingressClassName` get assigned to this IngressClass on creation. Ingress creation gets rejected if there are multiple default IngressClasses. Ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#default-ingress-class | +| controller.ingressClassResource.enabled | bool | `true` | Create the IngressClass or not | +| controller.ingressClassResource.name | string | `"nginx"` | Name of the IngressClass | +| controller.ingressClassResource.parameters | object | `{}` | A link to a custom resource containing additional configuration for the controller. This is optional if the controller consuming this IngressClass does not require additional parameters. Ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class | +| controller.keda.apiVersion | string | `"keda.sh/v1alpha1"` | | +| controller.keda.behavior | object | `{}` | | +| controller.keda.cooldownPeriod | int | `300` | | +| controller.keda.enabled | bool | `false` | | +| controller.keda.maxReplicas | int | `11` | | +| controller.keda.minReplicas | int | `1` | | +| controller.keda.pollingInterval | int | `30` | | +| controller.keda.restoreToOriginalReplicaCount | bool | `false` | | +| controller.keda.scaledObject.annotations | object | `{}` | | +| controller.keda.triggers | list | `[]` | | +| controller.kind | string | `"Deployment"` | Use a `DaemonSet` or `Deployment` | +| controller.labels | object | `{}` | Labels to be added to the controller Deployment or DaemonSet and other resources that do not have option to specify labels # | +| controller.lifecycle | object | `{"preStop":{"exec":{"command":["/wait-shutdown"]}}}` | Improve connection draining when ingress controller pod is deleted using a lifecycle hook: With this new hook, we increased the default terminationGracePeriodSeconds from 30 seconds to 300, allowing the draining of connections up to five minutes. If the active connections end before that, the pod will terminate gracefully at that time. To effectively take advantage of this feature, the Configmap feature worker-shutdown-timeout new value is 240s instead of 10s. # | +| controller.livenessProbe.failureThreshold | int | `5` | | +| controller.livenessProbe.httpGet.path | string | `"/healthz"` | | +| controller.livenessProbe.httpGet.port | int | `10254` | | +| controller.livenessProbe.httpGet.scheme | string | `"HTTP"` | | +| controller.livenessProbe.initialDelaySeconds | int | `10` | | +| controller.livenessProbe.periodSeconds | int | `10` | | +| controller.livenessProbe.successThreshold | int | `1` | | +| controller.livenessProbe.timeoutSeconds | int | `1` | | +| controller.maxmindLicenseKey | string | `""` | Maxmind license key to download GeoLite2 Databases. # https://blog.maxmind.com/2019/12/significant-changes-to-accessing-and-using-geolite2-databases/ | +| controller.metrics.enabled | bool | `false` | | +| controller.metrics.port | int | `10254` | | +| controller.metrics.portName | string | `"metrics"` | | +| controller.metrics.prometheusRule.additionalLabels | object | `{}` | | +| controller.metrics.prometheusRule.enabled | bool | `false` | | +| controller.metrics.prometheusRule.rules | list | `[]` | | +| controller.metrics.service.annotations | object | `{}` | | +| controller.metrics.service.externalIPs | list | `[]` | List of IP addresses at which the stats-exporter service is available # Ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips # | +| controller.metrics.service.labels | object | `{}` | Labels to be added to the metrics service resource | +| controller.metrics.service.loadBalancerSourceRanges | list | `[]` | | +| controller.metrics.service.servicePort | int | `10254` | | +| controller.metrics.service.type | string | `"ClusterIP"` | | +| controller.metrics.serviceMonitor.additionalLabels | object | `{}` | | +| controller.metrics.serviceMonitor.annotations | object | `{}` | Annotations to be added to the ServiceMonitor. | +| controller.metrics.serviceMonitor.enabled | bool | `false` | | +| controller.metrics.serviceMonitor.metricRelabelings | list | `[]` | | +| controller.metrics.serviceMonitor.namespace | string | `""` | | +| controller.metrics.serviceMonitor.namespaceSelector | object | `{}` | | +| controller.metrics.serviceMonitor.relabelings | list | `[]` | | +| controller.metrics.serviceMonitor.scrapeInterval | string | `"30s"` | | +| controller.metrics.serviceMonitor.targetLabels | list | `[]` | | +| controller.minAvailable | int | `1` | Minimum available pods set in PodDisruptionBudget. Define either 'minAvailable' or 'maxUnavailable', never both. | +| controller.minReadySeconds | int | `0` | `minReadySeconds` to avoid killing pods before we are ready # | +| controller.name | string | `"controller"` | | +| controller.networkPolicy.enabled | bool | `false` | Enable 'networkPolicy' or not | +| controller.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for controller pod assignment # Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ # | +| controller.opentelemetry.containerSecurityContext.allowPrivilegeEscalation | bool | `false` | | +| controller.opentelemetry.containerSecurityContext.capabilities.drop[0] | string | `"ALL"` | | +| controller.opentelemetry.containerSecurityContext.readOnlyRootFilesystem | bool | `true` | | +| controller.opentelemetry.containerSecurityContext.runAsNonRoot | bool | `true` | | +| controller.opentelemetry.containerSecurityContext.runAsUser | int | `65532` | The image's default user, inherited from its base image `cgr.dev/chainguard/static`. | +| controller.opentelemetry.containerSecurityContext.seccompProfile.type | string | `"RuntimeDefault"` | | +| controller.opentelemetry.enabled | bool | `false` | | +| controller.opentelemetry.image.digest | string | `"sha256:f7604ac0547ed64d79b98d92133234e66c2c8aade3c1f4809fed5eec1fb7f922"` | | +| controller.opentelemetry.image.distroless | bool | `true` | | +| controller.opentelemetry.image.image | string | `"ingress-nginx/opentelemetry-1.25.3"` | | +| controller.opentelemetry.image.registry | string | `"registry.k8s.io"` | | +| controller.opentelemetry.image.tag | string | `"v20240813-b933310d"` | | +| controller.opentelemetry.name | string | `"opentelemetry"` | | +| controller.opentelemetry.resources | object | `{}` | | +| controller.podAnnotations | object | `{}` | Annotations to be added to controller pods # | +| controller.podLabels | object | `{}` | Labels to add to the pod container metadata | +| controller.podSecurityContext | object | `{}` | Security context for controller pods | +| controller.priorityClassName | string | `""` | | +| controller.proxySetHeaders | object | `{}` | Will add custom headers before sending traffic to backends according to https://github.com/kubernetes/ingress-nginx/tree/main/docs/examples/customization/custom-headers | +| controller.publishService | object | `{"enabled":true,"pathOverride":""}` | Allows customization of the source of the IP address or FQDN to report in the ingress status field. By default, it reads the information provided by the service. If disable, the status field reports the IP address of the node or nodes where an ingress controller pod is running. | +| controller.publishService.enabled | bool | `true` | Enable 'publishService' or not | +| controller.publishService.pathOverride | string | `""` | Allows overriding of the publish service to bind to Must be / | +| controller.readinessProbe.failureThreshold | int | `3` | | +| controller.readinessProbe.httpGet.path | string | `"/healthz"` | | +| controller.readinessProbe.httpGet.port | int | `10254` | | +| controller.readinessProbe.httpGet.scheme | string | `"HTTP"` | | +| controller.readinessProbe.initialDelaySeconds | int | `10` | | +| controller.readinessProbe.periodSeconds | int | `10` | | +| controller.readinessProbe.successThreshold | int | `1` | | +| controller.readinessProbe.timeoutSeconds | int | `1` | | +| controller.replicaCount | int | `1` | | +| controller.reportNodeInternalIp | bool | `false` | Bare-metal considerations via the host network https://kubernetes.github.io/ingress-nginx/deploy/baremetal/#via-the-host-network Ingress status was blank because there is no Service exposing the Ingress-Nginx Controller in a configuration using the host network, the default --publish-service flag used in standard cloud setups does not apply | +| controller.resources.requests.cpu | string | `"100m"` | | +| controller.resources.requests.memory | string | `"90Mi"` | | +| controller.scope.enabled | bool | `false` | Enable 'scope' or not | +| controller.scope.namespace | string | `""` | Namespace to limit the controller to; defaults to $(POD_NAMESPACE) | +| controller.scope.namespaceSelector | string | `""` | When scope.enabled == false, instead of watching all namespaces, we watching namespaces whose labels only match with namespaceSelector. Format like foo=bar. Defaults to empty, means watching all namespaces. | +| controller.service.annotations | object | `{}` | Annotations to be added to the external controller service. See `controller.service.internal.annotations` for annotations to be added to the internal controller service. | +| controller.service.appProtocol | bool | `true` | Declare the app protocol of the external HTTP and HTTPS listeners or not. Supersedes provider-specific annotations for declaring the backend protocol. Ref: https://kubernetes.io/docs/concepts/services-networking/service/#application-protocol | +| controller.service.clusterIP | string | `""` | Pre-defined cluster internal IP address of the external controller service. Take care of collisions with existing services. This value is immutable. Set once, it can not be changed without deleting and re-creating the service. Ref: https://kubernetes.io/docs/concepts/services-networking/service/#choosing-your-own-ip-address | +| controller.service.enableHttp | bool | `true` | Enable the HTTP listener on both controller services or not. | +| controller.service.enableHttps | bool | `true` | Enable the HTTPS listener on both controller services or not. | +| controller.service.enabled | bool | `true` | Enable controller services or not. This does not influence the creation of either the admission webhook or the metrics service. | +| controller.service.external.enabled | bool | `true` | Enable the external controller service or not. Useful for internal-only deployments. | +| controller.service.externalIPs | list | `[]` | List of node IP addresses at which the external controller service is available. Ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips | +| controller.service.externalTrafficPolicy | string | `""` | External traffic policy of the external controller service. Set to "Local" to preserve source IP on providers supporting it. Ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip | +| controller.service.internal.annotations | object | `{}` | Annotations to be added to the internal controller service. Mandatory for the internal controller service to be created. Varies with the cloud service. Ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer | +| controller.service.internal.appProtocol | bool | `true` | Declare the app protocol of the internal HTTP and HTTPS listeners or not. Supersedes provider-specific annotations for declaring the backend protocol. Ref: https://kubernetes.io/docs/concepts/services-networking/service/#application-protocol | +| controller.service.internal.clusterIP | string | `""` | Pre-defined cluster internal IP address of the internal controller service. Take care of collisions with existing services. This value is immutable. Set once, it can not be changed without deleting and re-creating the service. Ref: https://kubernetes.io/docs/concepts/services-networking/service/#choosing-your-own-ip-address | +| controller.service.internal.enabled | bool | `false` | Enable the internal controller service or not. Remember to configure `controller.service.internal.annotations` when enabling this. | +| controller.service.internal.externalIPs | list | `[]` | List of node IP addresses at which the internal controller service is available. Ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips | +| controller.service.internal.externalTrafficPolicy | string | `""` | External traffic policy of the internal controller service. Set to "Local" to preserve source IP on providers supporting it. Ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip | +| controller.service.internal.ipFamilies | list | `["IPv4"]` | List of IP families (e.g. IPv4, IPv6) assigned to the internal controller service. This field is usually assigned automatically based on cluster configuration and the `ipFamilyPolicy` field. Ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services | +| controller.service.internal.ipFamilyPolicy | string | `"SingleStack"` | Represents the dual-stack capabilities of the internal controller service. Possible values are SingleStack, PreferDualStack or RequireDualStack. Fields `ipFamilies` and `clusterIP` depend on the value of this field. Ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services | +| controller.service.internal.loadBalancerClass | string | `""` | Load balancer class of the internal controller service. Used by cloud providers to select a load balancer implementation other than the cloud provider default. Ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class | +| controller.service.internal.loadBalancerIP | string | `""` | Deprecated: Pre-defined IP address of the internal controller service. Used by cloud providers to connect the resulting load balancer service to a pre-existing static IP. Ref: https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer | +| controller.service.internal.loadBalancerSourceRanges | list | `[]` | Restrict access to the internal controller service. Values must be CIDRs. Allows any source address by default. | +| controller.service.internal.nodePorts.http | string | `""` | Node port allocated for the internal HTTP listener. If left empty, the service controller allocates one from the configured node port range. | +| controller.service.internal.nodePorts.https | string | `""` | Node port allocated for the internal HTTPS listener. If left empty, the service controller allocates one from the configured node port range. | +| controller.service.internal.nodePorts.tcp | object | `{}` | Node port mapping for internal TCP listeners. If left empty, the service controller allocates them from the configured node port range. Example: tcp: 8080: 30080 | +| controller.service.internal.nodePorts.udp | object | `{}` | Node port mapping for internal UDP listeners. If left empty, the service controller allocates them from the configured node port range. Example: udp: 53: 30053 | +| controller.service.internal.ports | object | `{}` | | +| controller.service.internal.sessionAffinity | string | `""` | Session affinity of the internal controller service. Must be either "None" or "ClientIP" if set. Defaults to "None". Ref: https://kubernetes.io/docs/reference/networking/virtual-ips/#session-affinity | +| controller.service.internal.targetPorts | object | `{}` | | +| controller.service.internal.type | string | `""` | Type of the internal controller service. Defaults to the value of `controller.service.type`. Ref: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types | +| controller.service.ipFamilies | list | `["IPv4"]` | List of IP families (e.g. IPv4, IPv6) assigned to the external controller service. This field is usually assigned automatically based on cluster configuration and the `ipFamilyPolicy` field. Ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services | +| controller.service.ipFamilyPolicy | string | `"SingleStack"` | Represents the dual-stack capabilities of the external controller service. Possible values are SingleStack, PreferDualStack or RequireDualStack. Fields `ipFamilies` and `clusterIP` depend on the value of this field. Ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services | +| controller.service.labels | object | `{}` | Labels to be added to both controller services. | +| controller.service.loadBalancerClass | string | `""` | Load balancer class of the external controller service. Used by cloud providers to select a load balancer implementation other than the cloud provider default. Ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class | +| controller.service.loadBalancerIP | string | `""` | Deprecated: Pre-defined IP address of the external controller service. Used by cloud providers to connect the resulting load balancer service to a pre-existing static IP. Ref: https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer | +| controller.service.loadBalancerSourceRanges | list | `[]` | Restrict access to the external controller service. Values must be CIDRs. Allows any source address by default. | +| controller.service.nodePorts.http | string | `""` | Node port allocated for the external HTTP listener. If left empty, the service controller allocates one from the configured node port range. | +| controller.service.nodePorts.https | string | `""` | Node port allocated for the external HTTPS listener. If left empty, the service controller allocates one from the configured node port range. | +| controller.service.nodePorts.tcp | object | `{}` | Node port mapping for external TCP listeners. If left empty, the service controller allocates them from the configured node port range. Example: tcp: 8080: 30080 | +| controller.service.nodePorts.udp | object | `{}` | Node port mapping for external UDP listeners. If left empty, the service controller allocates them from the configured node port range. Example: udp: 53: 30053 | +| controller.service.ports.http | int | `80` | Port the external HTTP listener is published with. | +| controller.service.ports.https | int | `443` | Port the external HTTPS listener is published with. | +| controller.service.sessionAffinity | string | `""` | Session affinity of the external controller service. Must be either "None" or "ClientIP" if set. Defaults to "None". Ref: https://kubernetes.io/docs/reference/networking/virtual-ips/#session-affinity | +| controller.service.targetPorts.http | string | `"http"` | Port of the ingress controller the external HTTP listener is mapped to. | +| controller.service.targetPorts.https | string | `"https"` | Port of the ingress controller the external HTTPS listener is mapped to. | +| controller.service.type | string | `"LoadBalancer"` | Type of the external controller service. Ref: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types | +| controller.shareProcessNamespace | bool | `false` | | +| controller.sysctls | object | `{}` | sysctls for controller pods # Ref: https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/ | +| controller.tcp.annotations | object | `{}` | Annotations to be added to the tcp config configmap | +| controller.tcp.configMapNamespace | string | `""` | Allows customization of the tcp-services-configmap; defaults to $(POD_NAMESPACE) | +| controller.terminationGracePeriodSeconds | int | `300` | `terminationGracePeriodSeconds` to avoid killing pods before we are ready # wait up to five minutes for the drain of connections # | +| controller.tolerations | list | `[]` | Node tolerations for server scheduling to nodes with taints # Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ # | +| controller.topologySpreadConstraints | list | `[]` | Topology spread constraints rely on node labels to identify the topology domain(s) that each Node is in. # Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ # | +| controller.udp.annotations | object | `{}` | Annotations to be added to the udp config configmap | +| controller.udp.configMapNamespace | string | `""` | Allows customization of the udp-services-configmap; defaults to $(POD_NAMESPACE) | +| controller.updateStrategy | object | `{}` | The update strategy to apply to the Deployment or DaemonSet # | +| controller.watchIngressWithoutClass | bool | `false` | Process Ingress objects without ingressClass annotation/ingressClassName field Overrides value for --watch-ingress-without-class flag of the controller binary Defaults to false | +| defaultBackend.affinity | object | `{}` | Affinity and anti-affinity rules for server scheduling to nodes # Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity | +| defaultBackend.autoscaling.annotations | object | `{}` | | +| defaultBackend.autoscaling.enabled | bool | `false` | | +| defaultBackend.autoscaling.maxReplicas | int | `2` | | +| defaultBackend.autoscaling.minReplicas | int | `1` | | +| defaultBackend.autoscaling.targetCPUUtilizationPercentage | int | `50` | | +| defaultBackend.autoscaling.targetMemoryUtilizationPercentage | int | `50` | | +| defaultBackend.containerSecurityContext | object | `{}` | Security context for default backend containers | +| defaultBackend.enabled | bool | `false` | | +| defaultBackend.existingPsp | string | `""` | Use an existing PSP instead of creating one | +| defaultBackend.extraArgs | object | `{}` | | +| defaultBackend.extraConfigMaps | list | `[]` | | +| defaultBackend.extraEnvs | list | `[]` | Additional environment variables to set for defaultBackend pods | +| defaultBackend.extraVolumeMounts | list | `[]` | | +| defaultBackend.extraVolumes | list | `[]` | | +| defaultBackend.image.allowPrivilegeEscalation | bool | `false` | | +| defaultBackend.image.image | string | `"defaultbackend-amd64"` | | +| defaultBackend.image.pullPolicy | string | `"IfNotPresent"` | | +| defaultBackend.image.readOnlyRootFilesystem | bool | `true` | | +| defaultBackend.image.registry | string | `"registry.k8s.io"` | | +| defaultBackend.image.runAsNonRoot | bool | `true` | | +| defaultBackend.image.runAsUser | int | `65534` | | +| defaultBackend.image.seccompProfile.type | string | `"RuntimeDefault"` | | +| defaultBackend.image.tag | string | `"1.5"` | | +| defaultBackend.labels | object | `{}` | Labels to be added to the default backend resources | +| defaultBackend.livenessProbe.failureThreshold | int | `3` | | +| defaultBackend.livenessProbe.initialDelaySeconds | int | `30` | | +| defaultBackend.livenessProbe.periodSeconds | int | `10` | | +| defaultBackend.livenessProbe.successThreshold | int | `1` | | +| defaultBackend.livenessProbe.timeoutSeconds | int | `5` | | +| defaultBackend.minAvailable | int | `1` | Minimum available pods set in PodDisruptionBudget. | +| defaultBackend.minReadySeconds | int | `0` | `minReadySeconds` to avoid killing pods before we are ready # | +| defaultBackend.name | string | `"defaultbackend"` | | +| defaultBackend.networkPolicy.enabled | bool | `false` | Enable 'networkPolicy' or not | +| defaultBackend.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for default backend pod assignment # Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ # | +| defaultBackend.podAnnotations | object | `{}` | Annotations to be added to default backend pods # | +| defaultBackend.podLabels | object | `{}` | Labels to add to the pod container metadata | +| defaultBackend.podSecurityContext | object | `{}` | Security context for default backend pods | +| defaultBackend.port | int | `8080` | | +| defaultBackend.priorityClassName | string | `""` | | +| defaultBackend.readinessProbe.failureThreshold | int | `6` | | +| defaultBackend.readinessProbe.initialDelaySeconds | int | `0` | | +| defaultBackend.readinessProbe.periodSeconds | int | `5` | | +| defaultBackend.readinessProbe.successThreshold | int | `1` | | +| defaultBackend.readinessProbe.timeoutSeconds | int | `5` | | +| defaultBackend.replicaCount | int | `1` | | +| defaultBackend.resources | object | `{}` | | +| defaultBackend.service.annotations | object | `{}` | | +| defaultBackend.service.externalIPs | list | `[]` | List of IP addresses at which the default backend service is available # Ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips # | +| defaultBackend.service.loadBalancerSourceRanges | list | `[]` | | +| defaultBackend.service.servicePort | int | `80` | | +| defaultBackend.service.type | string | `"ClusterIP"` | | +| defaultBackend.serviceAccount.automountServiceAccountToken | bool | `true` | | +| defaultBackend.serviceAccount.create | bool | `true` | | +| defaultBackend.serviceAccount.name | string | `""` | | +| defaultBackend.tolerations | list | `[]` | Node tolerations for server scheduling to nodes with taints # Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ # | +| defaultBackend.topologySpreadConstraints | list | `[]` | Topology spread constraints rely on node labels to identify the topology domain(s) that each Node is in. Ref.: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ | +| defaultBackend.updateStrategy | object | `{}` | The update strategy to apply to the Deployment or DaemonSet # | +| dhParam | string | `""` | A base64-encoded Diffie-Hellman parameter. This can be generated with: `openssl dhparam 4096 2> /dev/null | base64` # Ref: https://github.com/kubernetes/ingress-nginx/tree/main/docs/examples/customization/ssl-dh-param | +| imagePullSecrets | list | `[]` | Optional array of imagePullSecrets containing private registry credentials # Ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ | +| namespaceOverride | string | `""` | Override the deployment namespace; defaults to .Release.Namespace | +| podSecurityPolicy.enabled | bool | `false` | | +| portNamePrefix | string | `""` | Prefix for TCP and UDP ports names in ingress controller service # Some cloud providers, like Yandex Cloud may have a requirements for a port name regex to support cloud load balancer integration | +| rbac.create | bool | `true` | | +| rbac.scope | bool | `false` | | +| revisionHistoryLimit | int | `10` | Rollback limit # | +| serviceAccount.annotations | object | `{}` | Annotations for the controller service account | +| serviceAccount.automountServiceAccountToken | bool | `true` | | +| serviceAccount.create | bool | `true` | | +| serviceAccount.name | string | `""` | | +| tcp | object | `{}` | TCP service key-value pairs # Ref: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/exposing-tcp-udp-services.md # | +| udp | object | `{}` | UDP service key-value pairs # Ref: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/exposing-tcp-udp-services.md # | diff --git a/backing-services/ingress-nginx/README.md.gotmpl b/backing-services/ingress-nginx/README.md.gotmpl new file mode 100644 index 0000000..17b029b --- /dev/null +++ b/backing-services/ingress-nginx/README.md.gotmpl @@ -0,0 +1,229 @@ +{{ template "chart.header" . }} +[ingress-nginx](https://github.com/kubernetes/ingress-nginx) Ingress controller for Kubernetes using NGINX as a reverse proxy and load balancer + +{{ template "chart.versionBadge" . }}{{ template "chart.typeBadge" . }}{{ template "chart.appVersionBadge" . }} + +To use, add `ingressClassName: nginx` spec field or the `kubernetes.io/ingress.class: nginx` annotation to your Ingress resources. + +This chart bootstraps an ingress-nginx deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +{{ template "chart.requirementsSection" . }} + +## Get Repo Info + +```console +helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx +helm repo update +``` + +## Install Chart + +**Important:** only helm3 is supported + +```console +helm install [RELEASE_NAME] ingress-nginx/ingress-nginx +``` + +The command deploys ingress-nginx on the Kubernetes cluster in the default configuration. + +_See [configuration](#configuration) below._ + +_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._ + +## Uninstall Chart + +```console +helm uninstall [RELEASE_NAME] +``` + +This removes all the Kubernetes components associated with the chart and deletes the release. + +_See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command documentation._ + +## Upgrading Chart + +```console +helm upgrade [RELEASE_NAME] [CHART] --install +``` + +_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._ + +### Migrating from stable/nginx-ingress + +There are two main ways to migrate a release from `stable/nginx-ingress` to `ingress-nginx/ingress-nginx` chart: + +1. For Nginx Ingress controllers used for non-critical services, the easiest method is to [uninstall](#uninstall-chart) the old release and [install](#install-chart) the new one +1. For critical services in production that require zero-downtime, you will want to: + 1. [Install](#install-chart) a second Ingress controller + 1. Redirect your DNS traffic from the old controller to the new controller + 1. Log traffic from both controllers during this changeover + 1. [Uninstall](#uninstall-chart) the old controller once traffic has fully drained from it + +Note that there are some different and upgraded configurations between the two charts, described by Rimas Mocevicius from JFrog in the "Upgrading to ingress-nginx Helm chart" section of [Migrating from Helm chart nginx-ingress to ingress-nginx](https://rimusz.net/migrating-to-ingress-nginx). As the `ingress-nginx/ingress-nginx` chart continues to update, you will want to check current differences by running [helm configuration](#configuration) commands on both charts. + +## Configuration + +See [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing). To see all configurable options with detailed comments, visit the chart's [values.yaml](./values.yaml), or run these configuration commands: + +```console +helm show values ingress-nginx/ingress-nginx +``` + +### PodDisruptionBudget + +Note that the PodDisruptionBudget resource will only be defined if the replicaCount is greater than one, +else it would make it impossible to evacuate a node. See [gh issue #7127](https://github.com/helm/charts/issues/7127) for more info. + +### Prometheus Metrics + +The Ingress-Nginx Controller can export Prometheus metrics, by setting `controller.metrics.enabled` to `true`. + +You can add Prometheus annotations to the metrics service using `controller.metrics.service.annotations`. +Alternatively, if you use the Prometheus Operator, you can enable ServiceMonitor creation using `controller.metrics.serviceMonitor.enabled`. And set `controller.metrics.serviceMonitor.additionalLabels.release="prometheus"`. "release=prometheus" should match the label configured in the prometheus servicemonitor ( see `kubectl get servicemonitor prometheus-kube-prom-prometheus -oyaml -n prometheus`) + +### ingress-nginx nginx\_status page/stats server + +Previous versions of this chart had a `controller.stats.*` configuration block, which is now obsolete due to the following changes in Ingress-Nginx Controller: + +- In [0.16.1](https://github.com/kubernetes/ingress-nginx/blob/main/Changelog.md#0161), the vts (virtual host traffic status) dashboard was removed +- In [0.23.0](https://github.com/kubernetes/ingress-nginx/blob/main/Changelog.md#0230), the status page at port 18080 is now a unix socket webserver only available at localhost. + You can use `curl --unix-socket /tmp/nginx-status-server.sock http://localhost/nginx_status` inside the controller container to access it locally, or use the snippet from [nginx-ingress changelog](https://github.com/kubernetes/ingress-nginx/blob/main/Changelog.md#0230) to re-enable the http server + +### ExternalDNS Service Configuration + +Add an [ExternalDNS](https://github.com/kubernetes-sigs/external-dns) annotation to the LoadBalancer service: + +```yaml +controller: + service: + annotations: + external-dns.alpha.kubernetes.io/hostname: kubernetes-example.com. +``` + +### AWS L7 ELB with SSL Termination + +Annotate the controller as shown in the [nginx-ingress l7 patch](https://github.com/kubernetes/ingress-nginx/blob/ab3a789caae65eec4ad6e3b46b19750b481b6bce/deploy/aws/l7/service-l7.yaml): + +```yaml +controller: + service: + targetPorts: + http: http + https: http + annotations: + service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:XX-XXXX-X:XXXXXXXXX:certificate/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX + service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http" + service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https" + service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: '3600' +``` + +### Additional Internal Load Balancer + +This setup is useful when you need both external and internal load balancers but don't want to have multiple ingress controllers and multiple ingress objects per application. + +By default, the ingress object will point to the external load balancer address, but if correctly configured, you can make use of the internal one if the URL you are looking up resolves to the internal load balancer's URL. + +You'll need to set both the following values: + +`controller.service.internal.enabled` +`controller.service.internal.annotations` + +If one of them is missing the internal load balancer will not be deployed. Example you may have `controller.service.internal.enabled=true` but no annotations set, in this case no action will be taken. + +`controller.service.internal.annotations` varies with the cloud service you're using. + +Example for AWS: + +```yaml +controller: + service: + internal: + enabled: true + annotations: + # Create internal NLB + service.beta.kubernetes.io/aws-load-balancer-scheme: "internal" + # Create internal ELB(Deprecated) + # service.beta.kubernetes.io/aws-load-balancer-internal: "true" + # Any other annotation can be declared here. +``` + +Example for GCE: + +```yaml +controller: + service: + internal: + enabled: true + annotations: + # Create internal LB. More information: https://cloud.google.com/kubernetes-engine/docs/how-to/internal-load-balancing + # For GKE versions 1.17 and later + networking.gke.io/load-balancer-type: "Internal" + # For earlier versions + # cloud.google.com/load-balancer-type: "Internal" + + # Any other annotation can be declared here. +``` + +Example for Azure: + +```yaml +controller: + service: + annotations: + # Create internal LB + service.beta.kubernetes.io/azure-load-balancer-internal: "true" + # Any other annotation can be declared here. +``` + +Example for Oracle Cloud Infrastructure: + +```yaml +controller: + service: + annotations: + # Create internal LB + service.beta.kubernetes.io/oci-load-balancer-internal: "true" + # Any other annotation can be declared here. +``` + +The load balancer annotations of more cloud service providers can be found: [Internal load balancer](https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer). + +An use case for this scenario is having a split-view DNS setup where the public zone CNAME records point to the external balancer URL while the private zone CNAME records point to the internal balancer URL. This way, you only need one ingress kubernetes object. + +Optionally you can set `controller.service.loadBalancerIP` if you need a static IP for the resulting `LoadBalancer`. + +### Ingress Admission Webhooks + +With nginx-ingress-controller version 0.25+, the Ingress-Nginx Controller pod exposes an endpoint that will integrate with the `validatingwebhookconfiguration` Kubernetes feature to prevent bad ingress from being added to the cluster. +**This feature is enabled by default since 0.31.0.** + +With nginx-ingress-controller in 0.25.* work only with kubernetes 1.14+, 0.26 fix [this issue](https://github.com/kubernetes/ingress-nginx/pull/4521) + +#### How the Chart Configures the Hooks +A validating and configuration requires the endpoint to which the request is sent to use TLS. It is possible to set up custom certificates to do this, but in most cases, a self-signed certificate is enough. The setup of this component requires some more complex orchestration when using helm. The steps are created to be idempotent and to allow turning the feature on and off without running into helm quirks. + +1. A pre-install hook provisions a certificate into the same namespace using a format compatible with provisioning using end user certificates. If the certificate already exists, the hook exits. +2. The Ingress-Nginx Controller pod is configured to use a TLS proxy container, which will load that certificate. +3. Validating and Mutating webhook configurations are created in the cluster. +4. A post-install hook reads the CA from the secret created by step 1 and patches the Validating and Mutating webhook configurations. This process will allow a custom CA provisioned by some other process to also be patched into the webhook configurations. The chosen failure policy is also patched into the webhook configurations + +#### Alternatives +It should be possible to use [cert-manager/cert-manager](https://github.com/cert-manager/cert-manager) if a more complete solution is required. + +You can enable automatic self-signed TLS certificate provisioning via cert-manager by setting the `controller.admissionWebhooks.certManager.enabled` value to true. + +Please ensure that cert-manager is correctly installed and configured. + +### Helm Error When Upgrading: spec.clusterIP: Invalid value: "" + +If you are upgrading this chart from a version between 0.31.0 and 1.2.2 then you may get an error like this: + +```console +Error: UPGRADE FAILED: Service "?????-controller" is invalid: spec.clusterIP: Invalid value: "": field is immutable +``` + +Detail of how and why are in [this issue](https://github.com/helm/charts/pull/13646) but to resolve this you can set `xxxx.service.omitClusterIP` to `true` where `xxxx` is the service referenced in the error. + +As of version `1.26.0` of this chart, by simply not providing any clusterIP value, `invalid: spec.clusterIP: Invalid value: "": field is immutable` will no longer occur since `clusterIP: ""` will not be rendered. + +{{ template "chart.valuesSection" . }} diff --git a/backing-services/ingress-nginx/bugx.values.yaml b/backing-services/ingress-nginx/bugx.values.yaml new file mode 100644 index 0000000..c4eeecd --- /dev/null +++ b/backing-services/ingress-nginx/bugx.values.yaml @@ -0,0 +1,16 @@ +controller: + name: controller + enableAnnotationValidations: false + image: + ## Keep false as default for now! + chroot: false + registry: localhost:30516 + image: ingress-nginx/controller + admissionWebhooks: + patch: + image: + registry: localhost:30516 + image: ingress-nginx/kube-webhook-certgen + tag: v1.4.4 + digest: "" + pullPolicy: IfNotPresent diff --git a/backing-services/ingress-nginx/changelog/helm-chart-2.10.0.md b/backing-services/ingress-nginx/changelog/helm-chart-2.10.0.md new file mode 100644 index 0000000..b42d6c2 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-2.10.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 2.10.0 + +* [#5843](https://github.com/kubernetes/ingress-nginx/pull/5843) Update jettech/kube-webhook-certgen image + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-2.9.1...ingress-nginx-2.10.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-2.11.0.md b/backing-services/ingress-nginx/changelog/helm-chart-2.11.0.md new file mode 100644 index 0000000..e549b38 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-2.11.0.md @@ -0,0 +1,10 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 2.11.0 + +* [#5879](https://github.com/kubernetes/ingress-nginx/pull/5879) Update helm chart for v0.34.0 +* [#5671](https://github.com/kubernetes/ingress-nginx/pull/5671) Make liveness probe more fault tolerant than readiness probe + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-2.10.0...ingress-nginx-2.11.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-2.11.1.md b/backing-services/ingress-nginx/changelog/helm-chart-2.11.1.md new file mode 100644 index 0000000..d910d3b --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-2.11.1.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 2.11.1 + +* [#5900](https://github.com/kubernetes/ingress-nginx/pull/5900) Release helm chart for v0.34.1 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-2.11.0...ingress-nginx-2.11.1 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-2.11.2.md b/backing-services/ingress-nginx/changelog/helm-chart-2.11.2.md new file mode 100644 index 0000000..9f78210 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-2.11.2.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 2.11.2 + +* [#5951](https://github.com/kubernetes/ingress-nginx/pull/5951) Bump chart patch version + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-2.11.1...ingress-nginx-2.11.2 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-2.11.3.md b/backing-services/ingress-nginx/changelog/helm-chart-2.11.3.md new file mode 100644 index 0000000..3447691 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-2.11.3.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 2.11.3 + +* [#6038](https://github.com/kubernetes/ingress-nginx/pull/6038) Bump chart version PATCH + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-2.11.2...ingress-nginx-2.11.3 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-2.12.0.md b/backing-services/ingress-nginx/changelog/helm-chart-2.12.0.md new file mode 100644 index 0000000..5cb3888 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-2.12.0.md @@ -0,0 +1,10 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 2.12.0 + +* [#6039](https://github.com/kubernetes/ingress-nginx/pull/6039) Add configurable serviceMonitor metricRelabelling and targetLabels +* [#6044](https://github.com/kubernetes/ingress-nginx/pull/6044) Fix YAML linting + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-2.11.3...ingress-nginx-2.12.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-2.12.1.md b/backing-services/ingress-nginx/changelog/helm-chart-2.12.1.md new file mode 100644 index 0000000..94d121d --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-2.12.1.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 2.12.1 + +* [#6075](https://github.com/kubernetes/ingress-nginx/pull/6075) Sync helm chart affinity examples + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-2.12.0...ingress-nginx-2.12.1 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-2.13.0.md b/backing-services/ingress-nginx/changelog/helm-chart-2.13.0.md new file mode 100644 index 0000000..01fe0b1 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-2.13.0.md @@ -0,0 +1,10 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 2.13.0 + +* [#6093](https://github.com/kubernetes/ingress-nginx/pull/6093) Release v0.35.0 +* [#6080](https://github.com/kubernetes/ingress-nginx/pull/6080) Switch images to k8s.gcr.io after Vanity Domain Flip + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-2.12.1...ingress-nginx-2.13.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-2.14.0.md b/backing-services/ingress-nginx/changelog/helm-chart-2.14.0.md new file mode 100644 index 0000000..2fb7a5a --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-2.14.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 2.14.0 + +* [#6104](https://github.com/kubernetes/ingress-nginx/pull/6104) Misc fixes for nginx-ingress chart for better keel and prometheus-operator integration + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-2.13.0...ingress-nginx-2.14.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-2.15.0.md b/backing-services/ingress-nginx/changelog/helm-chart-2.15.0.md new file mode 100644 index 0000000..543a559 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-2.15.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 2.15.0 + +* [#6087](https://github.com/kubernetes/ingress-nginx/pull/6087) Adding parameter for externalTrafficPolicy in internal controller service spec + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-2.14.0...ingress-nginx-2.15.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-2.16.0.md b/backing-services/ingress-nginx/changelog/helm-chart-2.16.0.md new file mode 100644 index 0000000..996f448 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-2.16.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 2.16.0 + +* [#6154](https://github.com/kubernetes/ingress-nginx/pull/6154) add `topologySpreadConstraint` to controller + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-2.15.0...ingress-nginx-2.16.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-2.9.0.md b/backing-services/ingress-nginx/changelog/helm-chart-2.9.0.md new file mode 100644 index 0000000..11c5f5f --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-2.9.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 2.9.0 + +* [#5795](https://github.com/kubernetes/ingress-nginx/pull/5795) Use fully qualified images to avoid cri-o issues + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-TODO...ingress-nginx-2.9.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-2.9.1.md b/backing-services/ingress-nginx/changelog/helm-chart-2.9.1.md new file mode 100644 index 0000000..7d4314d --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-2.9.1.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 2.9.1 + +* [#5823](https://github.com/kubernetes/ingress-nginx/pull/5823) Add quoting to sysctls because numeric values need to be presented as strings (#5823) + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-2.9.0...ingress-nginx-2.9.1 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.0.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.0.0.md new file mode 100644 index 0000000..a7d50ee --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.0.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.0.0 + +* [#6167](https://github.com/kubernetes/ingress-nginx/pull/6167) Update chart requirements + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-2.16.0...ingress-nginx-3.0.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.10.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.10.0.md new file mode 100644 index 0000000..3369bed --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.10.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.10.0 + +* Fix routing regression introduced in 0.41.0 with PathType Exact + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-3.9.0...ingress-nginx-3.10.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.10.1.md b/backing-services/ingress-nginx/changelog/helm-chart-3.10.1.md new file mode 100644 index 0000000..6ff682e --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.10.1.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.10.1 + +* Fix regression introduced in 0.41.0 with external authentication + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-3.10.0...ingress-nginx-3.10.1 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.11.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.11.0.md new file mode 100644 index 0000000..69ba550 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.11.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.11.0 + +* Support Keda Autoscaling + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-3.10.1...ingress-nginx-3.11.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.11.1.md b/backing-services/ingress-nginx/changelog/helm-chart-3.11.1.md new file mode 100644 index 0000000..4e81f4b --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.11.1.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.11.1 + +* [#6505](https://github.com/kubernetes/ingress-nginx/pull/6505) Reorder HPA resource list to work with GitOps tooling + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-3.11.0...ingress-nginx-3.11.1 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.12.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.12.0.md new file mode 100644 index 0000000..41b9744 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.12.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.12.0 + +* [#6514](https://github.com/kubernetes/ingress-nginx/pull/6514) Remove helm2 support and update docs + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-3.11.1...ingress-nginx-3.12.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.13.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.13.0.md new file mode 100644 index 0000000..0855a79 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.13.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.13.0 + +* [#6544](https://github.com/kubernetes/ingress-nginx/pull/6544) Fix default backend HPA name variable + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-3.12.0...ingress-nginx-3.13.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.14.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.14.0.md new file mode 100644 index 0000000..e07880b --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.14.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.14.0 + +* [#6469](https://github.com/kubernetes/ingress-nginx/pull/6469) Allow custom service names for controller and backend + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-3.13.0...ingress-nginx-3.14.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.15.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.15.0.md new file mode 100644 index 0000000..3053a35 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.15.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.15.0 + +* [#6586](https://github.com/kubernetes/ingress-nginx/pull/6586) Fix 'maxmindLicenseKey' location in values.yaml + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-3.14.0...ingress-nginx-3.15.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.15.1.md b/backing-services/ingress-nginx/changelog/helm-chart-3.15.1.md new file mode 100644 index 0000000..f11ee0a --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.15.1.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.15.1 + +* Fix chart-releaser action + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-3.15.0...ingress-nginx-3.15.1 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.16.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.16.0.md new file mode 100644 index 0000000..fba30b1 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.16.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.16.0 + +* [#6646](https://github.com/kubernetes/ingress-nginx/pull/6646) Added LoadBalancerIP value for internal service + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-3.15.1...helm-chart-3.16.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.16.1.md b/backing-services/ingress-nginx/changelog/helm-chart-3.16.1.md new file mode 100644 index 0000000..650d1b8 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.16.1.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.16.1 + +* Fix chart-releaser action + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-3.16.0...helm-chart-3.16.1 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.17.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.17.0.md new file mode 100644 index 0000000..175c7a2 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.17.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.17.0 + +* Update ingress-nginx v0.42.0 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-3.16.1...helm-chart-3.17.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.18.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.18.0.md new file mode 100644 index 0000000..31b815e --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.18.0.md @@ -0,0 +1,10 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.18.0 + +* [#6688](https://github.com/kubernetes/ingress-nginx/pull/6688) Allow volume-type emptyDir in controller podsecuritypolicy +* [#6691](https://github.com/kubernetes/ingress-nginx/pull/6691) Improve parsing of helm parameters + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-3.17.0...helm-chart-3.18.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.19.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.19.0.md new file mode 100644 index 0000000..0970bf0 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.19.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.19.0 + +* Update ingress-nginx v0.43.0 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-3.18.0...helm-chart-3.19.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.20.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.20.0.md new file mode 100644 index 0000000..4b81ae4 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.20.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.20.0 + +* [#6730](https://github.com/kubernetes/ingress-nginx/pull/6730) Do not create HPA for defaultBackend if not enabled. + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-3.19.0...helm-chart-3.20.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.20.1.md b/backing-services/ingress-nginx/changelog/helm-chart-3.20.1.md new file mode 100644 index 0000000..952bf2b --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.20.1.md @@ -0,0 +1,10 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.20.1 + +* Do not create KEDA in case of DaemonSets. +* Fix KEDA v2 definition + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-3.20.0...helm-chart-3.20.1 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.21.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.21.0.md new file mode 100644 index 0000000..25edbef --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.21.0.md @@ -0,0 +1,12 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.21.0 + +* [#6783](https://github.com/kubernetes/ingress-nginx/pull/6783) Add custom annotations to ScaledObject +* [#6761](https://github.com/kubernetes/ingress-nginx/pull/6761) Adding quotes in the serviceAccount name in Helm values +* [#6767](https://github.com/kubernetes/ingress-nginx/pull/6767) Remove ClusterRole when scope option is enabled +* [#6785](https://github.com/kubernetes/ingress-nginx/pull/6785) Update kube-webhook-certgen image to v1.5.1 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-3.20.1...helm-chart-3.21.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.22.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.22.0.md new file mode 100644 index 0000000..147d664 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.22.0.md @@ -0,0 +1,10 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.22.0 + +* [#6802](https://github.com/kubernetes/ingress-nginx/pull/6802) Add value for configuring a custom Diffie-Hellman parameters file +* [#6815](https://github.com/kubernetes/ingress-nginx/pull/6815) Allow use of numeric namespaces in helm chart + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-3.21.0...helm-chart-3.22.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.23.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.23.0.md new file mode 100644 index 0000000..5dcb50f --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.23.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.23.0 + +* Update ingress-nginx v0.44.0 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-3.22.0...helm-chart-3.23.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.24.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.24.0.md new file mode 100644 index 0000000..d7db808 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.24.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.24.0 + +* [#6908](https://github.com/kubernetes/ingress-nginx/pull/6908) Add volumes to default-backend deployment + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-3.23.0...helm-chart-3.24.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.25.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.25.0.md new file mode 100644 index 0000000..f9679a1 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.25.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.25.0 + +* [#6957](https://github.com/kubernetes/ingress-nginx/pull/6957) Add ability to specify automountServiceAccountToken + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-3.24.0...helm-chart-3.25.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.26.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.26.0.md new file mode 100644 index 0000000..0c3a1df --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.26.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.26.0 + +* [#6979](https://github.com/kubernetes/ingress-nginx/pull/6979) Changed servicePort value for metrics + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-3.25.0...helm-chart-3.26.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.27.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.27.0.md new file mode 100644 index 0000000..8113d7b --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.27.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.27.0 + +* Update ingress-nginx v0.45.0 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-3.26.0...helm-chart-3.27.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.28.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.28.0.md new file mode 100644 index 0000000..eee0ccb --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.28.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.28.0 + +* [#6900](https://github.com/kubernetes/ingress-nginx/pull/6900) Support existing PSPs + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-3.27.0...helm-chart-3.28.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.29.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.29.0.md new file mode 100644 index 0000000..f0fabdc --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.29.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.29.0 + +* [#6945](https://github.com/kubernetes/ingress-nginx/pull/7020) Add option to specify job label for ServiceMonitor + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-3.28.0...helm-chart-3.29.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.3.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.3.0.md new file mode 100644 index 0000000..09fab37 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.3.0.md @@ -0,0 +1,12 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.3.0 + +* [#6203](https://github.com/kubernetes/ingress-nginx/pull/6203) Refactor parsing of key values +* [#6162](https://github.com/kubernetes/ingress-nginx/pull/6162) Add helm chart options to expose metrics service as NodePort +* [#6180](https://github.com/kubernetes/ingress-nginx/pull/6180) Fix helm chart admissionReviewVersions regression +* [#6169](https://github.com/kubernetes/ingress-nginx/pull/6169) Fix Typo in example prometheus rules + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-3.0.0...ingress-nginx-3.3.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.3.1.md b/backing-services/ingress-nginx/changelog/helm-chart-3.3.1.md new file mode 100644 index 0000000..81f44fd --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.3.1.md @@ -0,0 +1,12 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.3.1 + +* [#6259](https://github.com/kubernetes/ingress-nginx/pull/6259) Release helm chart +* [#6258](https://github.com/kubernetes/ingress-nginx/pull/6258) Fix chart markdown link +* [#6253](https://github.com/kubernetes/ingress-nginx/pull/6253) Release v0.40.0 +* [#6233](https://github.com/kubernetes/ingress-nginx/pull/6233) Add admission controller e2e test + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-3.3.0...ingress-nginx-3.3.1 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.30.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.30.0.md new file mode 100644 index 0000000..77ad6b4 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.30.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.30.0 + +* [#7092](https://github.com/kubernetes/ingress-nginx/pull/7092) Removes the possibility of using localhost in ExternalNames as endpoints + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-3.29.0...helm-chart-3.30.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.31.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.31.0.md new file mode 100644 index 0000000..bc07fed --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.31.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.31.0 + +* [7137] https://github.com/kubernetes/ingress-nginx/pull/7137 Add support for custom probes + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-3.30.0...helm-chart-3.31.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.32.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.32.0.md new file mode 100644 index 0000000..68f7ed6 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.32.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.32.0 + +* [7117] https://github.com/kubernetes/ingress-nginx/pull/7117 Add annotations for HPA + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-3.31.0...helm-chart-3.32.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.33.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.33.0.md new file mode 100644 index 0000000..b56c5fc --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.33.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.33.0 + +* [7164] https://github.com/kubernetes/ingress-nginx/pull/7164 Update nginx to v1.20.1 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-3.32.0...helm-chart-3.33.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.34.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.34.0.md new file mode 100644 index 0000000..a28cd02 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.34.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.34.0 + +* [7256] https://github.com/kubernetes/ingress-nginx/pull/7256 Add namespace field in the namespace scoped resource templates + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-3.33.0...helm-chart-3.34.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.4.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.4.0.md new file mode 100644 index 0000000..3b4ca93 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.4.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.4.0 + +* [#6268](https://github.com/kubernetes/ingress-nginx/pull/6268) Update to 0.40.2 in helm chart #6288 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-3.3.1...ingress-nginx-3.4.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.5.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.5.0.md new file mode 100644 index 0000000..44991b3 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.5.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.5.0 + +* [#6260](https://github.com/kubernetes/ingress-nginx/pull/6260) Allow Helm Chart to customize admission webhook's annotations, timeoutSeconds, namespaceSelector, objectSelector and cert files locations + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-3.4.0...ingress-nginx-3.5.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.5.1.md b/backing-services/ingress-nginx/changelog/helm-chart-3.5.1.md new file mode 100644 index 0000000..740f00c --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.5.1.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.5.1 + +* [#6299](https://github.com/kubernetes/ingress-nginx/pull/6299) Fix helm chart release + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-3.5.0...ingress-nginx-3.5.1 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.6.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.6.0.md new file mode 100644 index 0000000..4af7f11 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.6.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.6.0 + +* [#6305](https://github.com/kubernetes/ingress-nginx/pull/6305) Add default linux nodeSelector + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-3.5.1...ingress-nginx-3.6.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.7.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.7.0.md new file mode 100644 index 0000000..a6b1299 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.7.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.7.0 + +* [#6316](https://github.com/kubernetes/ingress-nginx/pull/6316) Numerals in podAnnotations in quotes [#6315](https://github.com/kubernetes/ingress-nginx/issues/6315) + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-3.6.0...ingress-nginx-3.7.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.7.1.md b/backing-services/ingress-nginx/changelog/helm-chart-3.7.1.md new file mode 100644 index 0000000..6ba12df --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.7.1.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.7.1 + +* [#6326](https://github.com/kubernetes/ingress-nginx/pull/6326) Fix liveness and readiness probe path in daemonset chart + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-3.7.0...ingress-nginx-3.7.1 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.8.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.8.0.md new file mode 100644 index 0000000..8df250a --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.8.0.md @@ -0,0 +1,13 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.8.0 + +* [#6395](https://github.com/kubernetes/ingress-nginx/pull/6395) Update jettech/kube-webhook-certgen image +* [#6377](https://github.com/kubernetes/ingress-nginx/pull/6377) Added loadBalancerSourceRanges for internal lbs +* [#6356](https://github.com/kubernetes/ingress-nginx/pull/6356) Add securitycontext settings on defaultbackend +* [#6401](https://github.com/kubernetes/ingress-nginx/pull/6401) Fix controller service annotations +* [#6403](https://github.com/kubernetes/ingress-nginx/pull/6403) Initial helm chart changelog + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-3.7.1...ingress-nginx-3.8.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-3.9.0.md b/backing-services/ingress-nginx/changelog/helm-chart-3.9.0.md new file mode 100644 index 0000000..e8c9def --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-3.9.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 3.9.0 + +* [#6423](https://github.com/kubernetes/ingress-nginx/pull/6423) Add Default backend HPA autoscaling + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/ingress-nginx-3.8.0...ingress-nginx-3.9.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.0.1.md b/backing-services/ingress-nginx/changelog/helm-chart-4.0.1.md new file mode 100644 index 0000000..7a187b3 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.0.1.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.0.1 + +* [7535] https://github.com/kubernetes/ingress-nginx/pull/7535 Release v1.0.0 ingress-nginx + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-3.34.0...helm-chart-4.0.1 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.0.10.md b/backing-services/ingress-nginx/changelog/helm-chart-4.0.10.md new file mode 100644 index 0000000..c5d6516 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.0.10.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.0.10 + +* [7964] https://github.com/kubernetes/ingress-nginx/pull/7964 Update controller version to v1.1.0 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.0.9...helm-chart-4.0.10 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.0.11.md b/backing-services/ingress-nginx/changelog/helm-chart-4.0.11.md new file mode 100644 index 0000000..5541823 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.0.11.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.0.11 + +* [7873] https://github.com/kubernetes/ingress-nginx/pull/7873 Makes the [appProtocol](https://kubernetes.io/docs/concepts/services-networking/_print/#application-protocol) field optional. + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.0.10...helm-chart-4.0.11 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.0.12.md b/backing-services/ingress-nginx/changelog/helm-chart-4.0.12.md new file mode 100644 index 0000000..320f6f5 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.0.12.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.0.12 + +* [7978] https://github.com/kubernetes/ingress-nginx/pull/7979 Support custom annotations in admissions Jobs + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.0.11...helm-chart-4.0.12 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.0.13.md b/backing-services/ingress-nginx/changelog/helm-chart-4.0.13.md new file mode 100644 index 0000000..edd9228 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.0.13.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.0.13 + +* [8008] https://github.com/kubernetes/ingress-nginx/pull/8008 Add relabelings in controller-servicemonitor.yaml + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.0.12...helm-chart-4.0.13 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.0.14.md b/backing-services/ingress-nginx/changelog/helm-chart-4.0.14.md new file mode 100644 index 0000000..e927010 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.0.14.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.0.14 + +* [8061] https://github.com/kubernetes/ingress-nginx/pull/8061 Using helm-docs to populate values table in README.md + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.0.13...helm-chart-4.0.14 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.0.15.md b/backing-services/ingress-nginx/changelog/helm-chart-4.0.15.md new file mode 100644 index 0000000..d3d14a9 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.0.15.md @@ -0,0 +1,43 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.0.15 + +* [8120] https://github.com/kubernetes/ingress-nginx/pull/8120 Update go in runner and release v1.1.1 +* [8119] https://github.com/kubernetes/ingress-nginx/pull/8119 Update to go v1.17.6 +* [8118] https://github.com/kubernetes/ingress-nginx/pull/8118 Remove deprecated libraries, update other libs +* [8117] https://github.com/kubernetes/ingress-nginx/pull/8117 Fix codegen errors +* [8115] https://github.com/kubernetes/ingress-nginx/pull/8115 chart/ghaction: set the correct permission to have access to push a release +* [8098] https://github.com/kubernetes/ingress-nginx/pull/8098 generating SHA for CA only certs in backend_ssl.go + comparison of P… +* [8088] https://github.com/kubernetes/ingress-nginx/pull/8088 Fix Edit this page link to use main branch +* [8072] https://github.com/kubernetes/ingress-nginx/pull/8072 Expose GeoIP2 Continent code as variable +* [8061] https://github.com/kubernetes/ingress-nginx/pull/8061 docs(charts): using helm-docs for chart +* [8058] https://github.com/kubernetes/ingress-nginx/pull/8058 Bump github.com/spf13/cobra from 1.2.1 to 1.3.0 +* [8054] https://github.com/kubernetes/ingress-nginx/pull/8054 Bump google.golang.org/grpc from 1.41.0 to 1.43.0 +* [8051] https://github.com/kubernetes/ingress-nginx/pull/8051 align bug report with feature request regarding kind documentation +* [8046] https://github.com/kubernetes/ingress-nginx/pull/8046 Report expired certificates (#8045) +* [8044] https://github.com/kubernetes/ingress-nginx/pull/8044 remove G109 check till gosec resolves issues +* [8042] https://github.com/kubernetes/ingress-nginx/pull/8042 docs_multiple_instances_one_cluster_ticket_7543 +* [8041] https://github.com/kubernetes/ingress-nginx/pull/8041 docs: fix typo'd executable name +* [8035] https://github.com/kubernetes/ingress-nginx/pull/8035 Comment busy owners +* [8029] https://github.com/kubernetes/ingress-nginx/pull/8029 Add stream-snippet as a ConfigMap and Annotation option +* [8023] https://github.com/kubernetes/ingress-nginx/pull/8023 fix nginx compilation flags +* [8021] https://github.com/kubernetes/ingress-nginx/pull/8021 Disable default modsecurity_rules_file if modsecurity-snippet is specified +* [8019] https://github.com/kubernetes/ingress-nginx/pull/8019 Revise main documentation page +* [8018] https://github.com/kubernetes/ingress-nginx/pull/8018 Preserve order of plugin invocation +* [8015] https://github.com/kubernetes/ingress-nginx/pull/8015 Add newline indenting to admission webhook annotations +* [8014] https://github.com/kubernetes/ingress-nginx/pull/8014 Add link to example error page manifest in docs +* [8009] https://github.com/kubernetes/ingress-nginx/pull/8009 Fix spelling in documentation and top-level files +* [8008] https://github.com/kubernetes/ingress-nginx/pull/8008 Add relabelings in controller-servicemonitor.yaml +* [8003] https://github.com/kubernetes/ingress-nginx/pull/8003 Minor improvements (formatting, consistency) in install guide +* [8001] https://github.com/kubernetes/ingress-nginx/pull/8001 fix: go-grpc Dockerfile +* [7999] https://github.com/kubernetes/ingress-nginx/pull/7999 images: use k8s-staging-test-infra/gcb-docker-gcloud +* [7996] https://github.com/kubernetes/ingress-nginx/pull/7996 doc: improvement +* [7983] https://github.com/kubernetes/ingress-nginx/pull/7983 Fix a couple of misspellings in the annotations documentation. +* [7979] https://github.com/kubernetes/ingress-nginx/pull/7979 allow set annotations for admission Jobs +* [7977] https://github.com/kubernetes/ingress-nginx/pull/7977 Add ssl_reject_handshake to default server +* [7975] https://github.com/kubernetes/ingress-nginx/pull/7975 add legacy version update v0.50.0 to main changelog +* [7972] https://github.com/kubernetes/ingress-nginx/pull/7972 updated service upstream definition + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.0.14...helm-chart-4.0.15 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.0.18.md b/backing-services/ingress-nginx/changelog/helm-chart-4.0.18.md new file mode 100644 index 0000000..30a8f75 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.0.18.md @@ -0,0 +1,40 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.0.18 + +* [8291](https://github.com/kubernetes/ingress-nginx/pull/8291) remove git tag env from cloud build +* [8286](https://github.com/kubernetes/ingress-nginx/pull/8286) Fix OpenTelemetry sidecar image build +* [8277](https://github.com/kubernetes/ingress-nginx/pull/8277) Add OpenSSF Best practices badge +* [8273](https://github.com/kubernetes/ingress-nginx/pull/8273) Issue#8241 +* [8267](https://github.com/kubernetes/ingress-nginx/pull/8267) Add fsGroup value to admission-webhooks/job-patch charts +* [8262](https://github.com/kubernetes/ingress-nginx/pull/8262) Updated confusing error +* [8256](https://github.com/kubernetes/ingress-nginx/pull/8256) fix: deny locations with invalid auth-url annotation +* [8253](https://github.com/kubernetes/ingress-nginx/pull/8253) Add a certificate info metric +* [8236](https://github.com/kubernetes/ingress-nginx/pull/8236) webhook: remove useless code. +* [8227](https://github.com/kubernetes/ingress-nginx/pull/8227) Update libraries in webhook image +* [8225](https://github.com/kubernetes/ingress-nginx/pull/8225) fix inconsistent-label-cardinality for prometheus metrics: nginx_ingress_controller_requests +* [8221](https://github.com/kubernetes/ingress-nginx/pull/8221) Do not validate ingresses with unknown ingress class in admission webhook endpoint +* [8210](https://github.com/kubernetes/ingress-nginx/pull/8210) Bump github.com/prometheus/client_golang from 1.11.0 to 1.12.1 +* [8209](https://github.com/kubernetes/ingress-nginx/pull/8209) Bump google.golang.org/grpc from 1.43.0 to 1.44.0 +* [8204](https://github.com/kubernetes/ingress-nginx/pull/8204) Add Artifact Hub lint +* [8203](https://github.com/kubernetes/ingress-nginx/pull/8203) Fix Indentation of example and link to cert-manager tutorial +* [8201](https://github.com/kubernetes/ingress-nginx/pull/8201) feat(metrics): add path and method labels to requests countera +* [8199](https://github.com/kubernetes/ingress-nginx/pull/8199) use functional options to reduce number of methods creating an EchoDeployment +* [8196](https://github.com/kubernetes/ingress-nginx/pull/8196) docs: fix inconsistent controller annotation +* [8191](https://github.com/kubernetes/ingress-nginx/pull/8191) Using Go install for misspell +* [8186](https://github.com/kubernetes/ingress-nginx/pull/8186) prometheus+grafana using servicemonitor +* [8185](https://github.com/kubernetes/ingress-nginx/pull/8185) Append elements on match, instead of removing for cors-annotations +* [8179](https://github.com/kubernetes/ingress-nginx/pull/8179) Bump github.com/opencontainers/runc from 1.0.3 to 1.1.0 +* [8173](https://github.com/kubernetes/ingress-nginx/pull/8173) Adding annotations to the controller service account +* [8163](https://github.com/kubernetes/ingress-nginx/pull/8163) Update the $req_id placeholder description +* [8162](https://github.com/kubernetes/ingress-nginx/pull/8162) Versioned static manifests +* [8159](https://github.com/kubernetes/ingress-nginx/pull/8159) Adding some geoip variables and default values +* [8155](https://github.com/kubernetes/ingress-nginx/pull/8155) #7271 feat: avoid-pdb-creation-when-default-backend-disabled-and-replicas-gt-1 +* [8151](https://github.com/kubernetes/ingress-nginx/pull/8151) Automatically generate helm docs +* [8143](https://github.com/kubernetes/ingress-nginx/pull/8143) Allow to configure delay before controller exits +* [8136](https://github.com/kubernetes/ingress-nginx/pull/8136) add ingressClass option to helm chart - back compatibility with ingress.class annotations +* [8126](https://github.com/kubernetes/ingress-nginx/pull/8126) Example for JWT + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.0.15...helm-chart-4.0.18 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.0.2.md b/backing-services/ingress-nginx/changelog/helm-chart-4.0.2.md new file mode 100644 index 0000000..9dbd003 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.0.2.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.0.2 + +* [7681] https://github.com/kubernetes/ingress-nginx/pull/7681 Release v1.0.1 of ingress-nginx + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.0.1...helm-chart-4.0.2 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.0.3.md b/backing-services/ingress-nginx/changelog/helm-chart-4.0.3.md new file mode 100644 index 0000000..09b89f6 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.0.3.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.0.3 + +* [7707] https://github.com/kubernetes/ingress-nginx/pull/7707 Release v1.0.2 of ingress-nginx + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.0.2...helm-chart-4.0.3 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.0.5.md b/backing-services/ingress-nginx/changelog/helm-chart-4.0.5.md new file mode 100644 index 0000000..be67704 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.0.5.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.0.5 + +* [7740] https://github.com/kubernetes/ingress-nginx/pull/7740 Release v1.0.3 of ingress-nginx + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.0.3...helm-chart-4.0.5 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.0.6.md b/backing-services/ingress-nginx/changelog/helm-chart-4.0.6.md new file mode 100644 index 0000000..25276e2 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.0.6.md @@ -0,0 +1,12 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.0.6 + +* [7804] https://github.com/kubernetes/ingress-nginx/pull/7804 Release v1.0.4 of ingress-nginx +* [7651] https://github.com/kubernetes/ingress-nginx/pull/7651 Support ipFamilyPolicy and ipFamilies fields in Helm Chart +* [7798] https://github.com/kubernetes/ingress-nginx/pull/7798 Exoscale: use HTTP Healthcheck mode +* [7793] https://github.com/kubernetes/ingress-nginx/pull/7793 Update kube-webhook-certgen to v1.1.1 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.0.5...helm-chart-4.0.6 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.0.7.md b/backing-services/ingress-nginx/changelog/helm-chart-4.0.7.md new file mode 100644 index 0000000..50fd922 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.0.7.md @@ -0,0 +1,10 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.0.7 + +* [7923] https://github.com/kubernetes/ingress-nginx/pull/7923 Release v1.0.5 of ingress-nginx +* [7806] https://github.com/kubernetes/ingress-nginx/pull/7806 Choice option for internal/external loadbalancer type service + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.0.6...helm-chart-4.0.7 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.0.9.md b/backing-services/ingress-nginx/changelog/helm-chart-4.0.9.md new file mode 100644 index 0000000..f2f725c --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.0.9.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.0.9 + +* [6992] https://github.com/kubernetes/ingress-nginx/pull/6992 Add ability to specify labels for all resources + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.0.7...helm-chart-4.0.9 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.1.0.md b/backing-services/ingress-nginx/changelog/helm-chart-4.1.0.md new file mode 100644 index 0000000..24aaf49 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.1.0.md @@ -0,0 +1,21 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.1.0 + +* [8481](https://github.com/kubernetes/ingress-nginx/pull/8481) Fix log creation in chroot script +* [8479](https://github.com/kubernetes/ingress-nginx/pull/8479) changed nginx base img tag to img built with alpine3.14.6 +* [8478](https://github.com/kubernetes/ingress-nginx/pull/8478) update base images and protobuf gomod +* [8468](https://github.com/kubernetes/ingress-nginx/pull/8468) Fallback to ngx.var.scheme for redirectScheme with use-forward-headers when X-Forwarded-Proto is empty +* [8456](https://github.com/kubernetes/ingress-nginx/pull/8456) Implement object deep inspector +* [8455](https://github.com/kubernetes/ingress-nginx/pull/8455) Update dependencies +* [8454](https://github.com/kubernetes/ingress-nginx/pull/8454) Update index.md +* [8447](https://github.com/kubernetes/ingress-nginx/pull/8447) typo fixing +* [8446](https://github.com/kubernetes/ingress-nginx/pull/8446) Fix suggested annotation-value-word-blocklist +* [8444](https://github.com/kubernetes/ingress-nginx/pull/8444) replace deprecated topology key in example with current one +* [8443](https://github.com/kubernetes/ingress-nginx/pull/8443) Add dependency review enforcement +* [8434](https://github.com/kubernetes/ingress-nginx/pull/8434) added new auth-tls-match-cn annotation +* [8426](https://github.com/kubernetes/ingress-nginx/pull/8426) Bump github.com/prometheus/common from 0.32.1 to 0.33.0 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.0.18...helm-chart-4.1.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.1.2.md b/backing-services/ingress-nginx/changelog/helm-chart-4.1.2.md new file mode 100644 index 0000000..2061855 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.1.2.md @@ -0,0 +1,11 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.1.2 + +* [8587](https://github.com/kubernetes/ingress-nginx/pull/8587) Add CAP_SYS_CHROOT to DS/PSP when needed +* [8458](https://github.com/kubernetes/ingress-nginx/pull/8458) Add portNamePrefix Helm chart parameter +* [8522](https://github.com/kubernetes/ingress-nginx/pull/8522) Add documentation for controller.service.loadBalancerIP in Helm chart + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.1.0...helm-chart-4.1.2 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.10.0.md b/backing-services/ingress-nginx/changelog/helm-chart-4.10.0.md new file mode 100644 index 0000000..a1f1847 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.10.0.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.10.0 + +* - "Update Ingress-Nginx version controller-v1.10.0" + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.9.1...helm-chart-4.10.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.10.1.md b/backing-services/ingress-nginx/changelog/helm-chart-4.10.1.md new file mode 100644 index 0000000..3a28de0 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.10.1.md @@ -0,0 +1,11 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.10.1 + +* - "update post submit helm ci and clean up (#11221)" +* - "refactor helm ci tests part I (#11188)" +* - "Update Ingress-Nginx version controller-v1.10.1" + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.10.0...helm-chart-4.10.1 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.10.2.md b/backing-services/ingress-nginx/changelog/helm-chart-4.10.2.md new file mode 100644 index 0000000..399bd98 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.10.2.md @@ -0,0 +1,18 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.10.2 + +* Chores: Align security contacts & chart maintainers to actual owners. (#11480) +* Fix helm install on cloud provider admonition block (#11412) +* edited helm-install tips (#11411) +* added info for aws helm install (#11410) +* add workflow to helm release and update ct for branch (#11317) +* Merge pull request #11277 from strongjz/chart-1.10.1 (#11314) +* release helm chart from release branch (#11278) +* update post submit helm ci and clean up (#11221) +* refactor helm ci tests part I (#11188) +* Update Ingress-Nginx version controller-v1.10.2 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.10.1...helm-chart-4.10.2 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.11.0.md b/backing-services/ingress-nginx/changelog/helm-chart-4.11.0.md new file mode 100644 index 0000000..64108c0 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.11.0.md @@ -0,0 +1,18 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.11.0 + +* Chores: Align security contacts & chart maintainers to actual owners. (#11465) +* Merge pull request #11277 from strongjz/chart-1.10.1 (#11415) +* Fix helm install on cloud provider admonition block (#11394) +* edited helm-install tips (#11393) +* added info for aws helm install (#11390) +* add workflow to helm release and update ct for branch (#11378) +* release helm chart from release branch (#11276) +* update post submit helm ci and clean up (#11220) +* refactor helm ci tests part I (#11178) +* Update Ingress-Nginx version controller-v1.11.0 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.10.2...helm-chart-4.11.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.11.1.md b/backing-services/ingress-nginx/changelog/helm-chart-4.11.1.md new file mode 100644 index 0000000..281513e --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.11.1.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.11.1 + +* Update Ingress-Nginx version controller-v1.11.1 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.11.0...helm-chart-4.11.1 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.11.2.md b/backing-services/ingress-nginx/changelog/helm-chart-4.11.2.md new file mode 100644 index 0000000..c7645a5 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.11.2.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.11.2 + +* Update Ingress-Nginx version controller-v1.11.2 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.11.1...helm-chart-4.11.2 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.11.3.md b/backing-services/ingress-nginx/changelog/helm-chart-4.11.3.md new file mode 100644 index 0000000..18ec6ba --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.11.3.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.11.3 + +* Update Ingress-Nginx version controller-v1.11.3 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.11.2...helm-chart-4.11.3 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.2.0.md b/backing-services/ingress-nginx/changelog/helm-chart-4.2.0.md new file mode 100644 index 0000000..2074a09 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.2.0.md @@ -0,0 +1,47 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.2.0 + +* Support for Kubernetes v1.19.0 was removed +* [8810](https://github.com/kubernetes/ingress-nginx/pull/8810) Prepare for v1.3.0 +* [8808](https://github.com/kubernetes/ingress-nginx/pull/8808) revert arch var name +* [8805](https://github.com/kubernetes/ingress-nginx/pull/8805) Bump k8s.io/klog/v2 from 2.60.1 to 2.70.1 +* [8803](https://github.com/kubernetes/ingress-nginx/pull/8803) Update to nginx base with alpine v3.16 +* [8802](https://github.com/kubernetes/ingress-nginx/pull/8802) chore: start v1.3.0 release process +* [8798](https://github.com/kubernetes/ingress-nginx/pull/8798) Add v1.24.0 to test matrix +* [8796](https://github.com/kubernetes/ingress-nginx/pull/8796) fix: add MAC_OS variable for static-check +* [8793](https://github.com/kubernetes/ingress-nginx/pull/8793) changed to alpine-v3.16 +* [8781](https://github.com/kubernetes/ingress-nginx/pull/8781) Bump github.com/stretchr/testify from 1.7.5 to 1.8.0 +* [8778](https://github.com/kubernetes/ingress-nginx/pull/8778) chore: remove stable.txt from release process +* [8775](https://github.com/kubernetes/ingress-nginx/pull/8775) Remove stable +* [8773](https://github.com/kubernetes/ingress-nginx/pull/8773) Bump github/codeql-action from 2.1.14 to 2.1.15 +* [8772](https://github.com/kubernetes/ingress-nginx/pull/8772) Bump ossf/scorecard-action from 1.1.1 to 1.1.2 +* [8771](https://github.com/kubernetes/ingress-nginx/pull/8771) fix bullet md format +* [8770](https://github.com/kubernetes/ingress-nginx/pull/8770) Add condition for monitoring.coreos.com/v1 API +* [8769](https://github.com/kubernetes/ingress-nginx/pull/8769) Fix typos and add links to developer guide +* [8767](https://github.com/kubernetes/ingress-nginx/pull/8767) change v1.2.0 to v1.2.1 in deploy doc URLs +* [8765](https://github.com/kubernetes/ingress-nginx/pull/8765) Bump github/codeql-action from 1.0.26 to 2.1.14 +* [8752](https://github.com/kubernetes/ingress-nginx/pull/8752) Bump github.com/spf13/cobra from 1.4.0 to 1.5.0 +* [8751](https://github.com/kubernetes/ingress-nginx/pull/8751) Bump github.com/stretchr/testify from 1.7.2 to 1.7.5 +* [8750](https://github.com/kubernetes/ingress-nginx/pull/8750) added announcement +* [8740](https://github.com/kubernetes/ingress-nginx/pull/8740) change sha e2etestrunner and echoserver +* [8738](https://github.com/kubernetes/ingress-nginx/pull/8738) Update docs to make it easier for noobs to follow step by step +* [8737](https://github.com/kubernetes/ingress-nginx/pull/8737) updated baseimage sha +* [8736](https://github.com/kubernetes/ingress-nginx/pull/8736) set ld-musl-path +* [8733](https://github.com/kubernetes/ingress-nginx/pull/8733) feat: migrate leaderelection lock to leases +* [8726](https://github.com/kubernetes/ingress-nginx/pull/8726) prometheus metric: upstream_latency_seconds +* [8720](https://github.com/kubernetes/ingress-nginx/pull/8720) Ci pin deps +* [8719](https://github.com/kubernetes/ingress-nginx/pull/8719) Working OpenTelemetry sidecar (base nginx image) +* [8714](https://github.com/kubernetes/ingress-nginx/pull/8714) Create Openssf scorecard +* [8708](https://github.com/kubernetes/ingress-nginx/pull/8708) Bump github.com/prometheus/common from 0.34.0 to 0.35.0 +* [8703](https://github.com/kubernetes/ingress-nginx/pull/8703) Bump actions/dependency-review-action from 1 to 2 +* [8701](https://github.com/kubernetes/ingress-nginx/pull/8701) Fix several typos +* [8699](https://github.com/kubernetes/ingress-nginx/pull/8699) fix the gosec test and a make target for it +* [8698](https://github.com/kubernetes/ingress-nginx/pull/8698) Bump actions/upload-artifact from 2.3.1 to 3.1.0 +* [8697](https://github.com/kubernetes/ingress-nginx/pull/8697) Bump actions/setup-go from 2.2.0 to 3.2.0 +* [8695](https://github.com/kubernetes/ingress-nginx/pull/8695) Bump actions/download-artifact from 2 to 3 +* [8694](https://github.com/kubernetes/ingress-nginx/pull/8694) Bump crazy-max/ghaction-docker-buildx from 1.6.2 to 3.3.1 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.1.2...helm-chart-4.2.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.2.1.md b/backing-services/ingress-nginx/changelog/helm-chart-4.2.1.md new file mode 100644 index 0000000..7965bb1 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.2.1.md @@ -0,0 +1,10 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.2.1 + +* The sha of kube-webhook-certgen image & the opentelemetry image, in values file, was changed to new images built on alpine-v3.16.1 +* [8896](https://github.com/kubernetes/ingress-nginx/pull/8896) updated to new images built today + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.2.0...helm-chart-4.2.1 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.3.0.md b/backing-services/ingress-nginx/changelog/helm-chart-4.3.0.md new file mode 100644 index 0000000..f9dca22 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.3.0.md @@ -0,0 +1,14 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.3.0 + +* Support for Kubernetes v.1.25.0 was added and support for endpoint slices +* Support for Kubernetes v1.20.0 and v1.21.0 was removed +* [8890](https://github.com/kubernetes/ingress-nginx/pull/8890) migrate to endpointslices +* [9059](https://github.com/kubernetes/ingress-nginx/pull/9059) kubewebhookcertgen sha change after go1191 +* [9046](https://github.com/kubernetes/ingress-nginx/pull/9046) Parameterize metrics port name +* [9104](https://github.com/kubernetes/ingress-nginx/pull/9104) Fix yaml formatting error with multiple annotations + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.2.1...helm-chart-4.3.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.4.0.md b/backing-services/ingress-nginx/changelog/helm-chart-4.4.0.md new file mode 100644 index 0000000..20f9e23 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.4.0.md @@ -0,0 +1,12 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.4.0 + +* Adding support for disabling liveness and readiness probes to the Helm chart by @njegosrailic in https://github.com/kubernetes/ingress-nginx/pull/9238 +* add:(admission-webhooks) ability to set securityContext by @ybelMekk in https://github.com/kubernetes/ingress-nginx/pull/9186 +* #7652 - Updated Helm chart to use the fullname for the electionID if not specified. by @FutureMatt in https://github.com/kubernetes/ingress-nginx/pull/9133 +* Rename controller-wehbooks-networkpolicy.yaml. by @Gacko in https://github.com/kubernetes/ingress-nginx/pull/9123 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.3.0...helm-chart-4.4.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.5.2.md b/backing-services/ingress-nginx/changelog/helm-chart-4.5.2.md new file mode 100644 index 0000000..b6d8a3b --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.5.2.md @@ -0,0 +1,13 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.5.2 + +* add lint on chart before release (#9570) +* ci: remove setup-helm step (#9404) +* feat(helm): Optionally use cert-manager instead admission patch (#9279) +* run helm release on main only and when the chart/value changes only (#9290) +* Update Ingress-Nginx version controller-v1.6.4 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.4.3...helm-chart-4.5.2 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.6.0.md b/backing-services/ingress-nginx/changelog/helm-chart-4.6.0.md new file mode 100644 index 0000000..469aaba --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.6.0.md @@ -0,0 +1,24 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.5.3 + +* docs(helm): fix value key in readme for enabling certManager (#9640) +* Upgrade alpine 3.17.2 +* Upgrade golang 1.20 +* Drop testing/support for Kubernetes 1.23 +* docs(helm): fix value key in readme for enabling certManager (#9640) +* Update Ingress-Nginx version controller-v1.7.0 +* feat: OpenTelemetry module integration (#9062) +* canary-weight-total annotation ignored in rule backends (#9729) +* fix controller psp's volume config (#9740) +* Fix several Helm YAML issues with extraModules and extraInitContainers (#9709) +* Chart: Drop `controller.headers`, rework DH param secret. (#9659) +* Deployment/DaemonSet: Label pods using `ingress-nginx.labels`. (#9732) +* HPA: autoscaling/v2beta1 deprecated, bump apiVersion to v2 for defaultBackend (#9731) +* Fix incorrect annotation name in upstream hashing configuration (#9617) + +* Update Ingress-Nginx version controller-v1.7.0 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.5.2...helm-chart-4.6.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.6.1.md b/backing-services/ingress-nginx/changelog/helm-chart-4.6.1.md new file mode 100644 index 0000000..57d99b8 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.6.1.md @@ -0,0 +1,11 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.6.1 + +* [helm] Support custom port configuration for internal service (#9846) +* Adding resource type to default HPA configuration to resolve issues with Terraform helm chart usage (#9803) +* Update Ingress-Nginx version controller-v1.7.1 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.6.0...helm-chart-4.6.1 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.7.0.md b/backing-services/ingress-nginx/changelog/helm-chart-4.7.0.md new file mode 100644 index 0000000..9d54070 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.7.0.md @@ -0,0 +1,14 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.7.0 + +* helm: Fix opentelemetry module installation for daemonset (#9792) +* Update charts/* to keep project name display aligned (#9931) +* HPA: Use capabilities & align manifests. (#9521) +* PodDisruptionBudget spec logic update (#9904) +* add option for annotations in PodDisruptionBudget (#9843) +* Update Ingress-Nginx version controller-v1.8.0 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.6.1...helm-chart-4.7.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.7.1.md b/backing-services/ingress-nginx/changelog/helm-chart-4.7.1.md new file mode 100644 index 0000000..4d69a71 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.7.1.md @@ -0,0 +1,12 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.7.1 + +* Added a doc line to the missing helm value service.internal.loadBalancerIP (#9406) +* feat(helm): Add loadBalancerClass (#9562) +* added helmshowvalues example (#10019) +* Update Ingress-Nginx version controller-v1.8.1 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.7.0...helm-chart-4.7.1 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.7.2.md b/backing-services/ingress-nginx/changelog/helm-chart-4.7.2.md new file mode 100644 index 0000000..57b17b9 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.7.2.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.7.2 + +* Update Ingress-Nginx version controller-v1.8.2 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.7.1...helm-chart-4.7.2 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.8.0-beta.0.md b/backing-services/ingress-nginx/changelog/helm-chart-4.8.0-beta.0.md new file mode 100644 index 0000000..9072a75 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.8.0-beta.0.md @@ -0,0 +1,13 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.8.0-beta.0 + +* ci(helm): fix Helm Chart release action 422 error (#10237) +* helm: Use .Release.Namespace as default for ServiceMonitor namespace (#10249) +* [helm] configure allow to configure hostAliases (#10180) +* [helm] pass service annotations through helm tpl engine (#10084) +* Update Ingress-Nginx version controller-v1.9.0-beta.0 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.7.2...helm-chart-4.8.0-beta.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.8.0.md b/backing-services/ingress-nginx/changelog/helm-chart-4.8.0.md new file mode 100644 index 0000000..af8f124 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.8.0.md @@ -0,0 +1,13 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.8.0 + +* ci(helm): fix Helm Chart release action 422 error (#10237) +* helm: Use .Release.Namespace as default for ServiceMonitor namespace (#10249) +* [helm] configure allow to configure hostAliases (#10180) +* [helm] pass service annotations through helm tpl engine (#10084) +* Update Ingress-Nginx version controller-v1.9.0 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.7.2...helm-chart-4.8.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.8.1.md b/backing-services/ingress-nginx/changelog/helm-chart-4.8.1.md new file mode 100644 index 0000000..53a4493 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.8.1.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.8.1 + +* Update Ingress-Nginx version controller-v1.9.1 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.8.0...helm-chart-4.8.1 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.8.2.md b/backing-services/ingress-nginx/changelog/helm-chart-4.8.2.md new file mode 100644 index 0000000..9957c1a --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.8.2.md @@ -0,0 +1,10 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.8.2 + +* update nginx base, httpbun, e2e, helm webhook cert gen (#10506) +* Update Ingress-Nginx version controller-v1.9.3 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.8.1...helm-chart-4.8.2 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.8.3.md b/backing-services/ingress-nginx/changelog/helm-chart-4.8.3.md new file mode 100644 index 0000000..b8d4d56 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.8.3.md @@ -0,0 +1,9 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.8.3 + +* Update Ingress-Nginx version controller-v1.9.4 + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.8.2...helm-chart-4.8.3 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.9.0.md b/backing-services/ingress-nginx/changelog/helm-chart-4.9.0.md new file mode 100644 index 0000000..5c77298 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.9.0.md @@ -0,0 +1,13 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.9.0 + +* - "Add controller.metrics.serviceMonitor.annotations in Helm chart" +* - "fix(labels): use complete labels variable on default-backend deployment" +* - "chart: allow setting allocateLoadBalancerNodePorts (#10693)" +* - "[release-1.9] feat(helm): add documentation about metric args (#10695)" +* - "Update Ingress-Nginx version controller-v1.9.5" + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.8.3...helm-chart-4.9.0 diff --git a/backing-services/ingress-nginx/changelog/helm-chart-4.9.1.md b/backing-services/ingress-nginx/changelog/helm-chart-4.9.1.md new file mode 100644 index 0000000..c6120e7 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart-4.9.1.md @@ -0,0 +1,10 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### 4.9.1 + +* - "update web hook cert gen to latest release v20231226-1a7112e06" +* - "Update Ingress-Nginx version controller-v1.9.6" + +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.9.0...helm-chart-4.9.1 diff --git a/backing-services/ingress-nginx/changelog/helm-chart.md.gotmpl b/backing-services/ingress-nginx/changelog/helm-chart.md.gotmpl new file mode 100644 index 0000000..ef5add5 --- /dev/null +++ b/backing-services/ingress-nginx/changelog/helm-chart.md.gotmpl @@ -0,0 +1,11 @@ +# Changelog + +This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). + +### {{ .NewHelmChartVersion }} +{{ with .HelmUpdates }} +{{- range . }} +* {{ . }} +{{- end }} +{{ end }} +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-{{ .PreviousHelmChartVersion }}...helm-chart-{{ .NewHelmChartVersion }} diff --git a/backing-services/ingress-nginx/ci/admission-webhooks-cert-manager-values.yaml b/backing-services/ingress-nginx/ci/admission-webhooks-cert-manager-values.yaml new file mode 100644 index 0000000..7eafd0c --- /dev/null +++ b/backing-services/ingress-nginx/ci/admission-webhooks-cert-manager-values.yaml @@ -0,0 +1,12 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + + service: + type: ClusterIP + + admissionWebhooks: + certManager: + enabled: true diff --git a/backing-services/ingress-nginx/ci/controller-configmap-addheaders-values.yaml b/backing-services/ingress-nginx/ci/controller-configmap-addheaders-values.yaml new file mode 100644 index 0000000..460a610 --- /dev/null +++ b/backing-services/ingress-nginx/ci/controller-configmap-addheaders-values.yaml @@ -0,0 +1,11 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + + service: + type: ClusterIP + + addHeaders: + X-Frame-Options: deny diff --git a/backing-services/ingress-nginx/ci/controller-configmap-proxyheaders-values.yaml b/backing-services/ingress-nginx/ci/controller-configmap-proxyheaders-values.yaml new file mode 100644 index 0000000..e23a13c --- /dev/null +++ b/backing-services/ingress-nginx/ci/controller-configmap-proxyheaders-values.yaml @@ -0,0 +1,11 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + + service: + type: ClusterIP + + proxySetHeaders: + X-Forwarded-Proto: https diff --git a/backing-services/ingress-nginx/ci/controller-configmap-values.yaml b/backing-services/ingress-nginx/ci/controller-configmap-values.yaml new file mode 100644 index 0000000..a702989 --- /dev/null +++ b/backing-services/ingress-nginx/ci/controller-configmap-values.yaml @@ -0,0 +1,11 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + + service: + type: ClusterIP + + config: + use-proxy-protocol: "true" diff --git a/backing-services/ingress-nginx/ci/controller-daemonset-extra-modules-values.yaml b/backing-services/ingress-nginx/ci/controller-daemonset-extra-modules-values.yaml new file mode 100644 index 0000000..edf12e7 --- /dev/null +++ b/backing-services/ingress-nginx/ci/controller-daemonset-extra-modules-values.yaml @@ -0,0 +1,30 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + + service: + type: ClusterIP + + kind: DaemonSet + + extraModules: + - name: opentelemetry + image: + registry: registry.k8s.io + image: ingress-nginx/opentelemetry-1.25.3 + tag: v20240813-b933310d + digest: sha256:f7604ac0547ed64d79b98d92133234e66c2c8aade3c1f4809fed5eec1fb7f922 + distroless: true + containerSecurityContext: + runAsNonRoot: true + runAsUser: 65532 + runAsGroup: 65532 + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true diff --git a/backing-services/ingress-nginx/ci/controller-daemonset-metrics-values.yaml b/backing-services/ingress-nginx/ci/controller-daemonset-metrics-values.yaml new file mode 100644 index 0000000..7a98580 --- /dev/null +++ b/backing-services/ingress-nginx/ci/controller-daemonset-metrics-values.yaml @@ -0,0 +1,13 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + + service: + type: ClusterIP + + kind: DaemonSet + + metrics: + enabled: true diff --git a/backing-services/ingress-nginx/ci/controller-daemonset-opentelemetry-values.yaml b/backing-services/ingress-nginx/ci/controller-daemonset-opentelemetry-values.yaml new file mode 100644 index 0000000..179ab2a --- /dev/null +++ b/backing-services/ingress-nginx/ci/controller-daemonset-opentelemetry-values.yaml @@ -0,0 +1,13 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + + service: + type: ClusterIP + + kind: DaemonSet + + opentelemetry: + enabled: true diff --git a/backing-services/ingress-nginx/ci/controller-daemonset-podannotations-values.yaml b/backing-services/ingress-nginx/ci/controller-daemonset-podannotations-values.yaml new file mode 100644 index 0000000..405992e --- /dev/null +++ b/backing-services/ingress-nginx/ci/controller-daemonset-podannotations-values.yaml @@ -0,0 +1,16 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + + service: + type: ClusterIP + + kind: DaemonSet + + podAnnotations: + prometheus.io/scrape: "true" + prometheus.io/port: "10254" + prometheus.io/scheme: http + prometheus.io/path: /metrics diff --git a/backing-services/ingress-nginx/ci/controller-daemonset-values.yaml b/backing-services/ingress-nginx/ci/controller-daemonset-values.yaml new file mode 100644 index 0000000..d34025c --- /dev/null +++ b/backing-services/ingress-nginx/ci/controller-daemonset-values.yaml @@ -0,0 +1,10 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + + service: + type: ClusterIP + + kind: DaemonSet diff --git a/backing-services/ingress-nginx/ci/controller-deployment-extra-modules-values.yaml b/backing-services/ingress-nginx/ci/controller-deployment-extra-modules-values.yaml new file mode 100644 index 0000000..d4083cc --- /dev/null +++ b/backing-services/ingress-nginx/ci/controller-deployment-extra-modules-values.yaml @@ -0,0 +1,30 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + + service: + type: ClusterIP + + kind: Deployment + + extraModules: + - name: opentelemetry + image: + registry: registry.k8s.io + image: ingress-nginx/opentelemetry-1.25.3 + tag: v20240813-b933310d + digest: sha256:f7604ac0547ed64d79b98d92133234e66c2c8aade3c1f4809fed5eec1fb7f922 + distroless: true + containerSecurityContext: + runAsNonRoot: true + runAsUser: 65532 + runAsGroup: 65532 + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true diff --git a/backing-services/ingress-nginx/ci/controller-deployment-metrics-values.yaml b/backing-services/ingress-nginx/ci/controller-deployment-metrics-values.yaml new file mode 100644 index 0000000..9c95d34 --- /dev/null +++ b/backing-services/ingress-nginx/ci/controller-deployment-metrics-values.yaml @@ -0,0 +1,13 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + + service: + type: ClusterIP + + kind: Deployment + + metrics: + enabled: true diff --git a/backing-services/ingress-nginx/ci/controller-deployment-opentelemetry-values.yaml b/backing-services/ingress-nginx/ci/controller-deployment-opentelemetry-values.yaml new file mode 100644 index 0000000..9443dde --- /dev/null +++ b/backing-services/ingress-nginx/ci/controller-deployment-opentelemetry-values.yaml @@ -0,0 +1,13 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + + service: + type: ClusterIP + + kind: Deployment + + opentelemetry: + enabled: true diff --git a/backing-services/ingress-nginx/ci/controller-deployment-podannotations-values.yaml b/backing-services/ingress-nginx/ci/controller-deployment-podannotations-values.yaml new file mode 100644 index 0000000..cf1f261 --- /dev/null +++ b/backing-services/ingress-nginx/ci/controller-deployment-podannotations-values.yaml @@ -0,0 +1,16 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + + service: + type: ClusterIP + + kind: Deployment + + podAnnotations: + prometheus.io/scrape: "true" + prometheus.io/port: "10254" + prometheus.io/scheme: http + prometheus.io/path: /metrics diff --git a/backing-services/ingress-nginx/ci/controller-deployment-values.yaml b/backing-services/ingress-nginx/ci/controller-deployment-values.yaml new file mode 100644 index 0000000..1b092dc --- /dev/null +++ b/backing-services/ingress-nginx/ci/controller-deployment-values.yaml @@ -0,0 +1,10 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + + service: + type: ClusterIP + + kind: Deployment diff --git a/backing-services/ingress-nginx/ci/controller-hpa-values.yaml b/backing-services/ingress-nginx/ci/controller-hpa-values.yaml new file mode 100644 index 0000000..54a0d2f --- /dev/null +++ b/backing-services/ingress-nginx/ci/controller-hpa-values.yaml @@ -0,0 +1,18 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + + service: + type: ClusterIP + + autoscaling: + enabled: true + behavior: + scaleDown: + stabilizationWindowSeconds: 300 + policies: + - type: Pods + value: 1 + periodSeconds: 180 diff --git a/backing-services/ingress-nginx/ci/controller-ingressclass-values.yaml b/backing-services/ingress-nginx/ci/controller-ingressclass-values.yaml new file mode 100644 index 0000000..c06429f --- /dev/null +++ b/backing-services/ingress-nginx/ci/controller-ingressclass-values.yaml @@ -0,0 +1,15 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + + service: + type: ClusterIP + + ingressClassResource: + name: custom-nginx + default: true + controllerValue: k8s.io/custom-nginx + + watchIngressWithoutClass: true diff --git a/backing-services/ingress-nginx/ci/controller-service-internal-values.yaml b/backing-services/ingress-nginx/ci/controller-service-internal-values.yaml new file mode 100644 index 0000000..11108fb --- /dev/null +++ b/backing-services/ingress-nginx/ci/controller-service-internal-values.yaml @@ -0,0 +1,13 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + + service: + type: ClusterIP + + internal: + enabled: true + annotations: + service.beta.kubernetes.io/aws-load-balancer-internal: "true" diff --git a/backing-services/ingress-nginx/ci/controller-service-values.yaml b/backing-services/ingress-nginx/ci/controller-service-values.yaml new file mode 100644 index 0000000..9039368 --- /dev/null +++ b/backing-services/ingress-nginx/ci/controller-service-values.yaml @@ -0,0 +1,22 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + + service: + type: NodePort + + nodePorts: + tcp: + 9000: 30090 + udp: + 9001: 30091 + +portNamePrefix: port + +tcp: + 9000: default/test:8080 + +udp: + 9001: default/test:8080 diff --git a/backing-services/ingress-nginx/ci/deamonset-psp-values.yaml b/backing-services/ingress-nginx/ci/deamonset-psp-values.yaml new file mode 100644 index 0000000..8026a63 --- /dev/null +++ b/backing-services/ingress-nginx/ci/deamonset-psp-values.yaml @@ -0,0 +1,13 @@ +controller: + kind: DaemonSet + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: false + service: + type: ClusterIP + +podSecurityPolicy: + enabled: true diff --git a/backing-services/ingress-nginx/ci/deamonset-webhook-and-psp-values.yaml b/backing-services/ingress-nginx/ci/deamonset-webhook-and-psp-values.yaml new file mode 100644 index 0000000..fccdb13 --- /dev/null +++ b/backing-services/ingress-nginx/ci/deamonset-webhook-and-psp-values.yaml @@ -0,0 +1,13 @@ +controller: + kind: DaemonSet + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: true + service: + type: ClusterIP + +podSecurityPolicy: + enabled: true diff --git a/backing-services/ingress-nginx/ci/deployment-psp-values.yaml b/backing-services/ingress-nginx/ci/deployment-psp-values.yaml new file mode 100644 index 0000000..2f332a7 --- /dev/null +++ b/backing-services/ingress-nginx/ci/deployment-psp-values.yaml @@ -0,0 +1,10 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + service: + type: ClusterIP + +podSecurityPolicy: + enabled: true diff --git a/backing-services/ingress-nginx/ci/deployment-webhook-and-psp-values.yaml b/backing-services/ingress-nginx/ci/deployment-webhook-and-psp-values.yaml new file mode 100644 index 0000000..6195bb3 --- /dev/null +++ b/backing-services/ingress-nginx/ci/deployment-webhook-and-psp-values.yaml @@ -0,0 +1,12 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: true + service: + type: ClusterIP + +podSecurityPolicy: + enabled: true diff --git a/backing-services/ingress-nginx/hospital-bahman-production.values.yaml b/backing-services/ingress-nginx/hospital-bahman-production.values.yaml new file mode 100644 index 0000000..4c8e93c --- /dev/null +++ b/backing-services/ingress-nginx/hospital-bahman-production.values.yaml @@ -0,0 +1,12 @@ +controller: + name: controller + enableAnnotationValidations: false + image: + ## Keep false as default for now! + chroot: false + registry: 172.16.16.1:30516 + image: ingress-nginx/controller + +service: + ports: + mongodb: 27018 \ No newline at end of file diff --git a/backing-services/ingress-nginx/schoolbus-demo.values.yaml b/backing-services/ingress-nginx/schoolbus-demo.values.yaml new file mode 100644 index 0000000..ebb73af --- /dev/null +++ b/backing-services/ingress-nginx/schoolbus-demo.values.yaml @@ -0,0 +1,8 @@ +controller: + name: controller + enableAnnotationValidations: false + image: + ## Keep false as default for now! + chroot: false + registry: 172.16.16.2:30516 + image: ingress-nginx/controller \ No newline at end of file diff --git a/backing-services/ingress-nginx/templates/NOTES.txt b/backing-services/ingress-nginx/templates/NOTES.txt new file mode 100644 index 0000000..f492300 --- /dev/null +++ b/backing-services/ingress-nginx/templates/NOTES.txt @@ -0,0 +1,73 @@ +The ingress-nginx controller has been installed. + +{{- if contains "NodePort" .Values.controller.service.type }} +Get the application URL by running these commands: + +{{- if (not (empty .Values.controller.service.nodePorts.http)) }} + export HTTP_NODE_PORT={{ .Values.controller.service.nodePorts.http }} +{{- else }} + export HTTP_NODE_PORT=$(kubectl get service --namespace {{ include "ingress-nginx.namespace" . }} {{ include "ingress-nginx.controller.fullname" . }} --output jsonpath="{.spec.ports[0].nodePort}") +{{- end }} +{{- if (not (empty .Values.controller.service.nodePorts.https)) }} + export HTTPS_NODE_PORT={{ .Values.controller.service.nodePorts.https }} +{{- else }} + export HTTPS_NODE_PORT=$(kubectl get service --namespace {{ include "ingress-nginx.namespace" . }} {{ include "ingress-nginx.controller.fullname" . }} --output jsonpath="{.spec.ports[1].nodePort}") +{{- end }} + export NODE_IP="$(kubectl get nodes --output jsonpath="{.items[0].status.addresses[1].address}")" + + echo "Visit http://${NODE_IP}:${HTTP_NODE_PORT} to access your application via HTTP." + echo "Visit https://${NODE_IP}:${HTTPS_NODE_PORT} to access your application via HTTPS." +{{- else if contains "LoadBalancer" .Values.controller.service.type }} +It may take a few minutes for the load balancer IP to be available. +You can watch the status by running 'kubectl get service --namespace {{ include "ingress-nginx.namespace" . }} {{ include "ingress-nginx.controller.fullname" . }} --output wide --watch' +{{- else if contains "ClusterIP" .Values.controller.service.type }} +Get the application URL by running these commands: + export POD_NAME="$(kubectl get pods --namespace {{ include "ingress-nginx.namespace" . }} --selector app.kubernetes.io/name={{ include "ingress-nginx.name" . }},app.kubernetes.io/instance={{ .Release.Name }},app.kubernetes.io/component=controller --output jsonpath="{.items[0].metadata.name}")" + kubectl port-forward --namespace {{ include "ingress-nginx.namespace" . }} "${POD_NAME}" 8080:80 + echo "Visit http://127.0.0.1:8080 to access your application." +{{- end }} + +An example Ingress that makes use of the controller: + +{{- $isV1 := semverCompare ">=1" .Chart.AppVersion}} + apiVersion: networking.k8s.io/v1 + kind: Ingress + metadata: + name: example + namespace: foo + {{- if eq $isV1 false }} + annotations: + kubernetes.io/ingress.class: {{ .Values.controller.ingressClass }} + {{- end }} + spec: + {{- if $isV1 }} + ingressClassName: {{ .Values.controller.ingressClassResource.name }} + {{- end }} + rules: + - host: www.example.com + http: + paths: + - pathType: Prefix + backend: + service: + name: exampleService + port: + number: 80 + path: / + # This section is only required if TLS is to be enabled for the Ingress + tls: + - hosts: + - www.example.com + secretName: example-tls + +If TLS is enabled for the Ingress, a Secret containing the certificate and key must also be provided: + + apiVersion: v1 + kind: Secret + metadata: + name: example-tls + namespace: foo + data: + tls.crt: + tls.key: + type: kubernetes.io/tls diff --git a/backing-services/ingress-nginx/templates/_helpers.tpl b/backing-services/ingress-nginx/templates/_helpers.tpl new file mode 100644 index 0000000..24cfd14 --- /dev/null +++ b/backing-services/ingress-nginx/templates/_helpers.tpl @@ -0,0 +1,272 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "ingress-nginx.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "ingress-nginx.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | 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 "ingress-nginx.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 -}} + +{{/* +Expand the namespace of the release. +Allows overriding it for multi-namespace deployments in combined charts. +*/}} +{{- define "ingress-nginx.namespace" -}} +{{- default .Release.Namespace .Values.namespaceOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Controller container security context. +*/}} +{{- define "ingress-nginx.controller.containerSecurityContext" -}} +{{- if .Values.controller.containerSecurityContext -}} +{{- toYaml .Values.controller.containerSecurityContext -}} +{{- else -}} +runAsNonRoot: {{ .Values.controller.image.runAsNonRoot }} +runAsUser: {{ .Values.controller.image.runAsUser }} +allowPrivilegeEscalation: {{ or .Values.controller.image.allowPrivilegeEscalation .Values.controller.image.chroot }} +{{- if .Values.controller.image.seccompProfile }} +seccompProfile: {{ toYaml .Values.controller.image.seccompProfile | nindent 2 }} +{{- end }} +capabilities: + drop: + - ALL + add: + - NET_BIND_SERVICE + {{- if .Values.controller.image.chroot }} + {{- if .Values.controller.image.seccompProfile }} + - SYS_ADMIN + {{- end }} + - SYS_CHROOT + {{- end }} +readOnlyRootFilesystem: {{ .Values.controller.image.readOnlyRootFilesystem }} +{{- end -}} +{{- end -}} + +{{/* +Get specific image +*/}} +{{- define "ingress-nginx.image" -}} +{{- if .chroot -}} +{{- printf "%s-chroot" .image -}} +{{- else -}} +{{- printf "%s" .image -}} +{{- end }} +{{- end -}} + +{{/* +Get specific image digest +*/}} +{{- define "ingress-nginx.imageDigest" -}} +{{- if .chroot -}} +{{- if .digestChroot -}} +{{- printf "@%s" .digestChroot -}} +{{- end }} +{{- else -}} +{{ if .digest -}} +{{- printf "@%s" .digest -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified controller name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "ingress-nginx.controller.fullname" -}} +{{- printf "%s-%s" (include "ingress-nginx.fullname" .) .Values.controller.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Construct a unique electionID. +Users can provide an override for an explicit electionID if they want via `.Values.controller.electionID` +*/}} +{{- define "ingress-nginx.controller.electionID" -}} +{{- $defElectionID := printf "%s-leader" (include "ingress-nginx.fullname" .) -}} +{{- $electionID := default $defElectionID .Values.controller.electionID -}} +{{- print $electionID -}} +{{- end -}} + +{{/* +Construct the path for the publish-service. + +By convention this will simply use the / to match the name of the +service generated. + +Users can provide an override for an explicit service they want bound via `.Values.controller.publishService.pathOverride` +*/}} +{{- define "ingress-nginx.controller.publishServicePath" -}} +{{- $defServiceName := printf "%s/%s" "$(POD_NAMESPACE)" (include "ingress-nginx.controller.fullname" .) -}} +{{- $servicePath := default $defServiceName .Values.controller.publishService.pathOverride }} +{{- print $servicePath | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "ingress-nginx.labels" -}} +helm.sh/chart: {{ include "ingress-nginx.chart" . }} +{{ include "ingress-nginx.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/part-of: {{ template "ingress-nginx.name" . }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- if .Values.commonLabels}} +{{ toYaml .Values.commonLabels }} +{{- end }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "ingress-nginx.selectorLabels" -}} +app.kubernetes.io/name: {{ include "ingress-nginx.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the controller service account to use +*/}} +{{- define "ingress-nginx.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "ingress-nginx.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified admission webhook name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "ingress-nginx.admissionWebhooks.fullname" -}} +{{- printf "%s-%s" (include "ingress-nginx.fullname" .) .Values.controller.admissionWebhooks.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create the name of the admission webhook patch job service account to use +*/}} +{{- define "ingress-nginx.admissionWebhooks.patch.serviceAccountName" -}} +{{- if .Values.controller.admissionWebhooks.patch.serviceAccount.create -}} + {{ default (include "ingress-nginx.admissionWebhooks.fullname" .) .Values.controller.admissionWebhooks.patch.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.controller.admissionWebhooks.patch.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified admission webhook secret creation job name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "ingress-nginx.admissionWebhooks.createSecretJob.fullname" -}} +{{- printf "%s-%s" (include "ingress-nginx.admissionWebhooks.fullname" .) .Values.controller.admissionWebhooks.createSecretJob.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified admission webhook patch job name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "ingress-nginx.admissionWebhooks.patchWebhookJob.fullname" -}} +{{- printf "%s-%s" (include "ingress-nginx.admissionWebhooks.fullname" .) .Values.controller.admissionWebhooks.patchWebhookJob.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified default backend name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "ingress-nginx.defaultBackend.fullname" -}} +{{- printf "%s-%s" (include "ingress-nginx.fullname" .) .Values.defaultBackend.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create the name of the default backend service account to use +*/}} +{{- define "ingress-nginx.defaultBackend.serviceAccountName" -}} +{{- if .Values.defaultBackend.serviceAccount.create -}} + {{ default (printf "%s-backend" (include "ingress-nginx.fullname" .)) .Values.defaultBackend.serviceAccount.name }} +{{- else -}} + {{ default "default-backend" .Values.defaultBackend.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Default backend container security context. +*/}} +{{- define "ingress-nginx.defaultBackend.containerSecurityContext" -}} +{{- if .Values.defaultBackend.containerSecurityContext -}} +{{- toYaml .Values.defaultBackend.containerSecurityContext -}} +{{- else -}} +runAsNonRoot: {{ .Values.defaultBackend.image.runAsNonRoot }} +runAsUser: {{ .Values.defaultBackend.image.runAsUser }} +allowPrivilegeEscalation: {{ .Values.defaultBackend.image.allowPrivilegeEscalation }} +{{- if .Values.defaultBackend.image.seccompProfile }} +seccompProfile: {{ toYaml .Values.defaultBackend.image.seccompProfile | nindent 2 }} +{{- end }} +capabilities: + drop: + - ALL +readOnlyRootFilesystem: {{ .Values.defaultBackend.image.readOnlyRootFilesystem }} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiGroup for PodSecurityPolicy. +*/}} +{{- define "podSecurityPolicy.apiGroup" -}} +{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "policy" -}} +{{- else -}} +{{- print "extensions" -}} +{{- end -}} +{{- end -}} + +{{/* +Extra modules. +*/}} +{{- define "extraModules" -}} +- name: {{ .name }} + {{- with .image }} + image: {{ if .repository }}{{ .repository }}{{ else }}{{ .registry }}/{{ .image }}{{ end }}:{{ .tag }}{{ if .digest }}@{{ .digest }}{{ end }} + command: + {{- if .distroless }} + - /init_module + {{- else }} + - sh + - -c + - /usr/local/bin/init_module.sh + {{- end }} + {{- end }} + {{- if .containerSecurityContext }} + securityContext: {{ toYaml .containerSecurityContext | nindent 4 }} + {{- end }} + {{- if .resources }} + resources: {{ toYaml .resources | nindent 4 }} + {{- end }} + volumeMounts: + - name: modules + mountPath: /modules_mount +{{- end -}} diff --git a/backing-services/ingress-nginx/templates/_params.tpl b/backing-services/ingress-nginx/templates/_params.tpl new file mode 100644 index 0000000..48569a8 --- /dev/null +++ b/backing-services/ingress-nginx/templates/_params.tpl @@ -0,0 +1,77 @@ +{{- define "ingress-nginx.params" -}} +- /nginx-ingress-controller +{{- if .Values.controller.enableAnnotationValidations }} +- --enable-annotation-validation=true +{{- end }} +{{- if .Values.defaultBackend.enabled }} +- --default-backend-service=$(POD_NAMESPACE)/{{ include "ingress-nginx.defaultBackend.fullname" . }} +{{- end }} +{{- if and .Values.controller.publishService.enabled .Values.controller.service.enabled }} +{{- if .Values.controller.service.external.enabled }} +- --publish-service={{ template "ingress-nginx.controller.publishServicePath" . }} +{{- else if .Values.controller.service.internal.enabled }} +- --publish-service={{ template "ingress-nginx.controller.publishServicePath" . }}-internal +{{- end }} +{{- end }} +- --election-id={{ include "ingress-nginx.controller.electionID" . }} +- --controller-class={{ .Values.controller.ingressClassResource.controllerValue }} +{{- if .Values.controller.ingressClass }} +- --ingress-class={{ .Values.controller.ingressClass }} +{{- end }} +- --configmap={{ default "$(POD_NAMESPACE)" .Values.controller.configMapNamespace }}/{{ include "ingress-nginx.controller.fullname" . }} +{{- if .Values.tcp }} +- --tcp-services-configmap={{ default "$(POD_NAMESPACE)" .Values.controller.tcp.configMapNamespace }}/{{ include "ingress-nginx.fullname" . }}-tcp +{{- end }} +{{- if .Values.udp }} +- --udp-services-configmap={{ default "$(POD_NAMESPACE)" .Values.controller.udp.configMapNamespace }}/{{ include "ingress-nginx.fullname" . }}-udp +{{- end }} +{{- if .Values.controller.scope.enabled }} +- --watch-namespace={{ default "$(POD_NAMESPACE)" .Values.controller.scope.namespace }} +{{- end }} +{{- if and (not .Values.controller.scope.enabled) .Values.controller.scope.namespaceSelector }} +- --watch-namespace-selector={{ .Values.controller.scope.namespaceSelector }} +{{- end }} +{{- if and .Values.controller.reportNodeInternalIp .Values.controller.hostNetwork }} +- --report-node-internal-ip-address={{ .Values.controller.reportNodeInternalIp }} +{{- end }} +{{- if .Values.controller.admissionWebhooks.enabled }} +- --validating-webhook=:{{ .Values.controller.admissionWebhooks.port }} +- --validating-webhook-certificate={{ .Values.controller.admissionWebhooks.certificate }} +- --validating-webhook-key={{ .Values.controller.admissionWebhooks.key }} +{{- end }} +{{- if .Values.controller.maxmindLicenseKey }} +- --maxmind-license-key={{ .Values.controller.maxmindLicenseKey }} +{{- end }} +{{- if .Values.controller.healthCheckHost }} +- --healthz-host={{ .Values.controller.healthCheckHost }} +{{- end }} +{{- if not (eq .Values.controller.healthCheckPath "/healthz") }} +- --health-check-path={{ .Values.controller.healthCheckPath }} +{{- end }} +{{- if .Values.controller.ingressClassByName }} +- --ingress-class-by-name=true +{{- end }} +{{- if .Values.controller.watchIngressWithoutClass }} +- --watch-ingress-without-class=true +{{- end }} +{{- if not .Values.controller.metrics.enabled }} +- --enable-metrics={{ .Values.controller.metrics.enabled }} +{{- end }} +{{- if .Values.controller.enableTopologyAwareRouting }} +- --enable-topology-aware-routing=true +{{- end }} +{{- if .Values.controller.disableLeaderElection }} +- --disable-leader-election=true +{{- end }} +{{- if .Values.controller.electionTTL }} +- --election-ttl={{ .Values.controller.electionTTL }} +{{- end }} +{{- range $key, $value := .Values.controller.extraArgs }} +{{- /* Accept keys without values or with false as value */}} +{{- if eq ($value | quote | len) 2 }} +- --{{ $key }} +{{- else }} +- --{{ $key }}={{ $value }} +{{- end }} +{{- end }} +{{- end -}} diff --git a/backing-services/ingress-nginx/templates/admission-webhooks/cert-manager.yaml b/backing-services/ingress-nginx/templates/admission-webhooks/cert-manager.yaml new file mode 100644 index 0000000..db2946c --- /dev/null +++ b/backing-services/ingress-nginx/templates/admission-webhooks/cert-manager.yaml @@ -0,0 +1,63 @@ +{{- if and .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.certManager.enabled -}} +{{- if not .Values.controller.admissionWebhooks.certManager.issuerRef -}} +# Create a selfsigned Issuer, in order to create a root CA certificate for +# signing webhook serving certificates +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: {{ include "ingress-nginx.fullname" . }}-self-signed-issuer + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + selfSigned: {} +--- +# Generate a CA Certificate used to sign certificates for the webhook +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ include "ingress-nginx.fullname" . }}-root-cert + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + secretName: {{ include "ingress-nginx.fullname" . }}-root-cert + duration: {{ .Values.controller.admissionWebhooks.certManager.rootCert.duration | default "43800h0m0s" | quote }} + issuerRef: + name: {{ include "ingress-nginx.fullname" . }}-self-signed-issuer + commonName: "ca.webhook.ingress-nginx" + isCA: true + subject: + organizations: + - ingress-nginx +--- +# Create an Issuer that uses the above generated CA certificate to issue certs +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: {{ include "ingress-nginx.fullname" . }}-root-issuer + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + ca: + secretName: {{ include "ingress-nginx.fullname" . }}-root-cert +{{- end }} +--- +# generate a server certificate for the apiservices to use +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + secretName: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + duration: {{ .Values.controller.admissionWebhooks.certManager.admissionCert.duration | default "8760h0m0s" | quote }} + issuerRef: + {{- if .Values.controller.admissionWebhooks.certManager.issuerRef }} + {{- toYaml .Values.controller.admissionWebhooks.certManager.issuerRef | nindent 4 }} + {{- else }} + name: {{ include "ingress-nginx.fullname" . }}-root-issuer + {{- end }} + dnsNames: + - {{ include "ingress-nginx.controller.fullname" . }}-admission + - {{ include "ingress-nginx.controller.fullname" . }}-admission.{{ include "ingress-nginx.namespace" . }} + - {{ include "ingress-nginx.controller.fullname" . }}-admission.{{ include "ingress-nginx.namespace" . }}.svc + subject: + organizations: + - ingress-nginx-admission +{{- end -}} diff --git a/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/clusterrole.yaml b/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/clusterrole.yaml new file mode 100644 index 0000000..a218482 --- /dev/null +++ b/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/clusterrole.yaml @@ -0,0 +1,33 @@ +{{- if and .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.patch.enabled .Values.controller.admissionWebhooks.patch.rbac.create (not .Values.controller.admissionWebhooks.certManager.enabled) -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.patch.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +rules: + - apiGroups: + - admissionregistration.k8s.io + resources: + - validatingwebhookconfigurations + verbs: + - get + - update +{{- if .Values.podSecurityPolicy.enabled }} + - apiGroups: [{{ template "podSecurityPolicy.apiGroup" . }}] + resources: ['podsecuritypolicies'] + verbs: ['use'] + {{- with .Values.controller.admissionWebhooks.existingPsp }} + resourceNames: [{{ . }}] + {{- else }} + resourceNames: [{{ include "ingress-nginx.admissionWebhooks.fullname" . }}] + {{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/clusterrolebinding.yaml b/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/clusterrolebinding.yaml new file mode 100644 index 0000000..b893884 --- /dev/null +++ b/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/clusterrolebinding.yaml @@ -0,0 +1,23 @@ +{{- if and .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.patch.enabled .Values.controller.admissionWebhooks.patch.rbac.create (not .Values.controller.admissionWebhooks.certManager.enabled) -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.patch.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ include "ingress-nginx.admissionWebhooks.patch.serviceAccountName" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/job-createSecret.yaml b/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/job-createSecret.yaml new file mode 100644 index 0000000..1766164 --- /dev/null +++ b/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/job-createSecret.yaml @@ -0,0 +1,79 @@ +{{- if and .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.patch.enabled (not .Values.controller.admissionWebhooks.certManager.enabled) -}} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "ingress-nginx.admissionWebhooks.createSecretJob.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + {{- with .Values.controller.admissionWebhooks.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.patch.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if .Capabilities.APIVersions.Has "batch/v1alpha1" }} + # Alpha feature since k8s 1.12 + ttlSecondsAfterFinished: 0 +{{- end }} + template: + metadata: + name: {{ include "ingress-nginx.admissionWebhooks.createSecretJob.fullname" . }} + {{- if .Values.controller.admissionWebhooks.patch.podAnnotations }} + annotations: {{ toYaml .Values.controller.admissionWebhooks.patch.podAnnotations | nindent 8 }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 8 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.patch.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if .Values.controller.admissionWebhooks.patch.priorityClassName }} + priorityClassName: {{ .Values.controller.admissionWebhooks.patch.priorityClassName }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 8 }} + {{- end }} + containers: + - name: create + {{- with .Values.controller.admissionWebhooks.patch.image }} + image: {{ if .repository }}{{ .repository }}{{ else }}{{ .registry }}/{{ .image }}{{ end }}:{{ .tag }}{{ if .digest }}@{{ .digest }}{{ end }} + {{- end }} + imagePullPolicy: {{ .Values.controller.admissionWebhooks.patch.image.pullPolicy }} + args: + - create + - --host={{ include "ingress-nginx.controller.fullname" . }}-admission,{{ include "ingress-nginx.controller.fullname" . }}-admission.$(POD_NAMESPACE).svc + - --namespace=$(POD_NAMESPACE) + - --secret-name={{ include "ingress-nginx.admissionWebhooks.fullname" . }} + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if .Values.controller.admissionWebhooks.extraEnvs }} + {{- toYaml .Values.controller.admissionWebhooks.extraEnvs | nindent 12 }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.createSecretJob.securityContext }} + securityContext: {{ toYaml .Values.controller.admissionWebhooks.createSecretJob.securityContext | nindent 12 }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.createSecretJob.resources }} + resources: {{ toYaml .Values.controller.admissionWebhooks.createSecretJob.resources | nindent 12 }} + {{- end }} + restartPolicy: OnFailure + serviceAccountName: {{ include "ingress-nginx.admissionWebhooks.patch.serviceAccountName" . }} + {{- if .Values.controller.admissionWebhooks.patch.nodeSelector }} + nodeSelector: {{ toYaml .Values.controller.admissionWebhooks.patch.nodeSelector | nindent 8 }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.patch.tolerations }} + tolerations: {{ toYaml .Values.controller.admissionWebhooks.patch.tolerations | nindent 8 }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.patch.securityContext }} + securityContext: {{ toYaml .Values.controller.admissionWebhooks.patch.securityContext | nindent 8 }} + {{- end }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/job-patchWebhook.yaml b/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/job-patchWebhook.yaml new file mode 100644 index 0000000..f7d44a2 --- /dev/null +++ b/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/job-patchWebhook.yaml @@ -0,0 +1,81 @@ +{{- if and .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.patch.enabled (not .Values.controller.admissionWebhooks.certManager.enabled) -}} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "ingress-nginx.admissionWebhooks.patchWebhookJob.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} + annotations: + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + {{- with .Values.controller.admissionWebhooks.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.patch.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if .Capabilities.APIVersions.Has "batch/v1alpha1" }} + # Alpha feature since k8s 1.12 + ttlSecondsAfterFinished: 0 +{{- end }} + template: + metadata: + name: {{ include "ingress-nginx.admissionWebhooks.patchWebhookJob.fullname" . }} + {{- if .Values.controller.admissionWebhooks.patch.podAnnotations }} + annotations: {{ toYaml .Values.controller.admissionWebhooks.patch.podAnnotations | nindent 8 }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 8 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.patch.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if .Values.controller.admissionWebhooks.patch.priorityClassName }} + priorityClassName: {{ .Values.controller.admissionWebhooks.patch.priorityClassName }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 8 }} + {{- end }} + containers: + - name: patch + {{- with .Values.controller.admissionWebhooks.patch.image }} + image: {{ if .repository }}{{ .repository }}{{ else }}{{ .registry }}/{{ .image }}{{ end }}:{{ .tag }}{{ if .digest }}@{{ .digest }}{{ end }} + {{- end }} + imagePullPolicy: {{ .Values.controller.admissionWebhooks.patch.image.pullPolicy }} + args: + - patch + - --webhook-name={{ include "ingress-nginx.admissionWebhooks.fullname" . }} + - --namespace=$(POD_NAMESPACE) + - --patch-mutating=false + - --secret-name={{ include "ingress-nginx.admissionWebhooks.fullname" . }} + - --patch-failure-policy={{ .Values.controller.admissionWebhooks.failurePolicy }} + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if .Values.controller.admissionWebhooks.extraEnvs }} + {{- toYaml .Values.controller.admissionWebhooks.extraEnvs | nindent 12 }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.patchWebhookJob.securityContext }} + securityContext: {{ toYaml .Values.controller.admissionWebhooks.patchWebhookJob.securityContext | nindent 12 }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.patchWebhookJob.resources }} + resources: {{ toYaml .Values.controller.admissionWebhooks.patchWebhookJob.resources | nindent 12 }} + {{- end }} + restartPolicy: OnFailure + serviceAccountName: {{ include "ingress-nginx.admissionWebhooks.patch.serviceAccountName" . }} + {{- if .Values.controller.admissionWebhooks.patch.nodeSelector }} + nodeSelector: {{ toYaml .Values.controller.admissionWebhooks.patch.nodeSelector | nindent 8 }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.patch.tolerations }} + tolerations: {{ toYaml .Values.controller.admissionWebhooks.patch.tolerations | nindent 8 }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.patch.securityContext }} + securityContext: {{ toYaml .Values.controller.admissionWebhooks.patch.securityContext | nindent 8 }} + {{- end }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/networkpolicy.yaml b/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/networkpolicy.yaml new file mode 100644 index 0000000..a8f38df --- /dev/null +++ b/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/networkpolicy.yaml @@ -0,0 +1,26 @@ +{{- if and .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.patch.enabled .Values.controller.admissionWebhooks.patch.networkPolicy.enabled (not .Values.controller.admissionWebhooks.certManager.enabled) -}} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.patch.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + {{- include "ingress-nginx.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: admission-webhook + policyTypes: + - Ingress + - Egress + egress: + - {} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/psp.yaml b/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/psp.yaml new file mode 100644 index 0000000..8e5dc72 --- /dev/null +++ b/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/psp.yaml @@ -0,0 +1,52 @@ +{{- if (semverCompare "<1.25.0-0" .Capabilities.KubeVersion.Version) }} +{{- if and .Values.podSecurityPolicy.enabled .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.patch.enabled (empty .Values.controller.admissionWebhooks.existingPsp) -}} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + seccomp.security.alpha.kubernetes.io/allowedProfileNames: "*" + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.patch.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + privileged: false + hostPID: false + hostIPC: false + hostNetwork: false + volumes: + - configMap + - downwardAPI + - emptyDir + - secret + - projected + fsGroup: + rule: MustRunAs + ranges: + - min: 1 + max: 65535 + readOnlyRootFilesystem: true + runAsUser: + rule: MustRunAsNonRoot + runAsGroup: + rule: MustRunAs + ranges: + - min: 1 + max: 65535 + supplementalGroups: + rule: MustRunAs + ranges: + - min: 1 + max: 65535 + allowPrivilegeEscalation: false + requiredDropCapabilities: + - ALL + seLinux: + rule: RunAsAny +{{- end }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/role.yaml b/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/role.yaml new file mode 100644 index 0000000..c4b23aa --- /dev/null +++ b/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/role.yaml @@ -0,0 +1,24 @@ +{{- if and .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.patch.enabled .Values.controller.admissionWebhooks.patch.rbac.create (not .Values.controller.admissionWebhooks.certManager.enabled) -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.patch.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +rules: + - apiGroups: + - "" + resources: + - secrets + verbs: + - get + - create +{{- end }} diff --git a/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/rolebinding.yaml b/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/rolebinding.yaml new file mode 100644 index 0000000..425e8d8 --- /dev/null +++ b/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/rolebinding.yaml @@ -0,0 +1,24 @@ +{{- if and .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.patch.enabled .Values.controller.admissionWebhooks.patch.rbac.create (not .Values.controller.admissionWebhooks.certManager.enabled) -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.patch.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ include "ingress-nginx.admissionWebhooks.patch.serviceAccountName" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/serviceaccount.yaml b/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/serviceaccount.yaml new file mode 100644 index 0000000..52f94dc --- /dev/null +++ b/backing-services/ingress-nginx/templates/admission-webhooks/job-patch/serviceaccount.yaml @@ -0,0 +1,17 @@ +{{- if and .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.patch.enabled .Values.controller.admissionWebhooks.patch.serviceAccount.create (not .Values.controller.admissionWebhooks.certManager.enabled) -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "ingress-nginx.admissionWebhooks.patch.serviceAccountName" . }} + namespace: {{ include "ingress-nginx.namespace" . }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.patch.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.controller.admissionWebhooks.patch.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/admission-webhooks/validating-webhook.yaml b/backing-services/ingress-nginx/templates/admission-webhooks/validating-webhook.yaml new file mode 100644 index 0000000..0949cea --- /dev/null +++ b/backing-services/ingress-nginx/templates/admission-webhooks/validating-webhook.yaml @@ -0,0 +1,54 @@ +{{- if .Values.controller.admissionWebhooks.enabled -}} +# before changing this value, check the required kubernetes version +# https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#prerequisites +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + annotations: + {{- if .Values.controller.admissionWebhooks.certManager.enabled }} + certmanager.k8s.io/inject-ca-from: {{ printf "%s/%s" (include "ingress-nginx.namespace" .) (include "ingress-nginx.admissionWebhooks.fullname" .) | quote }} + cert-manager.io/inject-ca-from: {{ printf "%s/%s" (include "ingress-nginx.namespace" .) (include "ingress-nginx.admissionWebhooks.fullname" .) | quote }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.annotations }} + {{- toYaml .Values.controller.admissionWebhooks.annotations | nindent 4 }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} +webhooks: + - name: validate.nginx.ingress.kubernetes.io + matchPolicy: Equivalent + rules: + - apiGroups: + - networking.k8s.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - ingresses + failurePolicy: {{ .Values.controller.admissionWebhooks.failurePolicy | default "Fail" }} + sideEffects: None + admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "ingress-nginx.controller.fullname" . }}-admission + namespace: {{ include "ingress-nginx.namespace" . }} + port: {{ .Values.controller.admissionWebhooks.service.servicePort }} + path: /networking/v1/ingresses + {{- if .Values.controller.admissionWebhooks.timeoutSeconds }} + timeoutSeconds: {{ .Values.controller.admissionWebhooks.timeoutSeconds }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.namespaceSelector }} + namespaceSelector: {{ toYaml .Values.controller.admissionWebhooks.namespaceSelector | nindent 6 }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.objectSelector }} + objectSelector: {{ toYaml .Values.controller.admissionWebhooks.objectSelector | nindent 6 }} + {{- end }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/clusterrole.yaml b/backing-services/ingress-nginx/templates/clusterrole.yaml new file mode 100644 index 0000000..51bc500 --- /dev/null +++ b/backing-services/ingress-nginx/templates/clusterrole.yaml @@ -0,0 +1,102 @@ +{{- if .Values.rbac.create }} + +{{- if and .Values.rbac.scope (not .Values.controller.scope.enabled) -}} + {{ required "Invalid configuration: 'rbac.scope' should be equal to 'controller.scope.enabled' (true/false)." (index (dict) ".") }} +{{- end }} + +{{- if not .Values.rbac.scope -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.fullname" . }} +rules: + - apiGroups: + - "" + resources: + - configmaps + - endpoints + - nodes + - pods + - secrets +{{- if not .Values.controller.scope.enabled }} + - namespaces +{{- end}} + verbs: + - list + - watch + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - list + - watch +{{- if and .Values.controller.scope.enabled .Values.controller.scope.namespace }} + - apiGroups: + - "" + resources: + - namespaces + resourceNames: + - "{{ .Values.controller.scope.namespace }}" + verbs: + - get +{{- end }} + - apiGroups: + - "" + resources: + - nodes + verbs: + - get + - apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch + - apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - apiGroups: + - networking.k8s.io + resources: + - ingresses/status + verbs: + - update + - apiGroups: + - networking.k8s.io + resources: + - ingressclasses + verbs: + - get + - list + - watch + - apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - list + - watch + - get +{{- end }} + +{{- end }} diff --git a/backing-services/ingress-nginx/templates/clusterrolebinding.yaml b/backing-services/ingress-nginx/templates/clusterrolebinding.yaml new file mode 100644 index 0000000..8f91aac --- /dev/null +++ b/backing-services/ingress-nginx/templates/clusterrolebinding.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.rbac.create (not .Values.rbac.scope) -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.fullname" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "ingress-nginx.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "ingress-nginx.serviceAccountName" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-configmap-addheaders.yaml b/backing-services/ingress-nginx/templates/controller-configmap-addheaders.yaml new file mode 100644 index 0000000..4e4bd13 --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-configmap-addheaders.yaml @@ -0,0 +1,14 @@ +{{- if .Values.controller.addHeaders -}} +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.fullname" . }}-custom-add-headers + namespace: {{ include "ingress-nginx.namespace" . }} +data: {{ toYaml .Values.controller.addHeaders | nindent 2 }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-configmap-proxyheaders.yaml b/backing-services/ingress-nginx/templates/controller-configmap-proxyheaders.yaml new file mode 100644 index 0000000..0a22600 --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-configmap-proxyheaders.yaml @@ -0,0 +1,14 @@ +{{- if .Values.controller.proxySetHeaders -}} +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.fullname" . }}-custom-proxy-headers + namespace: {{ include "ingress-nginx.namespace" . }} +data: {{ toYaml .Values.controller.proxySetHeaders | nindent 2 }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-configmap-tcp.yaml b/backing-services/ingress-nginx/templates/controller-configmap-tcp.yaml new file mode 100644 index 0000000..131a9ad --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-configmap-tcp.yaml @@ -0,0 +1,17 @@ +{{- if .Values.tcp -}} +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- if .Values.controller.tcp.annotations }} + annotations: {{ toYaml .Values.controller.tcp.annotations | nindent 4 }} +{{- end }} + name: {{ include "ingress-nginx.fullname" . }}-tcp + namespace: {{ include "ingress-nginx.namespace" . }} +data: {{ tpl (toYaml .Values.tcp) . | nindent 2 }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-configmap-udp.yaml b/backing-services/ingress-nginx/templates/controller-configmap-udp.yaml new file mode 100644 index 0000000..7137da9 --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-configmap-udp.yaml @@ -0,0 +1,17 @@ +{{- if .Values.udp -}} +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- if .Values.controller.udp.annotations }} + annotations: {{ toYaml .Values.controller.udp.annotations | nindent 4 }} +{{- end }} + name: {{ include "ingress-nginx.fullname" . }}-udp + namespace: {{ include "ingress-nginx.namespace" . }} +data: {{ tpl (toYaml .Values.udp) . | nindent 2 }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-configmap.yaml b/backing-services/ingress-nginx/templates/controller-configmap.yaml new file mode 100644 index 0000000..22080d1 --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-configmap.yaml @@ -0,0 +1,28 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- if .Values.controller.configAnnotations }} + annotations: {{ toYaml .Values.controller.configAnnotations | nindent 4 }} +{{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +data: + allow-snippet-annotations: "{{ .Values.controller.allowSnippetAnnotations }}" +{{- if .Values.controller.addHeaders }} + add-headers: {{ include "ingress-nginx.namespace" . }}/{{ include "ingress-nginx.fullname" . }}-custom-add-headers +{{- end }} +{{- if .Values.controller.proxySetHeaders }} + proxy-set-headers: {{ include "ingress-nginx.namespace" . }}/{{ include "ingress-nginx.fullname" . }}-custom-proxy-headers +{{- end }} +{{- if .Values.dhParam }} + ssl-dh-param: {{ include "ingress-nginx.namespace" . }}/{{ include "ingress-nginx.controller.fullname" . }} +{{- end }} +{{- range $key, $value := .Values.controller.config }} + {{- $key | nindent 2 }}: {{ tpl (toString $value) $ | quote }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-daemonset.yaml b/backing-services/ingress-nginx/templates/controller-daemonset.yaml new file mode 100644 index 0000000..fcc633d --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-daemonset.yaml @@ -0,0 +1,242 @@ +{{- if eq .Values.controller.kind "DaemonSet" -}} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} + {{- if .Values.controller.annotations }} + annotations: {{ toYaml .Values.controller.annotations | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "ingress-nginx.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: controller + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + {{- if .Values.controller.updateStrategy }} + updateStrategy: {{ toYaml .Values.controller.updateStrategy | nindent 4 }} + {{- end }} + minReadySeconds: {{ .Values.controller.minReadySeconds }} + template: + metadata: + {{- if .Values.controller.podAnnotations }} + annotations: + {{- range $key, $value := .Values.controller.podAnnotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 8 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.controller.podLabels }} + {{- toYaml .Values.controller.podLabels | nindent 8 }} + {{- end }} + spec: + {{- if .Values.controller.dnsConfig }} + dnsConfig: {{ toYaml .Values.controller.dnsConfig | nindent 8 }} + {{- end }} + {{- if .Values.controller.hostAliases }} + hostAliases: {{ tpl (toYaml .Values.controller.hostAliases) $ | nindent 8 }} + {{- end }} + {{- if .Values.controller.hostname }} + hostname: {{ toYaml .Values.controller.hostname | nindent 8 }} + {{- end }} + dnsPolicy: {{ .Values.controller.dnsPolicy }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 8 }} + {{- end }} + {{- if .Values.controller.priorityClassName }} + priorityClassName: {{ .Values.controller.priorityClassName | quote }} + {{- end }} + {{- if or .Values.controller.podSecurityContext .Values.controller.sysctls }} + securityContext: + {{- if .Values.controller.podSecurityContext }} + {{- toYaml .Values.controller.podSecurityContext | nindent 8 }} + {{- end }} + {{- if .Values.controller.sysctls }} + sysctls: + {{- range $sysctl, $value := .Values.controller.sysctls }} + - name: {{ $sysctl | quote }} + value: {{ $value | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.controller.shareProcessNamespace }} + shareProcessNamespace: {{ .Values.controller.shareProcessNamespace }} + {{- end }} + containers: + - name: {{ .Values.controller.containerName }} + {{- with .Values.controller.image }} + image: {{ if .repository }}{{ .repository }}{{ else }}{{ .registry }}/{{ include "ingress-nginx.image" . }}{{ end }}:{{ .tag }}{{ include "ingress-nginx.imageDigest" . }} + {{- end }} + imagePullPolicy: {{ .Values.controller.image.pullPolicy }} + {{- if .Values.controller.lifecycle }} + lifecycle: {{ toYaml .Values.controller.lifecycle | nindent 12 }} + {{- end }} + args: {{ include "ingress-nginx.params" . | nindent 12 }} + securityContext: {{ include "ingress-nginx.controller.containerSecurityContext" . | nindent 12 }} + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if .Values.controller.enableMimalloc }} + - name: LD_PRELOAD + value: /usr/local/lib/libmimalloc.so + {{- end }} + {{- if .Values.controller.extraEnvs }} + {{- toYaml .Values.controller.extraEnvs | nindent 12 }} + {{- end }} + {{- if .Values.controller.startupProbe }} + startupProbe: {{ toYaml .Values.controller.startupProbe | nindent 12 }} + {{- end }} + {{- if .Values.controller.livenessProbe }} + livenessProbe: {{ toYaml .Values.controller.livenessProbe | nindent 12 }} + {{- end }} + {{- if .Values.controller.readinessProbe }} + readinessProbe: {{ toYaml .Values.controller.readinessProbe | nindent 12 }} + {{- end }} + ports: + {{- range $key, $value := .Values.controller.containerPort }} + - name: {{ $key }} + containerPort: {{ $value }} + protocol: TCP + {{- if $.Values.controller.hostPort.enabled }} + hostPort: {{ index $.Values.controller.hostPort.ports $key | default $value }} + {{- end }} + {{- end }} + {{- if .Values.controller.metrics.enabled }} + - name: {{ .Values.controller.metrics.portName }} + containerPort: {{ .Values.controller.metrics.port }} + protocol: TCP + {{- end }} + {{- if .Values.controller.admissionWebhooks.enabled }} + - name: webhook + containerPort: {{ .Values.controller.admissionWebhooks.port }} + protocol: TCP + {{- end }} + {{- range $key, $value := .Values.tcp }} + - name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-tcp + containerPort: {{ $key }} + protocol: TCP + {{- if $.Values.controller.hostPort.enabled }} + hostPort: {{ $key }} + {{- end }} + {{- end }} + {{- range $key, $value := .Values.udp }} + - name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-udp + containerPort: {{ $key }} + protocol: UDP + {{- if $.Values.controller.hostPort.enabled }} + hostPort: {{ $key }} + {{- end }} + {{- end }} + {{- if (or .Values.controller.customTemplate.configMapName .Values.controller.extraVolumeMounts .Values.controller.admissionWebhooks.enabled .Values.controller.extraModules .Values.controller.opentelemetry.enabled) }} + volumeMounts: + {{- if (or .Values.controller.extraModules .Values.controller.opentelemetry.enabled) }} + - name: modules + {{- if .Values.controller.image.chroot }} + mountPath: /chroot/modules_mount + {{- else }} + mountPath: /modules_mount + {{- end }} + {{- end }} + {{- if .Values.controller.customTemplate.configMapName }} + - mountPath: /etc/nginx/template + name: nginx-template-volume + readOnly: true + {{- end }} + {{- if .Values.controller.admissionWebhooks.enabled }} + - name: webhook-cert + mountPath: /usr/local/certificates/ + readOnly: true + {{- end }} + {{- if .Values.controller.extraVolumeMounts }} + {{- toYaml .Values.controller.extraVolumeMounts | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.controller.resources }} + resources: {{ toYaml .Values.controller.resources | nindent 12 }} + {{- end }} + {{- if .Values.controller.extraContainers }} + {{- toYaml .Values.controller.extraContainers | nindent 8 }} + {{- end }} + {{- if (or .Values.controller.extraInitContainers .Values.controller.extraModules .Values.controller.opentelemetry.enabled) }} + initContainers: + {{- if .Values.controller.extraInitContainers }} + {{- toYaml .Values.controller.extraInitContainers | nindent 8 }} + {{- end }} + {{- if .Values.controller.extraModules }} + {{- range .Values.controller.extraModules }} + {{- $containerSecurityContext := .containerSecurityContext | default $.Values.controller.containerSecurityContext }} + {{- include "extraModules" (dict "name" .name "image" .image "containerSecurityContext" $containerSecurityContext "resources" .resources) | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.controller.opentelemetry.enabled }} + {{- with .Values.controller.opentelemetry }} + {{- $containerSecurityContext := .containerSecurityContext | default $.Values.controller.containerSecurityContext }} + {{- include "extraModules" (dict "name" .name "image" .image "containerSecurityContext" $containerSecurityContext "resources" .resources) | nindent 8 }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.controller.hostNetwork }} + hostNetwork: {{ .Values.controller.hostNetwork }} + {{- end }} + {{- if .Values.controller.nodeSelector }} + nodeSelector: {{ toYaml .Values.controller.nodeSelector | nindent 8 }} + {{- end }} + {{- if .Values.controller.tolerations }} + tolerations: {{ toYaml .Values.controller.tolerations | nindent 8 }} + {{- end }} + {{- if .Values.controller.affinity }} + affinity: {{ tpl (toYaml .Values.controller.affinity) $ | nindent 8 }} + {{- end }} + {{- if .Values.controller.topologySpreadConstraints }} + topologySpreadConstraints: {{ tpl (toYaml .Values.controller.topologySpreadConstraints) $ | nindent 8 }} + {{- end }} + serviceAccountName: {{ template "ingress-nginx.serviceAccountName" . }} + terminationGracePeriodSeconds: {{ .Values.controller.terminationGracePeriodSeconds }} + {{- if (or .Values.controller.customTemplate.configMapName .Values.controller.extraVolumeMounts .Values.controller.admissionWebhooks.enabled .Values.controller.extraVolumes .Values.controller.extraModules .Values.controller.opentelemetry.enabled) }} + volumes: + {{- if (or .Values.controller.extraModules .Values.controller.opentelemetry.enabled)}} + - name: modules + emptyDir: {} + {{- end }} + {{- if .Values.controller.customTemplate.configMapName }} + - name: nginx-template-volume + configMap: + name: {{ .Values.controller.customTemplate.configMapName }} + items: + - key: {{ .Values.controller.customTemplate.configMapKey }} + path: nginx.tmpl + {{- end }} + {{- if .Values.controller.admissionWebhooks.enabled }} + - name: webhook-cert + secret: + secretName: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + {{- if .Values.controller.admissionWebhooks.certManager.enabled }} + items: + - key: tls.crt + path: cert + - key: tls.key + path: key + {{- end }} + {{- end }} + {{- if .Values.controller.extraVolumes }} + {{ toYaml .Values.controller.extraVolumes | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-deployment.yaml b/backing-services/ingress-nginx/templates/controller-deployment.yaml new file mode 100644 index 0000000..5211acd --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-deployment.yaml @@ -0,0 +1,245 @@ +{{- if eq .Values.controller.kind "Deployment" -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} + {{- if .Values.controller.annotations }} + annotations: {{ toYaml .Values.controller.annotations | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "ingress-nginx.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: controller + {{- if eq .Values.controller.autoscaling.enabled .Values.controller.keda.enabled }} + replicas: {{ .Values.controller.replicaCount }} + {{- end }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + {{- if .Values.controller.updateStrategy }} + strategy: {{ toYaml .Values.controller.updateStrategy | nindent 4 }} + {{- end }} + minReadySeconds: {{ .Values.controller.minReadySeconds }} + template: + metadata: + {{- if .Values.controller.podAnnotations }} + annotations: + {{- range $key, $value := .Values.controller.podAnnotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 8 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.controller.podLabels }} + {{- toYaml .Values.controller.podLabels | nindent 8 }} + {{- end }} + spec: + {{- if .Values.controller.dnsConfig }} + dnsConfig: {{ toYaml .Values.controller.dnsConfig | nindent 8 }} + {{- end }} + {{- if .Values.controller.hostAliases }} + hostAliases: {{ tpl (toYaml .Values.controller.hostAliases) $ | nindent 8 }} + {{- end }} + {{- if .Values.controller.hostname }} + hostname: {{ toYaml .Values.controller.hostname | nindent 8 }} + {{- end }} + dnsPolicy: {{ .Values.controller.dnsPolicy }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 8 }} + {{- end }} + {{- if .Values.controller.priorityClassName }} + priorityClassName: {{ .Values.controller.priorityClassName | quote }} + {{- end }} + {{- if or .Values.controller.podSecurityContext .Values.controller.sysctls }} + securityContext: + {{- if .Values.controller.podSecurityContext }} + {{- toYaml .Values.controller.podSecurityContext | nindent 8 }} + {{- end }} + {{- if .Values.controller.sysctls }} + sysctls: + {{- range $sysctl, $value := .Values.controller.sysctls }} + - name: {{ $sysctl | quote }} + value: {{ $value | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.controller.shareProcessNamespace }} + shareProcessNamespace: {{ .Values.controller.shareProcessNamespace }} + {{- end }} + containers: + - name: {{ .Values.controller.containerName }} + {{- with .Values.controller.image }} + image: {{ if .repository }}{{ .repository }}{{ else }}{{ .registry }}/{{ include "ingress-nginx.image" . }}{{ end }}:{{ .tag }}{{ include "ingress-nginx.imageDigest" . }} + {{- end }} + imagePullPolicy: {{ .Values.controller.image.pullPolicy }} + {{- if .Values.controller.lifecycle }} + lifecycle: {{ toYaml .Values.controller.lifecycle | nindent 12 }} + {{- end }} + args: {{ include "ingress-nginx.params" . | nindent 12 }} + securityContext: {{ include "ingress-nginx.controller.containerSecurityContext" . | nindent 12 }} + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if .Values.controller.enableMimalloc }} + - name: LD_PRELOAD + value: /usr/local/lib/libmimalloc.so + {{- end }} + {{- if .Values.controller.extraEnvs }} + {{- toYaml .Values.controller.extraEnvs | nindent 12 }} + {{- end }} + {{- if .Values.controller.startupProbe }} + startupProbe: {{ toYaml .Values.controller.startupProbe | nindent 12 }} + {{- end }} + {{- if .Values.controller.livenessProbe }} + livenessProbe: {{ toYaml .Values.controller.livenessProbe | nindent 12 }} + {{- end }} + {{- if .Values.controller.readinessProbe }} + readinessProbe: {{ toYaml .Values.controller.readinessProbe | nindent 12 }} + {{- end }} + ports: + {{- range $key, $value := .Values.controller.containerPort }} + - name: {{ $key }} + containerPort: {{ $value }} + protocol: TCP + {{- if $.Values.controller.hostPort.enabled }} + hostPort: {{ index $.Values.controller.hostPort.ports $key | default $value }} + {{- end }} + {{- end }} + {{- if .Values.controller.metrics.enabled }} + - name: {{ .Values.controller.metrics.portName }} + containerPort: {{ .Values.controller.metrics.port }} + protocol: TCP + {{- end }} + {{- if .Values.controller.admissionWebhooks.enabled }} + - name: webhook + containerPort: {{ .Values.controller.admissionWebhooks.port }} + protocol: TCP + {{- end }} + {{- range $key, $value := .Values.tcp }} + - name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-tcp + containerPort: {{ $key }} + protocol: TCP + {{- if $.Values.controller.hostPort.enabled }} + hostPort: {{ $key }} + {{- end }} + {{- end }} + {{- range $key, $value := .Values.udp }} + - name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-udp + containerPort: {{ $key }} + protocol: UDP + {{- if $.Values.controller.hostPort.enabled }} + hostPort: {{ $key }} + {{- end }} + {{- end }} + {{- if (or .Values.controller.customTemplate.configMapName .Values.controller.extraVolumeMounts .Values.controller.admissionWebhooks.enabled .Values.controller.extraModules .Values.controller.opentelemetry.enabled) }} + volumeMounts: + {{- if (or .Values.controller.extraModules .Values.controller.opentelemetry.enabled) }} + - name: modules + {{- if .Values.controller.image.chroot }} + mountPath: /chroot/modules_mount + {{- else }} + mountPath: /modules_mount + {{- end }} + {{- end }} + {{- if .Values.controller.customTemplate.configMapName }} + - mountPath: /etc/nginx/template + name: nginx-template-volume + readOnly: true + {{- end }} + {{- if .Values.controller.admissionWebhooks.enabled }} + - name: webhook-cert + mountPath: /usr/local/certificates/ + readOnly: true + {{- end }} + {{- if .Values.controller.extraVolumeMounts }} + {{- toYaml .Values.controller.extraVolumeMounts | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.controller.resources }} + resources: {{ toYaml .Values.controller.resources | nindent 12 }} + {{- end }} + {{- if .Values.controller.extraContainers }} + {{- toYaml .Values.controller.extraContainers | nindent 8 }} + {{- end }} + {{- if (or .Values.controller.extraInitContainers .Values.controller.extraModules .Values.controller.opentelemetry.enabled) }} + initContainers: + {{- if .Values.controller.extraInitContainers }} + {{- toYaml .Values.controller.extraInitContainers | nindent 8 }} + {{- end }} + {{- if .Values.controller.extraModules }} + {{- range .Values.controller.extraModules }} + {{- $containerSecurityContext := .containerSecurityContext | default $.Values.controller.containerSecurityContext }} + {{- include "extraModules" (dict "name" .name "image" .image "containerSecurityContext" $containerSecurityContext "resources" .resources) | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.controller.opentelemetry.enabled }} + {{- with .Values.controller.opentelemetry }} + {{- $containerSecurityContext := .containerSecurityContext | default $.Values.controller.containerSecurityContext }} + {{- include "extraModules" (dict "name" .name "image" .image "containerSecurityContext" $containerSecurityContext "resources" .resources) | nindent 8 }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.controller.hostNetwork }} + hostNetwork: {{ .Values.controller.hostNetwork }} + {{- end }} + {{- if .Values.controller.nodeSelector }} + nodeSelector: {{ toYaml .Values.controller.nodeSelector | nindent 8 }} + {{- end }} + {{- if .Values.controller.tolerations }} + tolerations: {{ toYaml .Values.controller.tolerations | nindent 8 }} + {{- end }} + {{- if .Values.controller.affinity }} + affinity: {{ tpl (toYaml .Values.controller.affinity) $ | nindent 8 }} + {{- end }} + {{- if .Values.controller.topologySpreadConstraints }} + topologySpreadConstraints: {{ tpl (toYaml .Values.controller.topologySpreadConstraints) $ | nindent 8 }} + {{- end }} + serviceAccountName: {{ template "ingress-nginx.serviceAccountName" . }} + terminationGracePeriodSeconds: {{ .Values.controller.terminationGracePeriodSeconds }} + {{- if (or .Values.controller.customTemplate.configMapName .Values.controller.extraVolumeMounts .Values.controller.admissionWebhooks.enabled .Values.controller.extraVolumes .Values.controller.extraModules .Values.controller.opentelemetry.enabled) }} + volumes: + {{- if (or .Values.controller.extraModules .Values.controller.opentelemetry.enabled)}} + - name: modules + emptyDir: {} + {{- end }} + {{- if .Values.controller.customTemplate.configMapName }} + - name: nginx-template-volume + configMap: + name: {{ .Values.controller.customTemplate.configMapName }} + items: + - key: {{ .Values.controller.customTemplate.configMapKey }} + path: nginx.tmpl + {{- end }} + {{- if .Values.controller.admissionWebhooks.enabled }} + - name: webhook-cert + secret: + secretName: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + {{- if .Values.controller.admissionWebhooks.certManager.enabled }} + items: + - key: tls.crt + path: cert + - key: tls.key + path: key + {{- end }} + {{- end }} + {{- if .Values.controller.extraVolumes }} + {{ toYaml .Values.controller.extraVolumes | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-hpa.yaml b/backing-services/ingress-nginx/templates/controller-hpa.yaml new file mode 100644 index 0000000..ec9ad73 --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-hpa.yaml @@ -0,0 +1,47 @@ +{{- if and (eq .Values.controller.kind "Deployment") .Values.controller.autoscaling.enabled (not .Values.controller.keda.enabled) -}} +apiVersion: {{ ternary "autoscaling/v2" "autoscaling/v2beta2" (.Capabilities.APIVersions.Has "autoscaling/v2") }} +kind: HorizontalPodAutoscaler +metadata: + {{- with .Values.controller.autoscaling.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "ingress-nginx.controller.fullname" . }} + minReplicas: {{ .Values.controller.autoscaling.minReplicas }} + maxReplicas: {{ .Values.controller.autoscaling.maxReplicas }} + metrics: + {{- with .Values.controller.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ . }} + {{- end }} + {{- with .Values.controller.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ . }} + {{- end }} + {{- with .Values.controller.autoscalingTemplate }} + {{- toYaml . | nindent 2 }} + {{- end }} + {{- with .Values.controller.autoscaling.behavior }} + behavior: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-ingressclass-aliases.yaml b/backing-services/ingress-nginx/templates/controller-ingressclass-aliases.yaml new file mode 100644 index 0000000..ffe2231 --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-ingressclass-aliases.yaml @@ -0,0 +1,23 @@ +{{- if .Values.controller.ingressClassResource.enabled -}} +{{- range .Values.controller.ingressClassResource.aliases }} +--- +apiVersion: networking.k8s.io/v1 +kind: IngressClass +metadata: + labels: + {{- include "ingress-nginx.labels" $ | nindent 4 }} + app.kubernetes.io/component: controller + {{- with $.Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ . }} + {{- if $.Values.controller.ingressClassResource.annotations }} + annotations: {{ toYaml $.Values.controller.ingressClassResource.annotations | nindent 4 }} + {{- end }} +spec: + controller: {{ $.Values.controller.ingressClassResource.controllerValue }} + {{- with $.Values.controller.ingressClassResource.parameters }} + parameters: {{ toYaml . | nindent 4 }} + {{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-ingressclass.yaml b/backing-services/ingress-nginx/templates/controller-ingressclass.yaml new file mode 100644 index 0000000..98479a5 --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-ingressclass.yaml @@ -0,0 +1,26 @@ +{{- if .Values.controller.ingressClassResource.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: IngressClass +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ .Values.controller.ingressClassResource.name }} + {{- if or .Values.controller.ingressClassResource.default .Values.controller.ingressClassResource.annotations }} + annotations: + {{- if .Values.controller.ingressClassResource.default }} + ingressclass.kubernetes.io/is-default-class: "true" + {{- end }} + {{- if .Values.controller.ingressClassResource.annotations }} + {{- toYaml .Values.controller.ingressClassResource.annotations | nindent 4 }} + {{- end }} + {{- end }} +spec: + controller: {{ .Values.controller.ingressClassResource.controllerValue }} + {{- with .Values.controller.ingressClassResource.parameters }} + parameters: {{ toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-keda.yaml b/backing-services/ingress-nginx/templates/controller-keda.yaml new file mode 100644 index 0000000..24d30fa --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-keda.yaml @@ -0,0 +1,46 @@ +{{- if and (eq .Values.controller.kind "Deployment") .Values.controller.keda.enabled (not .Values.controller.autoscaling.enabled) -}} +apiVersion: {{ .Values.controller.keda.apiVersion }} +kind: ScaledObject +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} + {{- if .Values.controller.keda.scaledObject.annotations }} + annotations: {{ toYaml .Values.controller.keda.scaledObject.annotations | nindent 4 }} + {{- end }} +spec: + scaleTargetRef: +{{- if eq .Values.controller.keda.apiVersion "keda.k8s.io/v1alpha1" }} + deploymentName: {{ include "ingress-nginx.controller.fullname" . }} +{{- else if eq .Values.controller.keda.apiVersion "keda.sh/v1alpha1" }} + name: {{ include "ingress-nginx.controller.fullname" . }} +{{- end }} + pollingInterval: {{ .Values.controller.keda.pollingInterval }} + cooldownPeriod: {{ .Values.controller.keda.cooldownPeriod }} + minReplicaCount: {{ .Values.controller.keda.minReplicas }} + maxReplicaCount: {{ .Values.controller.keda.maxReplicas }} +{{- with .Values.controller.keda.fallback }} + fallback: + failureThreshold: {{ .failureThreshold | default 3 }} + replicas: {{ .replicas | default $.Values.controller.keda.maxReplicas }} +{{- end }} + triggers: +{{- with .Values.controller.keda.triggers }} +{{ toYaml . | indent 2 }} +{{ end }} + advanced: + restoreToOriginalReplicaCount: {{ .Values.controller.keda.restoreToOriginalReplicaCount }} +{{- if .Values.controller.keda.behavior }} + horizontalPodAutoscalerConfig: + behavior: +{{ with .Values.controller.keda.behavior -}} +{{ toYaml . | indent 8 }} +{{ end }} + +{{- end }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-networkpolicy.yaml b/backing-services/ingress-nginx/templates/controller-networkpolicy.yaml new file mode 100644 index 0000000..e68f991 --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-networkpolicy.yaml @@ -0,0 +1,45 @@ +{{- if .Values.controller.networkPolicy.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + podSelector: + matchLabels: + {{- include "ingress-nginx.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: controller + policyTypes: + - Ingress + - Egress + ingress: + - ports: + {{- range $key, $value := .Values.controller.containerPort }} + - protocol: TCP + port: {{ $value }} + {{- end }} + {{- if .Values.controller.metrics.enabled }} + - protocol: TCP + port: {{ .Values.controller.metrics.port }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.enabled }} + - protocol: TCP + port: {{ .Values.controller.admissionWebhooks.port }} + {{- end }} + {{- range $key, $value := .Values.tcp }} + - protocol: TCP + port: {{ $key }} + {{- end }} + {{- range $key, $value := .Values.udp }} + - protocol: UDP + port: {{ $key }} + {{- end }} + egress: + - {} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-poddisruptionbudget.yaml b/backing-services/ingress-nginx/templates/controller-poddisruptionbudget.yaml new file mode 100644 index 0000000..8e0181f --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-poddisruptionbudget.yaml @@ -0,0 +1,36 @@ +# PDB is not supported for DaemonSets. +# https://github.com/kubernetes/kubernetes/issues/108124 +{{- if eq .Values.controller.kind "Deployment" }} +{{- $replicas := .Values.controller.replicaCount }} +{{- if and .Values.controller.autoscaling.enabled (not .Values.controller.keda.enabled) }} +{{- $replicas = .Values.controller.autoscaling.minReplicas }} +{{- else if and .Values.controller.keda.enabled (not .Values.controller.autoscaling.enabled) }} +{{- $replicas = .Values.controller.keda.minReplicas }} +{{- end }} +{{- if gt ($replicas | int) 1 }} +apiVersion: {{ ternary "policy/v1" "policy/v1beta1" (semverCompare ">=1.21.0-0" .Capabilities.KubeVersion.Version) }} +kind: PodDisruptionBudget +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} + {{- if .Values.controller.annotations }} + annotations: {{ toYaml .Values.controller.annotations | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "ingress-nginx.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: controller + {{- if and .Values.controller.minAvailable (not (hasKey .Values.controller "maxUnavailable")) }} + minAvailable: {{ .Values.controller.minAvailable }} + {{- else if .Values.controller.maxUnavailable }} + maxUnavailable: {{ .Values.controller.maxUnavailable }} + {{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-prometheusrule.yaml b/backing-services/ingress-nginx/templates/controller-prometheusrule.yaml new file mode 100644 index 0000000..41684c3 --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-prometheusrule.yaml @@ -0,0 +1,23 @@ +{{- if and .Values.controller.metrics.enabled .Values.controller.metrics.prometheusRule.enabled -}} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ include "ingress-nginx.controller.fullname" . }} +{{- if .Values.controller.metrics.prometheusRule.namespace }} + namespace: {{ .Values.controller.metrics.prometheusRule.namespace }} +{{- else }} + namespace: {{ include "ingress-nginx.namespace" . }} +{{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- if .Values.controller.metrics.prometheusRule.additionalLabels }} + {{- toYaml .Values.controller.metrics.prometheusRule.additionalLabels | nindent 4 }} + {{- end }} +spec: +{{- if .Values.controller.metrics.prometheusRule.rules }} + groups: + - name: {{ template "ingress-nginx.name" . }} + rules: {{- toYaml .Values.controller.metrics.prometheusRule.rules | nindent 4 }} +{{- end }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-psp.yaml b/backing-services/ingress-nginx/templates/controller-psp.yaml new file mode 100644 index 0000000..aad1d27 --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-psp.yaml @@ -0,0 +1,100 @@ +{{- if (semverCompare "<1.25.0-0" .Capabilities.KubeVersion.Version) }} +{{- if and .Values.podSecurityPolicy.enabled (empty .Values.controller.existingPsp) -}} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "ingress-nginx.fullname" . }} + annotations: + seccomp.security.alpha.kubernetes.io/allowedProfileNames: "*" + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + privileged: false + hostPID: false + hostIPC: false + hostNetwork: {{ .Values.controller.hostNetwork }} +{{- if or .Values.controller.hostNetwork .Values.controller.hostPort.enabled }} + hostPorts: + {{- if .Values.controller.hostNetwork }} + {{- range $key, $value := .Values.controller.containerPort }} + # controller.containerPort.{{ $key }} + - min: {{ $value }} + max: {{ $value }} + {{- end }} + {{- else if .Values.controller.hostPort.enabled }} + {{- range $key, $value := .Values.controller.hostPort.ports }} + # controller.hostPort.ports.{{ $key }} + - min: {{ $value }} + max: {{ $value }} + {{- end }} + {{- end }} + {{- if .Values.controller.metrics.enabled }} + # controller.metrics.port + - min: {{ .Values.controller.metrics.port }} + max: {{ .Values.controller.metrics.port }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.enabled }} + # controller.admissionWebhooks.port + - min: {{ .Values.controller.admissionWebhooks.port }} + max: {{ .Values.controller.admissionWebhooks.port }} + {{- end }} + {{- range $key, $value := .Values.tcp }} + # tcp.{{ $key }} + - min: {{ $key }} + max: {{ $key }} + {{- end }} + {{- range $key, $value := .Values.udp }} + # udp.{{ $key }} + - min: {{ $key }} + max: {{ $key }} + {{- end }} +{{- end }} + volumes: + - configMap + - downwardAPI + - emptyDir + - secret + - projected + fsGroup: + rule: MustRunAs + ranges: + - min: 1 + max: 65535 + readOnlyRootFilesystem: false + runAsUser: + rule: MustRunAsNonRoot + runAsGroup: + rule: MustRunAs + ranges: + - min: 1 + max: 65535 + supplementalGroups: + rule: MustRunAs + ranges: + - min: 1 + max: 65535 + allowPrivilegeEscalation: {{ or .Values.controller.image.allowPrivilegeEscalation .Values.controller.image.chroot }} + requiredDropCapabilities: + - ALL + allowedCapabilities: + - NET_BIND_SERVICE + {{- if .Values.controller.image.chroot }} + {{- if .Values.controller.image.seccompProfile }} + - SYS_ADMIN + {{- end }} + - SYS_CHROOT + {{- end }} + seLinux: + rule: RunAsAny +{{- if .Values.controller.sysctls }} + allowedUnsafeSysctls: + {{- range $sysctl, $value := .Values.controller.sysctls }} + - {{ $sysctl }} + {{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-role.yaml b/backing-services/ingress-nginx/templates/controller-role.yaml new file mode 100644 index 0000000..a94b399 --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-role.yaml @@ -0,0 +1,104 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +rules: + - apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - apiGroups: + - "" + resources: + - configmaps + - pods + - secrets + - endpoints + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch + - apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - get + - list + - watch + # Omit Ingress status permissions if `--update-status` is disabled. + {{- if ne (index .Values.controller.extraArgs "update-status") "false" }} + - apiGroups: + - networking.k8s.io + resources: + - ingresses/status + verbs: + - update + {{- end }} + - apiGroups: + - networking.k8s.io + resources: + - ingressclasses + verbs: + - get + - list + - watch + - apiGroups: + - coordination.k8s.io + resources: + - leases + resourceNames: + - {{ include "ingress-nginx.controller.electionID" . }} + verbs: + - get + - update + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - list + - watch + - get +{{- if .Values.podSecurityPolicy.enabled }} + - apiGroups: [{{ template "podSecurityPolicy.apiGroup" . }}] + resources: ['podsecuritypolicies'] + verbs: ['use'] + {{- with .Values.controller.existingPsp }} + resourceNames: [{{ . }}] + {{- else }} + resourceNames: [{{ include "ingress-nginx.fullname" . }}] + {{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-rolebinding.yaml b/backing-services/ingress-nginx/templates/controller-rolebinding.yaml new file mode 100644 index 0000000..153430a --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-rolebinding.yaml @@ -0,0 +1,21 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "ingress-nginx.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "ingress-nginx.serviceAccountName" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-secret.yaml b/backing-services/ingress-nginx/templates/controller-secret.yaml new file mode 100644 index 0000000..f20f534 --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-secret.yaml @@ -0,0 +1,15 @@ +{{- if .Values.dhParam -}} +apiVersion: v1 +kind: Secret +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +data: + dhparam.pem: {{ .Values.dhParam }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-service-internal.yaml b/backing-services/ingress-nginx/templates/controller-service-internal.yaml new file mode 100644 index 0000000..6d0b47c --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-service-internal.yaml @@ -0,0 +1,105 @@ +{{- if and .Values.controller.service.enabled .Values.controller.service.internal.enabled .Values.controller.service.internal.annotations -}} +apiVersion: v1 +kind: Service +metadata: + annotations: + {{- range $key, $value := .Values.controller.service.internal.annotations }} + {{ $key }}: {{ tpl ($value | toString) $ | quote }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- if .Values.controller.service.labels }} + {{- toYaml .Values.controller.service.labels | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }}-internal + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + type: {{ .Values.controller.service.internal.type | default .Values.controller.service.type }} +{{- if .Values.controller.service.internal.clusterIP }} + clusterIP: {{ .Values.controller.service.internal.clusterIP }} +{{- end }} +{{- if .Values.controller.service.internal.externalIPs }} + externalIPs: {{ toYaml .Values.controller.service.internal.externalIPs | nindent 4 }} +{{- end }} +{{- if .Values.controller.service.internal.loadBalancerIP }} + loadBalancerIP: {{ .Values.controller.service.internal.loadBalancerIP }} +{{- end }} +{{- if .Values.controller.service.internal.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{ toYaml .Values.controller.service.internal.loadBalancerSourceRanges | nindent 4 }} +{{- end }} +{{- if .Values.controller.service.internal.loadBalancerClass }} + loadBalancerClass: {{ .Values.controller.service.internal.loadBalancerClass }} +{{- end }} +{{- if hasKey .Values.controller.service.internal "allocateLoadBalancerNodePorts" }} + allocateLoadBalancerNodePorts: {{ .Values.controller.service.internal.allocateLoadBalancerNodePorts }} +{{- end }} +{{- if .Values.controller.service.internal.externalTrafficPolicy }} + externalTrafficPolicy: {{ .Values.controller.service.internal.externalTrafficPolicy }} +{{- end }} +{{- if .Values.controller.service.internal.sessionAffinity }} + sessionAffinity: {{ .Values.controller.service.internal.sessionAffinity }} +{{- end }} +{{- if .Values.controller.service.internal.healthCheckNodePort }} + healthCheckNodePort: {{ .Values.controller.service.internal.healthCheckNodePort }} +{{- end }} +{{- if semverCompare ">=1.21.0-0" .Capabilities.KubeVersion.Version -}} +{{- if .Values.controller.service.internal.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.controller.service.internal.ipFamilyPolicy }} +{{- end }} +{{- if .Values.controller.service.internal.ipFamilies }} + ipFamilies: {{ toYaml .Values.controller.service.internal.ipFamilies | nindent 4 }} +{{- end }} +{{- end }} + ports: + {{- $setNodePorts := (or (eq .Values.controller.service.type "NodePort") (eq .Values.controller.service.type "LoadBalancer")) }} + {{- if .Values.controller.service.enableHttp }} + - name: http + port: {{ .Values.controller.service.internal.ports.http | default .Values.controller.service.ports.http }} + protocol: TCP + targetPort: {{ .Values.controller.service.internal.targetPorts.http | default .Values.controller.service.targetPorts.http }} + {{- if and (semverCompare ">=1.20.0-0" .Capabilities.KubeVersion.Version) (.Values.controller.service.internal.appProtocol) }} + appProtocol: http + {{- end }} + {{- if (and $setNodePorts (not (empty .Values.controller.service.internal.nodePorts.http))) }} + nodePort: {{ .Values.controller.service.internal.nodePorts.http }} + {{- end }} + {{- end }} + {{- if .Values.controller.service.enableHttps }} + - name: https + port: {{ .Values.controller.service.internal.ports.https | default .Values.controller.service.ports.https }} + protocol: TCP + targetPort: {{ .Values.controller.service.internal.targetPorts.https | default .Values.controller.service.targetPorts.https }} + {{- if and (semverCompare ">=1.20.0-0" .Capabilities.KubeVersion.Version) (.Values.controller.service.internal.appProtocol) }} + appProtocol: https + {{- end }} + {{- if (and $setNodePorts (not (empty .Values.controller.service.internal.nodePorts.https))) }} + nodePort: {{ .Values.controller.service.internal.nodePorts.https }} + {{- end }} + {{- end }} + {{- range $key, $value := .Values.tcp }} + - name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-tcp + port: {{ $key }} + protocol: TCP + targetPort: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-tcp + {{- if $.Values.controller.service.internal.nodePorts.tcp }} + {{- if index $.Values.controller.service.internal.nodePorts.tcp $key }} + nodePort: {{ index $.Values.controller.service.internal.nodePorts.tcp $key }} + {{- end }} + {{- end }} + {{- end }} + {{- range $key, $value := .Values.udp }} + - name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-udp + port: {{ $key }} + protocol: UDP + targetPort: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-udp + {{- if $.Values.controller.service.internal.nodePorts.udp }} + {{- if index $.Values.controller.service.internal.nodePorts.udp $key }} + nodePort: {{ index $.Values.controller.service.internal.nodePorts.udp $key }} + {{- end }} + {{- end }} + {{- end }} + selector: + {{- include "ingress-nginx.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: controller +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-service-metrics.yaml b/backing-services/ingress-nginx/templates/controller-service-metrics.yaml new file mode 100644 index 0000000..7c15329 --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-service-metrics.yaml @@ -0,0 +1,45 @@ +{{- if .Values.controller.metrics.enabled -}} +apiVersion: v1 +kind: Service +metadata: +{{- if .Values.controller.metrics.service.annotations }} + annotations: {{ toYaml .Values.controller.metrics.service.annotations | nindent 4 }} +{{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- if .Values.controller.metrics.service.labels }} + {{- toYaml .Values.controller.metrics.service.labels | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }}-metrics + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + type: {{ .Values.controller.metrics.service.type }} +{{- if .Values.controller.metrics.service.clusterIP }} + clusterIP: {{ .Values.controller.metrics.service.clusterIP }} +{{- end }} +{{- if .Values.controller.metrics.service.externalIPs }} + externalIPs: {{ toYaml .Values.controller.metrics.service.externalIPs | nindent 4 }} +{{- end }} +{{- if .Values.controller.metrics.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.controller.metrics.service.loadBalancerIP }} +{{- end }} +{{- if .Values.controller.metrics.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{ toYaml .Values.controller.metrics.service.loadBalancerSourceRanges | nindent 4 }} +{{- end }} +{{- if .Values.controller.metrics.service.externalTrafficPolicy }} + externalTrafficPolicy: {{ .Values.controller.metrics.service.externalTrafficPolicy }} +{{- end }} + ports: + - name: {{ .Values.controller.metrics.portName }} + port: {{ .Values.controller.metrics.service.servicePort }} + protocol: TCP + targetPort: {{ .Values.controller.metrics.portName }} + {{- $setNodePorts := (or (eq .Values.controller.metrics.service.type "NodePort") (eq .Values.controller.metrics.service.type "LoadBalancer")) }} + {{- if (and $setNodePorts (not (empty .Values.controller.metrics.service.nodePort))) }} + nodePort: {{ .Values.controller.metrics.service.nodePort }} + {{- end }} + selector: + {{- include "ingress-nginx.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: controller +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-service-webhook.yaml b/backing-services/ingress-nginx/templates/controller-service-webhook.yaml new file mode 100644 index 0000000..67aac0d --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-service-webhook.yaml @@ -0,0 +1,40 @@ +{{- if .Values.controller.admissionWebhooks.enabled -}} +apiVersion: v1 +kind: Service +metadata: +{{- if .Values.controller.admissionWebhooks.service.annotations }} + annotations: {{ toYaml .Values.controller.admissionWebhooks.service.annotations | nindent 4 }} +{{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }}-admission + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + type: {{ .Values.controller.admissionWebhooks.service.type }} +{{- if .Values.controller.admissionWebhooks.service.clusterIP }} + clusterIP: {{ .Values.controller.admissionWebhooks.service.clusterIP }} +{{- end }} +{{- if .Values.controller.admissionWebhooks.service.externalIPs }} + externalIPs: {{ toYaml .Values.controller.admissionWebhooks.service.externalIPs | nindent 4 }} +{{- end }} +{{- if .Values.controller.admissionWebhooks.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.controller.admissionWebhooks.service.loadBalancerIP }} +{{- end }} +{{- if .Values.controller.admissionWebhooks.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{ toYaml .Values.controller.admissionWebhooks.service.loadBalancerSourceRanges | nindent 4 }} +{{- end }} + ports: + - name: https-webhook + port: {{ .Values.controller.admissionWebhooks.service.servicePort }} + targetPort: webhook + {{- if semverCompare ">=1.20.0-0" .Capabilities.KubeVersion.Version }} + appProtocol: https + {{- end }} + selector: + {{- include "ingress-nginx.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: controller +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-service.yaml b/backing-services/ingress-nginx/templates/controller-service.yaml new file mode 100644 index 0000000..cb78a70 --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-service.yaml @@ -0,0 +1,105 @@ +{{- if and .Values.controller.service.enabled .Values.controller.service.external.enabled -}} +apiVersion: v1 +kind: Service +metadata: + annotations: + {{- range $key, $value := .Values.controller.service.annotations }} + {{ $key }}: {{ tpl ($value | toString) $ | quote }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- if .Values.controller.service.labels }} + {{- toYaml .Values.controller.service.labels | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + type: {{ .Values.controller.service.type }} +{{- if .Values.controller.service.clusterIP }} + clusterIP: {{ .Values.controller.service.clusterIP }} +{{- end }} +{{- if .Values.controller.service.externalIPs }} + externalIPs: {{ toYaml .Values.controller.service.externalIPs | nindent 4 }} +{{- end }} +{{- if .Values.controller.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.controller.service.loadBalancerIP }} +{{- end }} +{{- if .Values.controller.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{ toYaml .Values.controller.service.loadBalancerSourceRanges | nindent 4 }} +{{- end }} +{{- if .Values.controller.service.loadBalancerClass }} + loadBalancerClass: {{ .Values.controller.service.loadBalancerClass }} +{{- end }} +{{- if hasKey .Values.controller.service "allocateLoadBalancerNodePorts" }} + allocateLoadBalancerNodePorts: {{ .Values.controller.service.allocateLoadBalancerNodePorts }} +{{- end }} +{{- if .Values.controller.service.externalTrafficPolicy }} + externalTrafficPolicy: {{ .Values.controller.service.externalTrafficPolicy }} +{{- end }} +{{- if .Values.controller.service.sessionAffinity }} + sessionAffinity: {{ .Values.controller.service.sessionAffinity }} +{{- end }} +{{- if .Values.controller.service.healthCheckNodePort }} + healthCheckNodePort: {{ .Values.controller.service.healthCheckNodePort }} +{{- end }} +{{- if semverCompare ">=1.21.0-0" .Capabilities.KubeVersion.Version -}} +{{- if .Values.controller.service.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.controller.service.ipFamilyPolicy }} +{{- end }} +{{- if .Values.controller.service.ipFamilies }} + ipFamilies: {{ toYaml .Values.controller.service.ipFamilies | nindent 4 }} +{{- end }} +{{- end }} + ports: + {{- $setNodePorts := (or (eq .Values.controller.service.type "NodePort") (eq .Values.controller.service.type "LoadBalancer")) }} + {{- if .Values.controller.service.enableHttp }} + - name: http + port: {{ .Values.controller.service.ports.http }} + protocol: TCP + targetPort: {{ .Values.controller.service.targetPorts.http }} + {{- if and (semverCompare ">=1.20.0-0" .Capabilities.KubeVersion.Version) (.Values.controller.service.appProtocol) }} + appProtocol: http + {{- end }} + {{- if (and $setNodePorts (not (empty .Values.controller.service.nodePorts.http))) }} + nodePort: {{ .Values.controller.service.nodePorts.http }} + {{- end }} + {{- end }} + {{- if .Values.controller.service.enableHttps }} + - name: https + port: {{ .Values.controller.service.ports.https }} + protocol: TCP + targetPort: {{ .Values.controller.service.targetPorts.https }} + {{- if and (semverCompare ">=1.20.0-0" .Capabilities.KubeVersion.Version) (.Values.controller.service.appProtocol) }} + appProtocol: https + {{- end }} + {{- if (and $setNodePorts (not (empty .Values.controller.service.nodePorts.https))) }} + nodePort: {{ .Values.controller.service.nodePorts.https }} + {{- end }} + {{- end }} + {{- range $key, $value := .Values.tcp }} + - name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-tcp + port: {{ $key }} + protocol: TCP + targetPort: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-tcp + {{- if $.Values.controller.service.nodePorts.tcp }} + {{- if index $.Values.controller.service.nodePorts.tcp $key }} + nodePort: {{ index $.Values.controller.service.nodePorts.tcp $key }} + {{- end }} + {{- end }} + {{- end }} + {{- range $key, $value := .Values.udp }} + - name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-udp + port: {{ $key }} + protocol: UDP + targetPort: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-udp + {{- if $.Values.controller.service.nodePorts.udp }} + {{- if index $.Values.controller.service.nodePorts.udp $key }} + nodePort: {{ index $.Values.controller.service.nodePorts.udp $key }} + {{- end }} + {{- end }} + {{- end }} + selector: + {{- include "ingress-nginx.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: controller +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-serviceaccount.yaml b/backing-services/ingress-nginx/templates/controller-serviceaccount.yaml new file mode 100644 index 0000000..df83de3 --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-serviceaccount.yaml @@ -0,0 +1,17 @@ +{{- if or .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ template "ingress-nginx.serviceAccountName" . }} + namespace: {{ include "ingress-nginx.namespace" . }} + {{- if .Values.serviceAccount.annotations }} + annotations: {{ toYaml .Values.serviceAccount.annotations | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/controller-servicemonitor.yaml b/backing-services/ingress-nginx/templates/controller-servicemonitor.yaml new file mode 100644 index 0000000..62301da --- /dev/null +++ b/backing-services/ingress-nginx/templates/controller-servicemonitor.yaml @@ -0,0 +1,53 @@ +{{- if and .Values.controller.metrics.enabled .Values.controller.metrics.serviceMonitor.enabled -}} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "ingress-nginx.controller.fullname" . }} +{{- if .Values.controller.metrics.serviceMonitor.namespace }} + namespace: {{ .Values.controller.metrics.serviceMonitor.namespace }} +{{- else }} + namespace: {{ include "ingress-nginx.namespace" . }} +{{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- if .Values.controller.metrics.serviceMonitor.additionalLabels }} + {{- toYaml .Values.controller.metrics.serviceMonitor.additionalLabels | nindent 4 }} + {{- end }} + {{- if .Values.controller.metrics.serviceMonitor.annotations }} + annotations: {{ toYaml .Values.controller.metrics.serviceMonitor.annotations | nindent 4 }} + {{- end }} +spec: + endpoints: + - port: {{ .Values.controller.metrics.portName }} + interval: {{ .Values.controller.metrics.serviceMonitor.scrapeInterval }} + {{- if .Values.controller.metrics.serviceMonitor.honorLabels }} + honorLabels: true + {{- end }} + {{- if .Values.controller.metrics.serviceMonitor.relabelings }} + relabelings: {{ toYaml .Values.controller.metrics.serviceMonitor.relabelings | nindent 8 }} + {{- end }} + {{- if .Values.controller.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: {{ toYaml .Values.controller.metrics.serviceMonitor.metricRelabelings | nindent 8 }} + {{- end }} +{{- if .Values.controller.metrics.serviceMonitor.jobLabel }} + jobLabel: {{ .Values.controller.metrics.serviceMonitor.jobLabel | quote }} +{{- end }} +{{- if .Values.controller.metrics.serviceMonitor.namespaceSelector }} + namespaceSelector: {{ toYaml .Values.controller.metrics.serviceMonitor.namespaceSelector | nindent 4 }} +{{- else }} + namespaceSelector: + matchNames: + - {{ include "ingress-nginx.namespace" . }} +{{- end }} +{{- if .Values.controller.metrics.serviceMonitor.targetLabels }} + targetLabels: + {{- range .Values.controller.metrics.serviceMonitor.targetLabels }} + - {{ . }} + {{- end }} +{{- end }} + selector: + matchLabels: + {{- include "ingress-nginx.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: controller +{{- end }} diff --git a/backing-services/ingress-nginx/templates/default-backend-deployment.yaml b/backing-services/ingress-nginx/templates/default-backend-deployment.yaml new file mode 100644 index 0000000..6755e23 --- /dev/null +++ b/backing-services/ingress-nginx/templates/default-backend-deployment.yaml @@ -0,0 +1,119 @@ +{{- if .Values.defaultBackend.enabled -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: default-backend + {{- with .Values.defaultBackend.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.defaultBackend.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + selector: + matchLabels: + {{- include "ingress-nginx.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: default-backend +{{- if not .Values.defaultBackend.autoscaling.enabled }} + replicas: {{ .Values.defaultBackend.replicaCount }} +{{- end }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + {{- if .Values.defaultBackend.updateStrategy }} + strategy: + {{ toYaml .Values.defaultBackend.updateStrategy | nindent 4 }} + {{- end }} + minReadySeconds: {{ .Values.defaultBackend.minReadySeconds }} + template: + metadata: + {{- if .Values.defaultBackend.podAnnotations }} + annotations: {{ toYaml .Values.defaultBackend.podAnnotations | nindent 8 }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 8 }} + app.kubernetes.io/component: default-backend + {{- with .Values.defaultBackend.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.defaultBackend.podLabels }} + {{- toYaml .Values.defaultBackend.podLabels | nindent 8 }} + {{- end }} + spec: + {{- if .Values.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 8 }} + {{- end }} + {{- if .Values.defaultBackend.priorityClassName }} + priorityClassName: {{ .Values.defaultBackend.priorityClassName }} + {{- end }} + {{- if .Values.defaultBackend.podSecurityContext }} + securityContext: {{ toYaml .Values.defaultBackend.podSecurityContext | nindent 8 }} + {{- end }} + containers: + - name: {{ template "ingress-nginx.name" . }}-default-backend + {{- with .Values.defaultBackend.image }} + image: {{ if .repository }}{{ .repository }}{{ else }}{{ .registry }}/{{ .image }}{{ end }}:{{ .tag }}{{ if .digest }}@{{ .digest }}{{ end }} + {{- end }} + imagePullPolicy: {{ .Values.defaultBackend.image.pullPolicy }} + {{- if .Values.defaultBackend.extraArgs }} + args: + {{- range $key, $value := .Values.defaultBackend.extraArgs }} + {{- /* Accept keys without values or with false as value */}} + {{- if eq ($value | quote | len) 2 }} + - --{{ $key }} + {{- else }} + - --{{ $key }}={{ $value }} + {{- end }} + {{- end }} + {{- end }} + securityContext: {{ include "ingress-nginx.defaultBackend.containerSecurityContext" . | nindent 12 }} + {{- if .Values.defaultBackend.extraEnvs }} + env: {{ toYaml .Values.defaultBackend.extraEnvs | nindent 12 }} + {{- end }} + livenessProbe: + httpGet: + path: /healthz + port: {{ .Values.defaultBackend.port }} + scheme: HTTP + initialDelaySeconds: {{ .Values.defaultBackend.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.defaultBackend.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.defaultBackend.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.defaultBackend.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.defaultBackend.livenessProbe.failureThreshold }} + readinessProbe: + httpGet: + path: /healthz + port: {{ .Values.defaultBackend.port }} + scheme: HTTP + initialDelaySeconds: {{ .Values.defaultBackend.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.defaultBackend.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.defaultBackend.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.defaultBackend.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.defaultBackend.readinessProbe.failureThreshold }} + ports: + - name: http + containerPort: {{ .Values.defaultBackend.port }} + protocol: TCP + {{- if .Values.defaultBackend.extraVolumeMounts }} + volumeMounts: {{- toYaml .Values.defaultBackend.extraVolumeMounts | nindent 12 }} + {{- end }} + {{- if .Values.defaultBackend.resources }} + resources: {{ toYaml .Values.defaultBackend.resources | nindent 12 }} + {{- end }} + {{- if .Values.defaultBackend.nodeSelector }} + nodeSelector: {{ toYaml .Values.defaultBackend.nodeSelector | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "ingress-nginx.defaultBackend.serviceAccountName" . }} + {{- if .Values.defaultBackend.tolerations }} + tolerations: {{ toYaml .Values.defaultBackend.tolerations | nindent 8 }} + {{- end }} + {{- if .Values.defaultBackend.affinity }} + affinity: {{ tpl (toYaml .Values.defaultBackend.affinity) $ | nindent 8 }} + {{- end }} + {{- if .Values.defaultBackend.topologySpreadConstraints }} + topologySpreadConstraints: {{ tpl (toYaml .Values.defaultBackend.topologySpreadConstraints) $ | nindent 8 }} + {{- end }} + terminationGracePeriodSeconds: 60 + {{- if .Values.defaultBackend.extraVolumes }} + volumes: {{ toYaml .Values.defaultBackend.extraVolumes | nindent 8 }} + {{- end }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/default-backend-extra-configmaps.yaml b/backing-services/ingress-nginx/templates/default-backend-extra-configmaps.yaml new file mode 100644 index 0000000..9af56cf --- /dev/null +++ b/backing-services/ingress-nginx/templates/default-backend-extra-configmaps.yaml @@ -0,0 +1,23 @@ +{{- if .Values.defaultBackend.enabled }} +{{- range .Values.defaultBackend.extraConfigMaps }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + {{- include "ingress-nginx.labels" $ | nindent 4 }} + app.kubernetes.io/component: default-backend + {{- with $.Values.defaultBackend.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ .name }} + namespace: {{ include "ingress-nginx.namespace" $ }} +data: + {{- with .data }} + {{- toYaml . | nindent 2 }} + {{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/default-backend-hpa.yaml b/backing-services/ingress-nginx/templates/default-backend-hpa.yaml new file mode 100644 index 0000000..49bcdcf --- /dev/null +++ b/backing-services/ingress-nginx/templates/default-backend-hpa.yaml @@ -0,0 +1,40 @@ +{{- if and .Values.defaultBackend.enabled .Values.defaultBackend.autoscaling.enabled }} +apiVersion: {{ ternary "autoscaling/v2" "autoscaling/v2beta2" (.Capabilities.APIVersions.Has "autoscaling/v2") }} +kind: HorizontalPodAutoscaler +metadata: + {{- with .Values.defaultBackend.autoscaling.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: default-backend + {{- with .Values.defaultBackend.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.defaultBackend.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "ingress-nginx.defaultBackend.fullname" . }} + minReplicas: {{ .Values.defaultBackend.autoscaling.minReplicas }} + maxReplicas: {{ .Values.defaultBackend.autoscaling.maxReplicas }} + metrics: + {{- with .Values.defaultBackend.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ . }} + {{- end }} + {{- with .Values.defaultBackend.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ . }} + {{- end }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/default-backend-networkpolicy.yaml b/backing-services/ingress-nginx/templates/default-backend-networkpolicy.yaml new file mode 100644 index 0000000..90b3c2b --- /dev/null +++ b/backing-services/ingress-nginx/templates/default-backend-networkpolicy.yaml @@ -0,0 +1,25 @@ +{{- if and .Values.defaultBackend.enabled .Values.defaultBackend.networkPolicy.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: default-backend + {{- with .Values.defaultBackend.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.defaultBackend.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + podSelector: + matchLabels: + {{- include "ingress-nginx.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: default-backend + policyTypes: + - Ingress + - Egress + ingress: + - ports: + - protocol: TCP + port: {{ .Values.defaultBackend.port }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/default-backend-poddisruptionbudget.yaml b/backing-services/ingress-nginx/templates/default-backend-poddisruptionbudget.yaml new file mode 100644 index 0000000..c8363fd --- /dev/null +++ b/backing-services/ingress-nginx/templates/default-backend-poddisruptionbudget.yaml @@ -0,0 +1,25 @@ +{{- if .Values.defaultBackend.enabled -}} +{{- $replicas := .Values.defaultBackend.replicaCount }} +{{- if .Values.defaultBackend.autoscaling.enabled }} +{{- $replicas = .Values.defaultBackend.autoscaling.minReplicas }} +{{- end }} +{{- if gt ($replicas | int) 1 }} +apiVersion: {{ ternary "policy/v1" "policy/v1beta1" (semverCompare ">=1.21.0-0" .Capabilities.KubeVersion.Version) }} +kind: PodDisruptionBudget +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: default-backend + {{- with .Values.defaultBackend.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.defaultBackend.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + selector: + matchLabels: + {{- include "ingress-nginx.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: default-backend + minAvailable: {{ .Values.defaultBackend.minAvailable }} +{{- end }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/default-backend-psp.yaml b/backing-services/ingress-nginx/templates/default-backend-psp.yaml new file mode 100644 index 0000000..4241091 --- /dev/null +++ b/backing-services/ingress-nginx/templates/default-backend-psp.yaml @@ -0,0 +1,50 @@ +{{- if (semverCompare "<1.25.0-0" .Capabilities.KubeVersion.Version) }} +{{- if and .Values.podSecurityPolicy.enabled .Values.defaultBackend.enabled (empty .Values.defaultBackend.existingPsp) -}} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "ingress-nginx.fullname" . }}-backend + annotations: + seccomp.security.alpha.kubernetes.io/allowedProfileNames: "*" + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: default-backend + {{- with .Values.defaultBackend.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + privileged: false + hostPID: false + hostIPC: false + hostNetwork: false + volumes: + - configMap + - downwardAPI + - emptyDir + - secret + - projected + fsGroup: + rule: MustRunAs + ranges: + - min: 1 + max: 65535 + readOnlyRootFilesystem: true + runAsUser: + rule: MustRunAsNonRoot + runAsGroup: + rule: MustRunAs + ranges: + - min: 1 + max: 65535 + supplementalGroups: + rule: MustRunAs + ranges: + - min: 1 + max: 65535 + allowPrivilegeEscalation: false + requiredDropCapabilities: + - ALL + seLinux: + rule: RunAsAny +{{- end }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/default-backend-role.yaml b/backing-services/ingress-nginx/templates/default-backend-role.yaml new file mode 100644 index 0000000..dd7868a --- /dev/null +++ b/backing-services/ingress-nginx/templates/default-backend-role.yaml @@ -0,0 +1,22 @@ +{{- if and .Values.rbac.create .Values.podSecurityPolicy.enabled .Values.defaultBackend.enabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: default-backend + {{- with .Values.defaultBackend.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.fullname" . }}-backend + namespace: {{ include "ingress-nginx.namespace" . }} +rules: + - apiGroups: [{{ template "podSecurityPolicy.apiGroup" . }}] + resources: ['podsecuritypolicies'] + verbs: ['use'] + {{- with .Values.defaultBackend.existingPsp }} + resourceNames: [{{ . }}] + {{- else }} + resourceNames: [{{ include "ingress-nginx.fullname" . }}-backend] + {{- end }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/default-backend-rolebinding.yaml b/backing-services/ingress-nginx/templates/default-backend-rolebinding.yaml new file mode 100644 index 0000000..3203b6f --- /dev/null +++ b/backing-services/ingress-nginx/templates/default-backend-rolebinding.yaml @@ -0,0 +1,21 @@ +{{- if and .Values.rbac.create .Values.podSecurityPolicy.enabled .Values.defaultBackend.enabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: default-backend + {{- with .Values.defaultBackend.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.fullname" . }}-backend + namespace: {{ include "ingress-nginx.namespace" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "ingress-nginx.fullname" . }}-backend +subjects: + - kind: ServiceAccount + name: {{ template "ingress-nginx.defaultBackend.serviceAccountName" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +{{- end }} diff --git a/backing-services/ingress-nginx/templates/default-backend-service.yaml b/backing-services/ingress-nginx/templates/default-backend-service.yaml new file mode 100644 index 0000000..65b6b83 --- /dev/null +++ b/backing-services/ingress-nginx/templates/default-backend-service.yaml @@ -0,0 +1,41 @@ +{{- if .Values.defaultBackend.enabled -}} +apiVersion: v1 +kind: Service +metadata: +{{- if .Values.defaultBackend.service.annotations }} + annotations: {{ toYaml .Values.defaultBackend.service.annotations | nindent 4 }} +{{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: default-backend + {{- with .Values.defaultBackend.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.defaultBackend.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + type: {{ .Values.defaultBackend.service.type }} +{{- if .Values.defaultBackend.service.clusterIP }} + clusterIP: {{ .Values.defaultBackend.service.clusterIP }} +{{- end }} +{{- if .Values.defaultBackend.service.externalIPs }} + externalIPs: {{ toYaml .Values.defaultBackend.service.externalIPs | nindent 4 }} +{{- end }} +{{- if .Values.defaultBackend.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.defaultBackend.service.loadBalancerIP }} +{{- end }} +{{- if .Values.defaultBackend.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{ toYaml .Values.defaultBackend.service.loadBalancerSourceRanges | nindent 4 }} +{{- end }} + ports: + - name: http + port: {{ .Values.defaultBackend.service.servicePort }} + protocol: TCP + targetPort: http + {{- if semverCompare ">=1.20.0-0" .Capabilities.KubeVersion.Version }} + appProtocol: http + {{- end }} + selector: + {{- include "ingress-nginx.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: default-backend +{{- end }} diff --git a/backing-services/ingress-nginx/templates/default-backend-serviceaccount.yaml b/backing-services/ingress-nginx/templates/default-backend-serviceaccount.yaml new file mode 100644 index 0000000..6fd2d62 --- /dev/null +++ b/backing-services/ingress-nginx/templates/default-backend-serviceaccount.yaml @@ -0,0 +1,14 @@ +{{- if and .Values.defaultBackend.enabled .Values.defaultBackend.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: default-backend + {{- with .Values.defaultBackend.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.defaultBackend.serviceAccountName" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +automountServiceAccountToken: {{ .Values.defaultBackend.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/backing-services/ingress-nginx/tests/admission-webhooks/job-patch/clusterrole_test.yaml b/backing-services/ingress-nginx/tests/admission-webhooks/job-patch/clusterrole_test.yaml new file mode 100644 index 0000000..d7a8b88 --- /dev/null +++ b/backing-services/ingress-nginx/tests/admission-webhooks/job-patch/clusterrole_test.yaml @@ -0,0 +1,11 @@ +suite: Admission Webhooks > Patch Job > ClusterRole +templates: + - admission-webhooks/job-patch/clusterrole.yaml + +tests: + - it: should not create a ClusterRole if `controller.admissionWebhooks.patch.rbac.create` is false + set: + controller.admissionWebhooks.patch.rbac.create: false + asserts: + - hasDocuments: + count: 0 diff --git a/backing-services/ingress-nginx/tests/admission-webhooks/job-patch/clusterrolebinding_test.yaml b/backing-services/ingress-nginx/tests/admission-webhooks/job-patch/clusterrolebinding_test.yaml new file mode 100644 index 0000000..d7c3266 --- /dev/null +++ b/backing-services/ingress-nginx/tests/admission-webhooks/job-patch/clusterrolebinding_test.yaml @@ -0,0 +1,11 @@ +suite: Admission Webhooks > Patch Job > ClusterRoleBinding +templates: + - admission-webhooks/job-patch/clusterrolebinding.yaml + +tests: + - it: should not create a ClusterRoleBinding if `controller.admissionWebhooks.patch.rbac.create` is false + set: + controller.admissionWebhooks.patch.rbac.create: false + asserts: + - hasDocuments: + count: 0 diff --git a/backing-services/ingress-nginx/tests/admission-webhooks/job-patch/role_test.yaml b/backing-services/ingress-nginx/tests/admission-webhooks/job-patch/role_test.yaml new file mode 100644 index 0000000..a236f3d --- /dev/null +++ b/backing-services/ingress-nginx/tests/admission-webhooks/job-patch/role_test.yaml @@ -0,0 +1,11 @@ +suite: Admission Webhooks > Patch Job > Role +templates: + - admission-webhooks/job-patch/role.yaml + +tests: + - it: should not create a Role if `controller.admissionWebhooks.patch.rbac.create` is false + set: + controller.admissionWebhooks.patch.rbac.create: false + asserts: + - hasDocuments: + count: 0 diff --git a/backing-services/ingress-nginx/tests/admission-webhooks/job-patch/rolebinding_test.yaml b/backing-services/ingress-nginx/tests/admission-webhooks/job-patch/rolebinding_test.yaml new file mode 100644 index 0000000..74abaa1 --- /dev/null +++ b/backing-services/ingress-nginx/tests/admission-webhooks/job-patch/rolebinding_test.yaml @@ -0,0 +1,11 @@ +suite: Admission Webhooks > Patch Job > RoleBinding +templates: + - admission-webhooks/job-patch/rolebinding.yaml + +tests: + - it: should not create a RoleBinding if `controller.admissionWebhooks.patch.rbac.create` is false + set: + controller.admissionWebhooks.patch.rbac.create: false + asserts: + - hasDocuments: + count: 0 diff --git a/backing-services/ingress-nginx/tests/admission-webhooks/job-patch/serviceaccount_test.yaml b/backing-services/ingress-nginx/tests/admission-webhooks/job-patch/serviceaccount_test.yaml new file mode 100644 index 0000000..7c30d1e --- /dev/null +++ b/backing-services/ingress-nginx/tests/admission-webhooks/job-patch/serviceaccount_test.yaml @@ -0,0 +1,47 @@ +suite: Admission Webhooks > Patch Job > ServiceAccount +templates: + - admission-webhooks/job-patch/serviceaccount.yaml + +tests: + - it: should not create a ServiceAccount if `controller.admissionWebhooks.patch.serviceAccount.create` is false + set: + controller.admissionWebhooks.patch.serviceAccount.create: false + asserts: + - hasDocuments: + count: 0 + + - it: should create a ServiceAccount if `controller.admissionWebhooks.patch.serviceAccount.create` is true + set: + controller.admissionWebhooks.patch.serviceAccount.create: true + asserts: + - hasDocuments: + count: 1 + - isKind: + of: ServiceAccount + - equal: + path: metadata.name + value: ingress-nginx-admission + + - it: should create a ServiceAccount with specified name if `controller.admissionWebhooks.patch.serviceAccount.name` is set + set: + controller.admissionWebhooks.patch.serviceAccount.name: ingress-nginx-admission-test-sa + asserts: + - hasDocuments: + count: 1 + - isKind: + of: ServiceAccount + - equal: + path: metadata.name + value: ingress-nginx-admission-test-sa + + - it: should create a ServiceAccount with token auto-mounting disabled if `controller.admissionWebhooks.patch.serviceAccount.automountServiceAccountToken` is false + set: + controller.admissionWebhooks.patch.serviceAccount.automountServiceAccountToken: false + asserts: + - hasDocuments: + count: 1 + - isKind: + of: ServiceAccount + - equal: + path: automountServiceAccountToken + value: false diff --git a/backing-services/ingress-nginx/tests/admission-webhooks/validating-webhook_test.yaml b/backing-services/ingress-nginx/tests/admission-webhooks/validating-webhook_test.yaml new file mode 100644 index 0000000..b9d6d78 --- /dev/null +++ b/backing-services/ingress-nginx/tests/admission-webhooks/validating-webhook_test.yaml @@ -0,0 +1,32 @@ +suite: Admission Webhooks > ValidatingWebhookConfiguration +templates: + - admission-webhooks/validating-webhook.yaml + +tests: + - it: should not create a ValidatingWebhookConfiguration if `controller.admissionWebhooks.enabled` is false + set: + controller.admissionWebhooks.enabled: false + asserts: + - hasDocuments: + count: 0 + + - it: should create a ValidatingWebhookConfiguration if `controller.admissionWebhooks.enabled` is true + set: + controller.admissionWebhooks.enabled: true + asserts: + - hasDocuments: + count: 1 + - isKind: + of: ValidatingWebhookConfiguration + - equal: + path: metadata.name + value: RELEASE-NAME-admission + + - it: should create a ValidatingWebhookConfiguration with a custom port if `controller.admissionWebhooks.service.servicePort` is set + set: + controller.admissionWebhooks.enabled: true + controller.admissionWebhooks.service.servicePort: 9443 + asserts: + - equal: + path: webhooks[0].clientConfig.service.port + value: 9443 diff --git a/backing-services/ingress-nginx/tests/controller-configmap-addheaders_test.yaml b/backing-services/ingress-nginx/tests/controller-configmap-addheaders_test.yaml new file mode 100644 index 0000000..e831d50 --- /dev/null +++ b/backing-services/ingress-nginx/tests/controller-configmap-addheaders_test.yaml @@ -0,0 +1,27 @@ +suite: Controller > ConfigMap > Add Headers +templates: + - controller-configmap-addheaders.yaml + +tests: + - it: should not create a ConfigMap if `controller.addHeaders` is not set + set: + controller.addHeaders: null + asserts: + - hasDocuments: + count: 0 + + - it: should create a ConfigMap if `controller.addHeaders` is set + set: + controller.addHeaders: + X-Another-Custom-Header: Value + asserts: + - hasDocuments: + count: 1 + - isKind: + of: ConfigMap + - equal: + path: metadata.name + value: RELEASE-NAME-ingress-nginx-custom-add-headers + - equal: + path: data.X-Another-Custom-Header + value: Value diff --git a/backing-services/ingress-nginx/tests/controller-configmap-proxyheaders_test.yaml b/backing-services/ingress-nginx/tests/controller-configmap-proxyheaders_test.yaml new file mode 100644 index 0000000..0634a37 --- /dev/null +++ b/backing-services/ingress-nginx/tests/controller-configmap-proxyheaders_test.yaml @@ -0,0 +1,27 @@ +suite: Controller > ConfigMap > Proxy Headers +templates: + - controller-configmap-proxyheaders.yaml + +tests: + - it: should not create a ConfigMap if `controller.proxySetHeaders` is not set + set: + controller.proxySetHeaders: null + asserts: + - hasDocuments: + count: 0 + + - it: should create a ConfigMap if `controller.proxySetHeaders` is set + set: + controller.proxySetHeaders: + X-Custom-Header: Value + asserts: + - hasDocuments: + count: 1 + - isKind: + of: ConfigMap + - equal: + path: metadata.name + value: RELEASE-NAME-ingress-nginx-custom-proxy-headers + - equal: + path: data.X-Custom-Header + value: Value diff --git a/backing-services/ingress-nginx/tests/controller-configmap_test.yaml b/backing-services/ingress-nginx/tests/controller-configmap_test.yaml new file mode 100644 index 0000000..168b657 --- /dev/null +++ b/backing-services/ingress-nginx/tests/controller-configmap_test.yaml @@ -0,0 +1,31 @@ +suite: Controller > ConfigMap +templates: + - controller-configmap.yaml + +tests: + - it: should create a ConfigMap + asserts: + - hasDocuments: + count: 1 + - isKind: + of: ConfigMap + - equal: + path: metadata.name + value: RELEASE-NAME-ingress-nginx-controller + + - it: should create a ConfigMap with templated values if `controller.config` contains templates + set: + controller.config: + template: "test.{{ .Release.Namespace }}.svc.kubernetes.local" + integer: 12345 + boolean: true + asserts: + - equal: + path: data.template + value: test.NAMESPACE.svc.kubernetes.local + - equal: + path: data.integer + value: "12345" + - equal: + path: data.boolean + value: "true" diff --git a/backing-services/ingress-nginx/tests/controller-daemonset_test.yaml b/backing-services/ingress-nginx/tests/controller-daemonset_test.yaml new file mode 100644 index 0000000..81d067b --- /dev/null +++ b/backing-services/ingress-nginx/tests/controller-daemonset_test.yaml @@ -0,0 +1,172 @@ +suite: Controller > DaemonSet +templates: + - controller-daemonset.yaml + +tests: + - it: should create a DaemonSet if `controller.kind` is "DaemonSet" + set: + controller.kind: DaemonSet + asserts: + - hasDocuments: + count: 1 + - isKind: + of: DaemonSet + - equal: + path: metadata.name + value: RELEASE-NAME-ingress-nginx-controller + + - it: should create a DaemonSet with argument `--enable-metrics=false` if `controller.metrics.enabled` is false + set: + controller.kind: DaemonSet + controller.metrics.enabled: false + asserts: + - contains: + path: spec.template.spec.containers[0].args + content: --enable-metrics=false + + - it: should create a DaemonSet without argument `--enable-metrics=false` if `controller.metrics.enabled` is true + set: + controller.kind: DaemonSet + controller.metrics.enabled: true + asserts: + - notContains: + path: spec.template.spec.containers[0].args + content: --enable-metrics=false + + - it: should create a DaemonSet with argument `--controller-class=k8s.io/ingress-nginx-internal` if `controller.ingressClassResource.controllerValue` is "k8s.io/ingress-nginx-internal" + set: + controller.kind: DaemonSet + controller.ingressClassResource.controllerValue: k8s.io/ingress-nginx-internal + asserts: + - contains: + path: spec.template.spec.containers[0].args + content: --controller-class=k8s.io/ingress-nginx-internal + + - it: should create a DaemonSet with resource limits if `controller.resources.limits` is set + set: + controller.kind: DaemonSet + controller.resources.limits.cpu: 500m + controller.resources.limits.memory: 512Mi + asserts: + - equal: + path: spec.template.spec.containers[0].resources.limits.cpu + value: 500m + - equal: + path: spec.template.spec.containers[0].resources.limits.memory + value: 512Mi + + - it: should create a DaemonSet with topology spread constraints if `controller.topologySpreadConstraints` is set + set: + controller.kind: DaemonSet + controller.topologySpreadConstraints: + - labelSelector: + matchLabels: + app.kubernetes.io/name: '{{ include "ingress-nginx.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + app.kubernetes.io/component: controller + topologyKey: topology.kubernetes.io/zone + maxSkew: 1 + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app.kubernetes.io/name: '{{ include "ingress-nginx.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + app.kubernetes.io/component: controller + topologyKey: kubernetes.io/hostname + maxSkew: 1 + whenUnsatisfiable: ScheduleAnyway + asserts: + - equal: + path: spec.template.spec.topologySpreadConstraints + value: + - labelSelector: + matchLabels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/component: controller + topologyKey: topology.kubernetes.io/zone + maxSkew: 1 + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/component: controller + topologyKey: kubernetes.io/hostname + maxSkew: 1 + whenUnsatisfiable: ScheduleAnyway + + - it: should create a DaemonSet with affinity if `controller.affinity` is set + set: + controller.kind: DaemonSet + controller.affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - '{{ include "ingress-nginx.name" . }}' + - key: app.kubernetes.io/instance + operator: In + values: + - '{{ .Release.Name }}' + - key: app.kubernetes.io/component + operator: In + values: + - controller + topologyKey: kubernetes.io/hostname + asserts: + - equal: + path: spec.template.spec.affinity + value: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - ingress-nginx + - key: app.kubernetes.io/instance + operator: In + values: + - RELEASE-NAME + - key: app.kubernetes.io/component + operator: In + values: + - controller + topologyKey: kubernetes.io/hostname + + - it: should create a DaemonSet with a custom registry if `controller.image.registry` is set + set: + controller.kind: DaemonSet + controller.image.registry: custom.registry.io + controller.image.tag: v1.0.0-dev + controller.image.digest: sha256:faa2d18687f734994b6bd9e309e7a73852a81c30e1b8f63165fcd4f0a087e3cd + asserts: + - equal: + path: spec.template.spec.containers[0].image + value: custom.registry.io/ingress-nginx/controller:v1.0.0-dev@sha256:faa2d18687f734994b6bd9e309e7a73852a81c30e1b8f63165fcd4f0a087e3cd + + - it: should create a DaemonSet with a custom image if `controller.image.image` is set + set: + controller.kind: DaemonSet + controller.image.image: custom-repo/custom-image + controller.image.tag: v1.0.0-dev + controller.image.digest: sha256:faa2d18687f734994b6bd9e309e7a73852a81c30e1b8f63165fcd4f0a087e3cd + asserts: + - equal: + path: spec.template.spec.containers[0].image + value: registry.k8s.io/custom-repo/custom-image:v1.0.0-dev@sha256:faa2d18687f734994b6bd9e309e7a73852a81c30e1b8f63165fcd4f0a087e3cd + + - it: should create a DaemonSet with a custom tag if `controller.image.tag` is set + set: + controller.kind: DaemonSet + controller.image.tag: custom-tag + controller.image.digest: sha256:faa2d18687f734994b6bd9e309e7a73852a81c30e1b8f63165fcd4f0a087e3cd + asserts: + - equal: + path: spec.template.spec.containers[0].image + value: registry.k8s.io/ingress-nginx/controller:custom-tag@sha256:faa2d18687f734994b6bd9e309e7a73852a81c30e1b8f63165fcd4f0a087e3cd diff --git a/backing-services/ingress-nginx/tests/controller-deployment_test.yaml b/backing-services/ingress-nginx/tests/controller-deployment_test.yaml new file mode 100644 index 0000000..382aecd --- /dev/null +++ b/backing-services/ingress-nginx/tests/controller-deployment_test.yaml @@ -0,0 +1,191 @@ +suite: Controller > Deployment +templates: + - controller-deployment.yaml + +tests: + - it: should create a Deployment + asserts: + - hasDocuments: + count: 1 + - isKind: + of: Deployment + - equal: + path: metadata.name + value: RELEASE-NAME-ingress-nginx-controller + + - it: should create a Deployment with 3 replicas if `controller.replicaCount` is 3 + set: + controller.replicaCount: 3 + asserts: + - equal: + path: spec.replicas + value: 3 + + - it: should create a Deployment without replicas if `controller.autoscaling.enabled` is true + set: + controller.autoscaling.enabled: true + asserts: + - notExists: + path: spec.replicas + + - it: should create a Deployment without replicas if `controller.keda.enabled` is true + set: + controller.keda.enabled: true + asserts: + - notExists: + path: spec.replicas + + - it: should create a Deployment with replicas if `controller.autoscaling.enabled` is true and `controller.keda.enabled` is true + set: + controller.autoscaling.enabled: true + controller.keda.enabled: true + asserts: + - exists: + path: spec.replicas + + - it: should create a Deployment with argument `--enable-metrics=false` if `controller.metrics.enabled` is false + set: + controller.metrics.enabled: false + asserts: + - contains: + path: spec.template.spec.containers[0].args + content: --enable-metrics=false + + - it: should create a Deployment without argument `--enable-metrics=false` if `controller.metrics.enabled` is true + set: + controller.metrics.enabled: true + asserts: + - notContains: + path: spec.template.spec.containers[0].args + content: --enable-metrics=false + + - it: should create a Deployment with argument `--controller-class=k8s.io/ingress-nginx-internal` if `controller.ingressClassResource.controllerValue` is "k8s.io/ingress-nginx-internal" + set: + controller.ingressClassResource.controllerValue: k8s.io/ingress-nginx-internal + asserts: + - contains: + path: spec.template.spec.containers[0].args + content: --controller-class=k8s.io/ingress-nginx-internal + + - it: should create a Deployment with resource limits if `controller.resources.limits` is set + set: + controller.resources.limits.cpu: 500m + controller.resources.limits.memory: 512Mi + asserts: + - equal: + path: spec.template.spec.containers[0].resources.limits.cpu + value: 500m + - equal: + path: spec.template.spec.containers[0].resources.limits.memory + value: 512Mi + + - it: should create a Deployment with topology spread constraints if `controller.topologySpreadConstraints` is set + set: + controller.topologySpreadConstraints: + - labelSelector: + matchLabels: + app.kubernetes.io/name: '{{ include "ingress-nginx.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + app.kubernetes.io/component: controller + topologyKey: topology.kubernetes.io/zone + maxSkew: 1 + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app.kubernetes.io/name: '{{ include "ingress-nginx.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + app.kubernetes.io/component: controller + topologyKey: kubernetes.io/hostname + maxSkew: 1 + whenUnsatisfiable: ScheduleAnyway + asserts: + - equal: + path: spec.template.spec.topologySpreadConstraints + value: + - labelSelector: + matchLabels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/component: controller + topologyKey: topology.kubernetes.io/zone + maxSkew: 1 + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/component: controller + topologyKey: kubernetes.io/hostname + maxSkew: 1 + whenUnsatisfiable: ScheduleAnyway + + - it: should create a Deployment with affinity if `controller.affinity` is set + set: + controller.affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - '{{ include "ingress-nginx.name" . }}' + - key: app.kubernetes.io/instance + operator: In + values: + - '{{ .Release.Name }}' + - key: app.kubernetes.io/component + operator: In + values: + - controller + topologyKey: kubernetes.io/hostname + asserts: + - equal: + path: spec.template.spec.affinity + value: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - ingress-nginx + - key: app.kubernetes.io/instance + operator: In + values: + - RELEASE-NAME + - key: app.kubernetes.io/component + operator: In + values: + - controller + topologyKey: kubernetes.io/hostname + + - it: should create a Deployment with a custom registry if `controller.image.registry` is set + set: + controller.image.registry: custom.registry.io + controller.image.tag: v1.0.0-dev + controller.image.digest: sha256:faa2d18687f734994b6bd9e309e7a73852a81c30e1b8f63165fcd4f0a087e3cd + asserts: + - equal: + path: spec.template.spec.containers[0].image + value: custom.registry.io/ingress-nginx/controller:v1.0.0-dev@sha256:faa2d18687f734994b6bd9e309e7a73852a81c30e1b8f63165fcd4f0a087e3cd + + - it: should create a Deployment with a custom image if `controller.image.image` is set + set: + controller.image.image: custom-repo/custom-image + controller.image.tag: v1.0.0-dev + controller.image.digest: sha256:faa2d18687f734994b6bd9e309e7a73852a81c30e1b8f63165fcd4f0a087e3cd + asserts: + - equal: + path: spec.template.spec.containers[0].image + value: registry.k8s.io/custom-repo/custom-image:v1.0.0-dev@sha256:faa2d18687f734994b6bd9e309e7a73852a81c30e1b8f63165fcd4f0a087e3cd + + - it: should create a Deployment with a custom tag if `controller.image.tag` is set + set: + controller.image.tag: custom-tag + controller.image.digest: sha256:faa2d18687f734994b6bd9e309e7a73852a81c30e1b8f63165fcd4f0a087e3cd + asserts: + - equal: + path: spec.template.spec.containers[0].image + value: registry.k8s.io/ingress-nginx/controller:custom-tag@sha256:faa2d18687f734994b6bd9e309e7a73852a81c30e1b8f63165fcd4f0a087e3cd diff --git a/backing-services/ingress-nginx/tests/controller-hpa_test.yaml b/backing-services/ingress-nginx/tests/controller-hpa_test.yaml new file mode 100644 index 0000000..869d3a6 --- /dev/null +++ b/backing-services/ingress-nginx/tests/controller-hpa_test.yaml @@ -0,0 +1,31 @@ +suite: Controller > HPA +templates: + - controller-hpa.yaml + +tests: + - it: should create an HPA if `controller.autoscaling.enabled` is true + set: + controller.autoscaling.enabled: true + asserts: + - hasDocuments: + count: 1 + - isKind: + of: HorizontalPodAutoscaler + - equal: + path: metadata.name + value: RELEASE-NAME-ingress-nginx-controller + + - it: should not create an HPA if `controller.autoscaling.enabled` is true and `controller.keda.enabled` is true + set: + controller.autoscaling.enabled: true + controller.keda.enabled: true + asserts: + - hasDocuments: + count: 0 + + - it: should not create an HPA if `controller.kind` is "DaemonSet" + set: + controller.kind: DaemonSet + asserts: + - hasDocuments: + count: 0 diff --git a/backing-services/ingress-nginx/tests/controller-ingressclass-aliases_test.yaml b/backing-services/ingress-nginx/tests/controller-ingressclass-aliases_test.yaml new file mode 100644 index 0000000..9a4a576 --- /dev/null +++ b/backing-services/ingress-nginx/tests/controller-ingressclass-aliases_test.yaml @@ -0,0 +1,110 @@ +suite: Controller > IngressClass > Aliases +templates: + - controller-ingressclass-aliases.yaml + +tests: + - it: should not create IngressClass aliases + asserts: + - hasDocuments: + count: 0 + + - it: should create an IngressClass alias with name "nginx-alias" if `controller.ingressClassResource.aliases` is set + set: + controller.ingressClassResource.aliases: + - nginx-alias + asserts: + - hasDocuments: + count: 1 + - isKind: + of: IngressClass + - equal: + path: metadata.name + value: nginx-alias + + - it: should create an IngressClass alias without annotation `ingressclass.kubernetes.io/is-default-class` if `controller.ingressClassResource.default` is true + set: + controller.ingressClassResource.aliases: + - nginx-alias + controller.ingressClassResource.default: true + asserts: + - hasDocuments: + count: 1 + - isKind: + of: IngressClass + - equal: + path: metadata.name + value: nginx-alias + - notExists: + path: metadata.annotations["ingressclass.kubernetes.io/is-default-class"] + + - it: should create an IngressClass alias with annotations if `controller.ingressClassResource.annotations` is set + set: + controller.ingressClassResource.aliases: + - nginx-alias + controller.ingressClassResource.annotations: + my-fancy-annotation: has-a-value + asserts: + - hasDocuments: + count: 1 + - isKind: + of: IngressClass + - equal: + path: metadata.name + value: nginx-alias + - equal: + path: metadata.annotations.my-fancy-annotation + value: has-a-value + + - it: should create an IngressClass alias with controller "k8s.io/ingress-nginx-internal" if `controller.ingressClassResource.controllerValue` is "k8s.io/ingress-nginx-internal" + set: + controller.ingressClassResource.aliases: + - nginx-alias + controller.ingressClassResource.controllerValue: k8s.io/ingress-nginx-internal + asserts: + - hasDocuments: + count: 1 + - isKind: + of: IngressClass + - equal: + path: metadata.name + value: nginx-alias + - equal: + path: spec.controller + value: k8s.io/ingress-nginx-internal + + - it: should create an IngressClass alias with parameters if `controller.ingressClassResource.parameters` is set + set: + controller.ingressClassResource.aliases: + - nginx-alias + controller.ingressClassResource.parameters: + apiGroup: k8s.example.com + kind: IngressParameters + name: external-lb + asserts: + - hasDocuments: + count: 1 + - isKind: + of: IngressClass + - equal: + path: metadata.name + value: nginx-alias + - equal: + path: spec.parameters + value: + apiGroup: k8s.example.com + kind: IngressParameters + name: external-lb + + - it: should create two IngressClass aliases if `controller.ingressClassResource.aliases` has two elements + set: + controller.ingressClassResource.aliases: + - nginx-alias-1 + - nginx-alias-2 + asserts: + - hasDocuments: + count: 2 + - isKind: + of: IngressClass + - matchRegex: + path: metadata.name + pattern: nginx-alias-(1|2) diff --git a/backing-services/ingress-nginx/tests/controller-ingressclass_test.yaml b/backing-services/ingress-nginx/tests/controller-ingressclass_test.yaml new file mode 100644 index 0000000..b3384af --- /dev/null +++ b/backing-services/ingress-nginx/tests/controller-ingressclass_test.yaml @@ -0,0 +1,93 @@ +suite: Controller > IngressClass +templates: + - controller-ingressclass.yaml + +tests: + - it: should create an IngressClass + asserts: + - hasDocuments: + count: 1 + - isKind: + of: IngressClass + - equal: + path: metadata.name + value: nginx + + - it: should create an IngressClass with name "nginx-internal" if `controller.ingressClassResource.name` is "nginx-internal" + set: + controller.ingressClassResource.name: nginx-internal + asserts: + - hasDocuments: + count: 1 + - isKind: + of: IngressClass + - equal: + path: metadata.name + value: nginx-internal + + - it: "should create an IngressClass with annotation `ingressclass.kubernetes.io/is-default-class: \"true\"` if `controller.ingressClassResource.default` is true" + set: + controller.ingressClassResource.default: true + asserts: + - hasDocuments: + count: 1 + - isKind: + of: IngressClass + - equal: + path: metadata.name + value: nginx + - equal: + path: metadata.annotations["ingressclass.kubernetes.io/is-default-class"] + value: "true" + + - it: should create an IngressClass with annotations if `controller.ingressClassResource.annotations` is set + set: + controller.ingressClassResource.annotations: + my-fancy-annotation: has-a-value + asserts: + - hasDocuments: + count: 1 + - isKind: + of: IngressClass + - equal: + path: metadata.name + value: nginx + - equal: + path: metadata.annotations.my-fancy-annotation + value: has-a-value + + - it: should create an IngressClass with controller "k8s.io/ingress-nginx-internal" if `controller.ingressClassResource.controllerValue` is "k8s.io/ingress-nginx-internal" + set: + controller.ingressClassResource.controllerValue: k8s.io/ingress-nginx-internal + asserts: + - hasDocuments: + count: 1 + - isKind: + of: IngressClass + - equal: + path: metadata.name + value: nginx + - equal: + path: spec.controller + value: k8s.io/ingress-nginx-internal + + - it: should create an IngressClass with parameters if `controller.ingressClassResource.parameters` is set + set: + controller.ingressClassResource.parameters: + apiGroup: k8s.example.com + kind: IngressParameters + name: external-lb + asserts: + - hasDocuments: + count: 1 + - isKind: + of: IngressClass + - equal: + path: metadata.name + value: nginx + - equal: + path: spec.parameters + value: + apiGroup: k8s.example.com + kind: IngressParameters + name: external-lb diff --git a/backing-services/ingress-nginx/tests/controller-keda_test.yaml b/backing-services/ingress-nginx/tests/controller-keda_test.yaml new file mode 100644 index 0000000..8002834 --- /dev/null +++ b/backing-services/ingress-nginx/tests/controller-keda_test.yaml @@ -0,0 +1,31 @@ +suite: Controller > KEDA +templates: + - controller-keda.yaml + +tests: + - it: should create a ScaledObject if `controller.keda.enabled` is true + set: + controller.keda.enabled: true + asserts: + - hasDocuments: + count: 1 + - isKind: + of: ScaledObject + - equal: + path: metadata.name + value: RELEASE-NAME-ingress-nginx-controller + + - it: should not create a ScaledObject if `controller.keda.enabled` is true and `controller.autoscaling.enabled` is true + set: + controller.keda.enabled: true + controller.autoscaling.enabled: true + asserts: + - hasDocuments: + count: 0 + + - it: should not create a ScaledObject if `controller.kind` is "DaemonSet" + set: + controller.kind: DaemonSet + asserts: + - hasDocuments: + count: 0 diff --git a/backing-services/ingress-nginx/tests/controller-networkpolicy_test.yaml b/backing-services/ingress-nginx/tests/controller-networkpolicy_test.yaml new file mode 100644 index 0000000..5de12e9 --- /dev/null +++ b/backing-services/ingress-nginx/tests/controller-networkpolicy_test.yaml @@ -0,0 +1,23 @@ +suite: Controller > NetworkPolicy +templates: + - controller-networkpolicy.yaml + +tests: + - it: should not create a NetworkPolicy if `controller.networkPolicy.enabled` is false + set: + controller.networkPolicy.enabled: false + asserts: + - hasDocuments: + count: 0 + + - it: should create a NetworkPolicy if `controller.networkPolicy.enabled` is true + set: + controller.networkPolicy.enabled: true + asserts: + - hasDocuments: + count: 1 + - isKind: + of: NetworkPolicy + - equal: + path: metadata.name + value: RELEASE-NAME-ingress-nginx-controller diff --git a/backing-services/ingress-nginx/tests/controller-poddisruptionbudget_test.yaml b/backing-services/ingress-nginx/tests/controller-poddisruptionbudget_test.yaml new file mode 100644 index 0000000..f215f35 --- /dev/null +++ b/backing-services/ingress-nginx/tests/controller-poddisruptionbudget_test.yaml @@ -0,0 +1,89 @@ +suite: Controller > PodDisruptionBudget +templates: + - controller-poddisruptionbudget.yaml + +tests: + - it: should create a PodDisruptionBudget if `controller.replicaCount` is greater than 1 + set: + controller.replicaCount: 2 + asserts: + - hasDocuments: + count: 1 + - isKind: + of: PodDisruptionBudget + - equal: + path: metadata.name + value: RELEASE-NAME-ingress-nginx-controller + + - it: should not create a PodDisruptionBudget if `controller.replicaCount` is less than or equal 1 + set: + controller.replicaCount: 1 + asserts: + - hasDocuments: + count: 0 + + - it: should create a PodDisruptionBudget if `controller.autoscaling.enabled` is true and `controller.autoscaling.minReplicas` is greater than 1 + set: + controller.autoscaling.enabled: true + controller.autoscaling.minReplicas: 2 + asserts: + - hasDocuments: + count: 1 + - isKind: + of: PodDisruptionBudget + - equal: + path: metadata.name + value: RELEASE-NAME-ingress-nginx-controller + + - it: should not create a PodDisruptionBudget if `controller.autoscaling.enabled` is true and `controller.autoscaling.minReplicas` is less than or equal 1 + set: + controller.autoscaling.enabled: true + controller.autoscaling.minReplicas: 1 + asserts: + - hasDocuments: + count: 0 + + - it: should create a PodDisruptionBudget if `controller.keda.enabled` is true and `controller.keda.minReplicas` is greater than 1 + set: + controller.keda.enabled: true + controller.keda.minReplicas: 2 + asserts: + - hasDocuments: + count: 1 + - isKind: + of: PodDisruptionBudget + - equal: + path: metadata.name + value: RELEASE-NAME-ingress-nginx-controller + + - it: should not create a PodDisruptionBudget if `controller.keda.enabled` is true and `controller.keda.minReplicas` is less than or equal 1 + set: + controller.keda.enabled: true + controller.keda.minReplicas: 1 + asserts: + - hasDocuments: + count: 0 + + - it: should not create a PodDisruptionBudget if `controller.autoscaling.enabled` is true and `controller.keda.enabled` is true + set: + controller.autoscaling.enabled: true + controller.keda.enabled: true + asserts: + - hasDocuments: + count: 0 + + - it: should create a PodDisruptionBudget without `minAvailable` and with `maxUnavailable` if `controller.minAvailable` and `controller.maxUnavailable` are set + set: + controller.replicaCount: 2 + controller.minAvailable: 1 + controller.maxUnavailable: 1 + asserts: + - hasDocuments: + count: 1 + - isKind: + of: PodDisruptionBudget + - notExists: + path: spec.minAvailable + - equal: + path: spec.maxUnavailable + value: 1 diff --git a/backing-services/ingress-nginx/tests/controller-prometheusrule_test.yaml b/backing-services/ingress-nginx/tests/controller-prometheusrule_test.yaml new file mode 100644 index 0000000..d60a983 --- /dev/null +++ b/backing-services/ingress-nginx/tests/controller-prometheusrule_test.yaml @@ -0,0 +1,17 @@ +suite: Controller > PrometheusRule +templates: + - controller-prometheusrule.yaml + +tests: + - it: should create a PrometheusRule if `controller.metrics.prometheusRule.enabled` is true + set: + controller.metrics.enabled: true + controller.metrics.prometheusRule.enabled: true + asserts: + - hasDocuments: + count: 1 + - isKind: + of: PrometheusRule + - equal: + path: metadata.name + value: RELEASE-NAME-ingress-nginx-controller diff --git a/backing-services/ingress-nginx/tests/controller-service-internal_test.yaml b/backing-services/ingress-nginx/tests/controller-service-internal_test.yaml new file mode 100644 index 0000000..5465e1a --- /dev/null +++ b/backing-services/ingress-nginx/tests/controller-service-internal_test.yaml @@ -0,0 +1,25 @@ +suite: Controller > Service > Internal +templates: + - controller-service-internal.yaml + +tests: + - it: should not create an internal Service if `controller.service.internal.enabled` is false + set: + controller.service.internal.enabled: false + asserts: + - hasDocuments: + count: 0 + + - it: should create an internal Service if `controller.service.internal.enabled` is true and `controller.service.internal.annotations` are set + set: + controller.service.internal.enabled: true + controller.service.internal.annotations: + test.annotation: "true" + asserts: + - hasDocuments: + count: 1 + - isKind: + of: Service + - equal: + path: metadata.name + value: RELEASE-NAME-ingress-nginx-controller-internal diff --git a/backing-services/ingress-nginx/tests/controller-service-metrics_test.yaml b/backing-services/ingress-nginx/tests/controller-service-metrics_test.yaml new file mode 100644 index 0000000..afdb940 --- /dev/null +++ b/backing-services/ingress-nginx/tests/controller-service-metrics_test.yaml @@ -0,0 +1,23 @@ +suite: Controller > Service > Metrics +templates: + - controller-service-metrics.yaml + +tests: + - it: should not create a metrics Service if `controller.metrics.enabled` is false + set: + controller.metrics.enabled: false + asserts: + - hasDocuments: + count: 0 + + - it: should create a metrics Service if `controller.metrics.enabled` is true + set: + controller.metrics.enabled: true + asserts: + - hasDocuments: + count: 1 + - isKind: + of: Service + - equal: + path: metadata.name + value: RELEASE-NAME-ingress-nginx-controller-metrics diff --git a/backing-services/ingress-nginx/tests/controller-service-webhook_test.yaml b/backing-services/ingress-nginx/tests/controller-service-webhook_test.yaml new file mode 100644 index 0000000..1c759ed --- /dev/null +++ b/backing-services/ingress-nginx/tests/controller-service-webhook_test.yaml @@ -0,0 +1,32 @@ +suite: Controller > Service > Webhook +templates: + - controller-service-webhook.yaml + +tests: + - it: should not create a webhook Service if `controller.admissionWebhooks.enabled` is false + set: + controller.admissionWebhooks.enabled: false + asserts: + - hasDocuments: + count: 0 + + - it: should create a webhook Service if `controller.admissionWebhooks.enabled` is true + set: + controller.admissionWebhooks.enabled: true + asserts: + - hasDocuments: + count: 1 + - isKind: + of: Service + - equal: + path: metadata.name + value: RELEASE-NAME-ingress-nginx-controller-admission + + - it: should create a webhook Service with a custom port if `controller.admissionWebhooks.service.servicePort` is set + set: + controller.admissionWebhooks.enabled: true + controller.admissionWebhooks.service.servicePort: 9443 + asserts: + - equal: + path: spec.ports[0].port + value: 9443 diff --git a/backing-services/ingress-nginx/tests/controller-service_test.yaml b/backing-services/ingress-nginx/tests/controller-service_test.yaml new file mode 100644 index 0000000..10574f2 --- /dev/null +++ b/backing-services/ingress-nginx/tests/controller-service_test.yaml @@ -0,0 +1,32 @@ +suite: Controller > Service +templates: + - controller-service.yaml + +tests: + - it: should not create a Service if `controller.service.external.enabled` is false + set: + controller.service.external.enabled: false + asserts: + - hasDocuments: + count: 0 + + - it: should create a Service if `controller.service.external.enabled` is true + set: + controller.service.external.enabled: true + asserts: + - hasDocuments: + count: 1 + - isKind: + of: Service + - equal: + path: metadata.name + value: RELEASE-NAME-ingress-nginx-controller + + - it: should create a Service of type "NodePort" if `controller.service.external.enabled` is true and `controller.service.type` is "NodePort" + set: + controller.service.external.enabled: true + controller.service.type: NodePort + asserts: + - equal: + path: spec.type + value: NodePort diff --git a/backing-services/ingress-nginx/tests/controller-servicemonitor_test.yaml b/backing-services/ingress-nginx/tests/controller-servicemonitor_test.yaml new file mode 100644 index 0000000..310097c --- /dev/null +++ b/backing-services/ingress-nginx/tests/controller-servicemonitor_test.yaml @@ -0,0 +1,29 @@ +suite: Controller > ServiceMonitor +templates: + - controller-servicemonitor.yaml + +tests: + - it: should create a ServiceMonitor if `controller.metrics.serviceMonitor.enabled` is true + set: + controller.metrics.enabled: true + controller.metrics.serviceMonitor.enabled: true + asserts: + - hasDocuments: + count: 1 + - isKind: + of: ServiceMonitor + - equal: + path: metadata.name + value: RELEASE-NAME-ingress-nginx-controller + + - it: should create a ServiceMonitor with annotations if `controller.metrics.serviceMonitor.annotations` is set + set: + controller.metrics.enabled: true + controller.metrics.serviceMonitor.enabled: true + controller.metrics.serviceMonitor.annotations: + my-little-annotation: test-value + asserts: + - equal: + path: metadata.annotations + value: + my-little-annotation: test-value diff --git a/backing-services/ingress-nginx/tests/default-backend-deployment_test.yaml b/backing-services/ingress-nginx/tests/default-backend-deployment_test.yaml new file mode 100644 index 0000000..4ba4b03 --- /dev/null +++ b/backing-services/ingress-nginx/tests/default-backend-deployment_test.yaml @@ -0,0 +1,169 @@ +suite: Default Backend > Deployment +templates: + - default-backend-deployment.yaml + +tests: + - it: should not create a Deployment if `defaultBackend.enabled` is false + set: + defaultBackend.enabled: false + asserts: + - hasDocuments: + count: 0 + + - it: should create a Deployment if `defaultBackend.enabled` is true + set: + defaultBackend.enabled: true + asserts: + - hasDocuments: + count: 1 + - isKind: + of: Deployment + - equal: + path: metadata.name + value: RELEASE-NAME-ingress-nginx-defaultbackend + + - it: should create a Deployment with 3 replicas if `defaultBackend.replicaCount` is 3 + set: + defaultBackend.enabled: true + defaultBackend.replicaCount: 3 + asserts: + - equal: + path: spec.replicas + value: 3 + + - it: should create a Deployment without replicas if `defaultBackend.autoscaling.enabled` is true + set: + defaultBackend.enabled: true + defaultBackend.autoscaling.enabled: true + asserts: + - notExists: + path: spec.replicas + + - it: should create a Deployment with resource limits if `defaultBackend.resources.limits` is set + set: + defaultBackend.enabled: true + defaultBackend.resources.limits.cpu: 500m + defaultBackend.resources.limits.memory: 512Mi + asserts: + - equal: + path: spec.template.spec.containers[0].resources.limits.cpu + value: 500m + - equal: + path: spec.template.spec.containers[0].resources.limits.memory + value: 512Mi + + - it: should create a Deployment with topology spread constraints if `defaultBackend.topologySpreadConstraints` is set + set: + defaultBackend.enabled: true + defaultBackend.topologySpreadConstraints: + - labelSelector: + matchLabels: + app.kubernetes.io/name: '{{ include "ingress-nginx.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + app.kubernetes.io/component: default-backend + topologyKey: topology.kubernetes.io/zone + maxSkew: 1 + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app.kubernetes.io/name: '{{ include "ingress-nginx.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + app.kubernetes.io/component: default-backend + topologyKey: kubernetes.io/hostname + maxSkew: 1 + whenUnsatisfiable: ScheduleAnyway + asserts: + - equal: + path: spec.template.spec.topologySpreadConstraints + value: + - labelSelector: + matchLabels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/component: default-backend + topologyKey: topology.kubernetes.io/zone + maxSkew: 1 + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/component: default-backend + topologyKey: kubernetes.io/hostname + maxSkew: 1 + whenUnsatisfiable: ScheduleAnyway + + - it: should create a Deployment with affinity if `defaultBackend.affinity` is set + set: + defaultBackend.enabled: true + defaultBackend.affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - '{{ include "ingress-nginx.name" . }}' + - key: app.kubernetes.io/instance + operator: In + values: + - '{{ .Release.Name }}' + - key: app.kubernetes.io/component + operator: In + values: + - default-backend + topologyKey: kubernetes.io/hostname + asserts: + - equal: + path: spec.template.spec.affinity + value: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - ingress-nginx + - key: app.kubernetes.io/instance + operator: In + values: + - RELEASE-NAME + - key: app.kubernetes.io/component + operator: In + values: + - default-backend + topologyKey: kubernetes.io/hostname + + - it: should create a Deployment with a custom registry if `defaultBackend.image.registry` is set + set: + defaultBackend.enabled: true + defaultBackend.image.registry: custom.registry.io + defaultBackend.image.tag: v1.0.0-dev + defaultBackend.image.digest: sha256:faa2d18687f734994b6bd9e309e7a73852a81c30e1b8f63165fcd4f0a087e3cd + asserts: + - equal: + path: spec.template.spec.containers[0].image + value: custom.registry.io/defaultbackend-amd64:v1.0.0-dev@sha256:faa2d18687f734994b6bd9e309e7a73852a81c30e1b8f63165fcd4f0a087e3cd + + - it: should create a Deployment with a custom image if `defaultBackend.image.image` is set + set: + defaultBackend.enabled: true + defaultBackend.image.image: custom-repo/custom-image + defaultBackend.image.tag: v1.0.0-dev + defaultBackend.image.digest: sha256:faa2d18687f734994b6bd9e309e7a73852a81c30e1b8f63165fcd4f0a087e3cd + asserts: + - equal: + path: spec.template.spec.containers[0].image + value: registry.k8s.io/custom-repo/custom-image:v1.0.0-dev@sha256:faa2d18687f734994b6bd9e309e7a73852a81c30e1b8f63165fcd4f0a087e3cd + + - it: should create a Deployment with a custom tag if `defaultBackend.image.tag` is set + set: + defaultBackend.enabled: true + defaultBackend.image.tag: custom-tag + defaultBackend.image.digest: sha256:faa2d18687f734994b6bd9e309e7a73852a81c30e1b8f63165fcd4f0a087e3cd + asserts: + - equal: + path: spec.template.spec.containers[0].image + value: registry.k8s.io/defaultbackend-amd64:custom-tag@sha256:faa2d18687f734994b6bd9e309e7a73852a81c30e1b8f63165fcd4f0a087e3cd diff --git a/backing-services/ingress-nginx/tests/default-backend-extra-configmaps_test.yaml b/backing-services/ingress-nginx/tests/default-backend-extra-configmaps_test.yaml new file mode 100644 index 0000000..aa600e7 --- /dev/null +++ b/backing-services/ingress-nginx/tests/default-backend-extra-configmaps_test.yaml @@ -0,0 +1,50 @@ +suite: Default Backend > Extra ConfigMaps +templates: + - default-backend-extra-configmaps.yaml + +tests: + - it: should not create a ConfigMap if `defaultBackend.extraConfigMaps` is empty + set: + defaultBackend.enabled: true + defaultBackend.extraConfigMaps: [] + asserts: + - hasDocuments: + count: 0 + + - it: should create one ConfigMap if `defaultBackend.extraConfigMaps` has one element + set: + defaultBackend.enabled: true + defaultBackend.extraConfigMaps: + - name: my-configmap-1 + data: + key1: value1 + asserts: + - hasDocuments: + count: 1 + - isKind: + of: ConfigMap + - equal: + path: metadata.name + value: my-configmap-1 + - equal: + path: data.key1 + value: value1 + + - it: should create two ConfigMaps if `defaultBackend.extraConfigMaps` has two elements + set: + defaultBackend.enabled: true + defaultBackend.extraConfigMaps: + - name: my-configmap-1 + data: + key1: value1 + - name: my-configmap-2 + data: + key2: value2 + asserts: + - hasDocuments: + count: 2 + - isKind: + of: ConfigMap + - matchRegex: + path: metadata.name + pattern: my-configmap-(1|2) diff --git a/backing-services/ingress-nginx/tests/default-backend-poddisruptionbudget_test.yaml b/backing-services/ingress-nginx/tests/default-backend-poddisruptionbudget_test.yaml new file mode 100644 index 0000000..0958018 --- /dev/null +++ b/backing-services/ingress-nginx/tests/default-backend-poddisruptionbudget_test.yaml @@ -0,0 +1,48 @@ +suite: Default Backend > PodDisruptionBudget +templates: + - default-backend-poddisruptionbudget.yaml + +tests: + - it: should create a PodDisruptionBudget if `defaultBackend.replicaCount` is greater than 1 + set: + defaultBackend.enabled: true + defaultBackend.replicaCount: 2 + asserts: + - hasDocuments: + count: 1 + - isKind: + of: PodDisruptionBudget + - equal: + path: metadata.name + value: RELEASE-NAME-ingress-nginx-defaultbackend + + - it: should not create a PodDisruptionBudget if `defaultBackend.replicaCount` is less than or equal 1 + set: + defaultBackend.enabled: true + defaultBackend.replicaCount: 1 + asserts: + - hasDocuments: + count: 0 + + - it: should create a PodDisruptionBudget if `defaultBackend.autoscaling.enabled` is true and `defaultBackend.autoscaling.minReplicas` is greater than 1 + set: + defaultBackend.enabled: true + defaultBackend.autoscaling.enabled: true + defaultBackend.autoscaling.minReplicas: 2 + asserts: + - hasDocuments: + count: 1 + - isKind: + of: PodDisruptionBudget + - equal: + path: metadata.name + value: RELEASE-NAME-ingress-nginx-defaultbackend + + - it: should not create a PodDisruptionBudget if `defaultBackend.autoscaling.enabled` is true and `defaultBackend.autoscaling.minReplicas` is less than or equal 1 + set: + defaultBackend.enabled: true + defaultBackend.autoscaling.enabled: true + defaultBackend.autoscaling.minReplicas: 1 + asserts: + - hasDocuments: + count: 0 diff --git a/backing-services/ingress-nginx/tests/default-backend-service_test.yaml b/backing-services/ingress-nginx/tests/default-backend-service_test.yaml new file mode 100644 index 0000000..f16904f --- /dev/null +++ b/backing-services/ingress-nginx/tests/default-backend-service_test.yaml @@ -0,0 +1,32 @@ +suite: Default Backend > Service +templates: + - default-backend-service.yaml + +tests: + - it: should not create a Service if `defaultBackend.enabled` is false + set: + defaultBackend.enabled: false + asserts: + - hasDocuments: + count: 0 + + - it: should create a Service if `defaultBackend.enabled` is true + set: + defaultBackend.enabled: true + asserts: + - hasDocuments: + count: 1 + - isKind: + of: Service + - equal: + path: metadata.name + value: RELEASE-NAME-ingress-nginx-defaultbackend + + - it: should create a Service with port 80 if `defaultBackend.service.port` is 80 + set: + defaultBackend.enabled: true + defaultBackend.service.port: 80 + asserts: + - equal: + path: spec.ports[0].port + value: 80 diff --git a/backing-services/ingress-nginx/values.yaml b/backing-services/ingress-nginx/values.yaml new file mode 100644 index 0000000..0663823 --- /dev/null +++ b/backing-services/ingress-nginx/values.yaml @@ -0,0 +1,1193 @@ +## nginx configuration +## Ref: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/index.md +## + +## Overrides for generated resource names +# See templates/_helpers.tpl +# nameOverride: +# fullnameOverride: + +# -- Override the deployment namespace; defaults to .Release.Namespace +namespaceOverride: "" +## Labels to apply to all resources +## +commonLabels: {} +# scmhash: abc123 +# myLabel: aakkmd + +controller: + name: controller + enableAnnotationValidations: false + image: + ## Keep false as default for now! + chroot: false + registry: registry.k8s.io + image: ingress-nginx/controller + ## for backwards compatibility consider setting the full image url via the repository value below + ## use *either* current default registry/image or repository format or installing chart by providing the values.yaml will fail + ## repository: + tag: "v1.11.3" + digest: "" + digestChroot: "" + pullPolicy: IfNotPresent + runAsNonRoot: true + # www-data -> uid 101 + runAsUser: 101 + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + readOnlyRootFilesystem: false + # -- Use an existing PSP instead of creating one + existingPsp: "" + # -- Configures the controller container name + containerName: controller + # -- Configures the ports that the nginx-controller listens on + containerPort: + http: 80 + https: 443 + # -- Global configuration passed to the ConfigMap consumed by the controller. Values may contain Helm templates. + # Ref.: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/ + config: {} + # -- Annotations to be added to the controller config configuration configmap. + configAnnotations: {} + # -- Will add custom headers before sending traffic to backends according to https://github.com/kubernetes/ingress-nginx/tree/main/docs/examples/customization/custom-headers + proxySetHeaders: {} + # -- Will add custom headers before sending response traffic to the client according to: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#add-headers + addHeaders: {} + # -- Optionally customize the pod dnsConfig. + dnsConfig: {} + # -- Optionally customize the pod hostAliases. + hostAliases: [] + # - ip: 127.0.0.1 + # hostnames: + # - foo.local + # - bar.local + # - ip: 10.1.2.3 + # hostnames: + # - foo.remote + # - bar.remote + # -- Optionally customize the pod hostname. + hostname: {} + # -- Optionally change this to ClusterFirstWithHostNet in case you have 'hostNetwork: true'. + # By default, while using host network, name resolution uses the host's DNS. If you wish nginx-controller + # to keep resolving names inside the k8s network, use ClusterFirstWithHostNet. + dnsPolicy: ClusterFirst + # -- Bare-metal considerations via the host network https://kubernetes.github.io/ingress-nginx/deploy/baremetal/#via-the-host-network + # Ingress status was blank because there is no Service exposing the Ingress-Nginx Controller in a configuration using the host network, the default --publish-service flag used in standard cloud setups does not apply + reportNodeInternalIp: false + # -- Process Ingress objects without ingressClass annotation/ingressClassName field + # Overrides value for --watch-ingress-without-class flag of the controller binary + # Defaults to false + watchIngressWithoutClass: false + # -- Process IngressClass per name (additionally as per spec.controller). + ingressClassByName: false + # -- This configuration enables Topology Aware Routing feature, used together with service annotation service.kubernetes.io/topology-mode="auto" + # Defaults to false + enableTopologyAwareRouting: false + # -- This configuration disable Nginx Controller Leader Election + disableLeaderElection: false + # -- Duration a leader election is valid before it's getting re-elected, e.g. `15s`, `10m` or `1h`. (Default: 30s) + electionTTL: "" + # -- This configuration defines if Ingress Controller should allow users to set + # their own *-snippet annotations, otherwise this is forbidden / dropped + # when users add those annotations. + # Global snippets in ConfigMap are still respected + allowSnippetAnnotations: false + # -- Required for use with CNI based kubernetes installations (such as ones set up by kubeadm), + # since CNI and hostport don't mix yet. Can be deprecated once https://github.com/kubernetes/kubernetes/issues/23920 + # is merged + hostNetwork: false + ## Use host ports 80 and 443 + ## Disabled by default + hostPort: + # -- Enable 'hostPort' or not + enabled: false + ports: + # -- 'hostPort' http port + http: 80 + # -- 'hostPort' https port + https: 443 + # NetworkPolicy for controller component. + networkPolicy: + # -- Enable 'networkPolicy' or not + enabled: false + # -- Election ID to use for status update, by default it uses the controller name combined with a suffix of 'leader' + electionID: "" + # -- This section refers to the creation of the IngressClass resource. + # IngressClasses are immutable and cannot be changed after creation. + # We do not support namespaced IngressClasses, yet, so a ClusterRole and a ClusterRoleBinding is required. + ingressClassResource: + # -- Name of the IngressClass + name: nginx + # -- Create the IngressClass or not + enabled: true + # -- If true, Ingresses without `ingressClassName` get assigned to this IngressClass on creation. + # Ingress creation gets rejected if there are multiple default IngressClasses. + # Ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#default-ingress-class + default: false + # -- Annotations to be added to the IngressClass resource. + annotations: {} + # -- Controller of the IngressClass. An Ingress Controller looks for IngressClasses it should reconcile by this value. + # This value is also being set as the `--controller-class` argument of this Ingress Controller. + # Ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class + controllerValue: k8s.io/ingress-nginx + # -- Aliases of this IngressClass. Creates copies with identical settings but the respective alias as name. + # Useful for development environments with only one Ingress Controller but production-like Ingress resources. + # `default` gets enabled on the original IngressClass only. + aliases: [] + # aliases: + # - nginx-alias-1 + # - nginx-alias-2 + # -- A link to a custom resource containing additional configuration for the controller. + # This is optional if the controller consuming this IngressClass does not require additional parameters. + # Ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class + parameters: {} + # parameters: + # apiGroup: k8s.example.com + # kind: IngressParameters + # name: external-lb + # -- For backwards compatibility with ingress.class annotation, use ingressClass. + # Algorithm is as follows, first ingressClassName is considered, if not present, controller looks for ingress.class annotation + ingressClass: nginx + # -- Labels to add to the pod container metadata + podLabels: {} + # key: value + + # -- Security context for controller pods + podSecurityContext: {} + # -- sysctls for controller pods + ## Ref: https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/ + sysctls: {} + # sysctls: + # "net.core.somaxconn": "8192" + # -- Security context for controller containers + containerSecurityContext: {} + # -- Allows customization of the source of the IP address or FQDN to report + # in the ingress status field. By default, it reads the information provided + # by the service. If disable, the status field reports the IP address of the + # node or nodes where an ingress controller pod is running. + publishService: + # -- Enable 'publishService' or not + enabled: true + # -- Allows overriding of the publish service to bind to + # Must be / + pathOverride: "" + # Limit the scope of the controller to a specific namespace + scope: + # -- Enable 'scope' or not + enabled: false + # -- Namespace to limit the controller to; defaults to $(POD_NAMESPACE) + namespace: "" + # -- When scope.enabled == false, instead of watching all namespaces, we watching namespaces whose labels + # only match with namespaceSelector. Format like foo=bar. Defaults to empty, means watching all namespaces. + namespaceSelector: "" + # -- Allows customization of the configmap / nginx-configmap namespace; defaults to $(POD_NAMESPACE) + configMapNamespace: "" + tcp: + # -- Allows customization of the tcp-services-configmap; defaults to $(POD_NAMESPACE) + configMapNamespace: "" + # -- Annotations to be added to the tcp config configmap + annotations: {} + udp: + # -- Allows customization of the udp-services-configmap; defaults to $(POD_NAMESPACE) + configMapNamespace: "" + # -- Annotations to be added to the udp config configmap + annotations: {} + # -- Maxmind license key to download GeoLite2 Databases. + ## https://blog.maxmind.com/2019/12/significant-changes-to-accessing-and-using-geolite2-databases/ + maxmindLicenseKey: "" + # -- Additional command line arguments to pass to Ingress-Nginx Controller + # E.g. to specify the default SSL certificate you can use + extraArgs: + enable-ssl-passthrough: "true" + ## extraArgs: + ## default-ssl-certificate: "/" + ## time-buckets: "0.005,0.01,0.025,0.05,0.1,0.25,0.5,1,2.5,5,10" + ## length-buckets: "10,20,30,40,50,60,70,80,90,100" + ## size-buckets: "10,100,1000,10000,100000,1e+06,1e+07" + + # -- Additional environment variables to set + extraEnvs: [] + # extraEnvs: + # - name: FOO + # valueFrom: + # secretKeyRef: + # key: FOO + # name: secret-resource + + # -- Use a `DaemonSet` or `Deployment` + kind: Deployment + # -- Annotations to be added to the controller Deployment or DaemonSet + ## + annotations: {} + # keel.sh/pollSchedule: "@every 60m" + + # -- Labels to be added to the controller Deployment or DaemonSet and other resources that do not have option to specify labels + ## + labels: {} + # keel.sh/policy: patch + # keel.sh/trigger: poll + + # -- The update strategy to apply to the Deployment or DaemonSet + ## + updateStrategy: {} + # rollingUpdate: + # maxUnavailable: 1 + # type: RollingUpdate + + # -- `minReadySeconds` to avoid killing pods before we are ready + ## + minReadySeconds: 0 + # -- Node tolerations for server scheduling to nodes with taints + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + ## + tolerations: [] + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + # -- Affinity and anti-affinity rules for server scheduling to nodes + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## + affinity: {} + # # An example of preferred pod anti-affinity, weight is in the range 1-100 + # podAntiAffinity: + # preferredDuringSchedulingIgnoredDuringExecution: + # - weight: 100 + # podAffinityTerm: + # labelSelector: + # matchExpressions: + # - key: app.kubernetes.io/name + # operator: In + # values: + # - '{{ include "ingress-nginx.name" . }}' + # - key: app.kubernetes.io/instance + # operator: In + # values: + # - '{{ .Release.Name }}' + # - key: app.kubernetes.io/component + # operator: In + # values: + # - controller + # topologyKey: kubernetes.io/hostname + + # # An example of required pod anti-affinity + # podAntiAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # - labelSelector: + # matchExpressions: + # - key: app.kubernetes.io/name + # operator: In + # values: + # - '{{ include "ingress-nginx.name" . }}' + # - key: app.kubernetes.io/instance + # operator: In + # values: + # - '{{ .Release.Name }}' + # - key: app.kubernetes.io/component + # operator: In + # values: + # - controller + # topologyKey: kubernetes.io/hostname + + # -- Topology spread constraints rely on node labels to identify the topology domain(s) that each Node is in. + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## + topologySpreadConstraints: [] + # - labelSelector: + # matchLabels: + # app.kubernetes.io/name: '{{ include "ingress-nginx.name" . }}' + # app.kubernetes.io/instance: '{{ .Release.Name }}' + # app.kubernetes.io/component: controller + # topologyKey: topology.kubernetes.io/zone + # maxSkew: 1 + # whenUnsatisfiable: ScheduleAnyway + # - labelSelector: + # matchLabels: + # app.kubernetes.io/name: '{{ include "ingress-nginx.name" . }}' + # app.kubernetes.io/instance: '{{ .Release.Name }}' + # app.kubernetes.io/component: controller + # topologyKey: kubernetes.io/hostname + # maxSkew: 1 + # whenUnsatisfiable: ScheduleAnyway + + # -- `terminationGracePeriodSeconds` to avoid killing pods before we are ready + ## wait up to five minutes for the drain of connections + ## + terminationGracePeriodSeconds: 300 + # -- Node labels for controller pod assignment + ## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: + kubernetes.io/os: linux + ## Liveness and readiness probe values + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## + ## startupProbe: + ## httpGet: + ## # should match container.healthCheckPath + ## path: "/healthz" + ## port: 10254 + ## scheme: HTTP + ## initialDelaySeconds: 5 + ## periodSeconds: 5 + ## timeoutSeconds: 2 + ## successThreshold: 1 + ## failureThreshold: 5 + livenessProbe: + httpGet: + # should match container.healthCheckPath + path: "/healthz" + port: 10254 + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 5 + readinessProbe: + httpGet: + # should match container.healthCheckPath + path: "/healthz" + port: 10254 + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 3 + # -- Path of the health check endpoint. All requests received on the port defined by + # the healthz-port parameter are forwarded internally to this path. + healthCheckPath: "/healthz" + # -- Address to bind the health check endpoint. + # It is better to set this option to the internal node address + # if the Ingress-Nginx Controller is running in the `hostNetwork: true` mode. + healthCheckHost: "" + # -- Annotations to be added to controller pods + ## + podAnnotations: {} + replicaCount: 1 + # -- Minimum available pods set in PodDisruptionBudget. + # Define either 'minAvailable' or 'maxUnavailable', never both. + minAvailable: 1 + # -- Maximum unavailable pods set in PodDisruptionBudget. If set, 'minAvailable' is ignored. + # maxUnavailable: 1 + + ## Define requests resources to avoid probe issues due to CPU utilization in busy nodes + ## ref: https://github.com/kubernetes/ingress-nginx/issues/4735#issuecomment-551204903 + ## Ideally, there should be no limits. + ## https://engineering.indeedblog.com/blog/2019/12/cpu-throttling-regression-fix/ + resources: + ## limits: + ## cpu: 100m + ## memory: 90Mi + requests: + cpu: 100m + memory: 90Mi + # Mutually exclusive with keda autoscaling + autoscaling: + enabled: false + annotations: {} + minReplicas: 1 + maxReplicas: 11 + targetCPUUtilizationPercentage: 50 + targetMemoryUtilizationPercentage: 50 + behavior: {} + # scaleDown: + # stabilizationWindowSeconds: 300 + # policies: + # - type: Pods + # value: 1 + # periodSeconds: 180 + # scaleUp: + # stabilizationWindowSeconds: 300 + # policies: + # - type: Pods + # value: 2 + # periodSeconds: 60 + autoscalingTemplate: [] + # Custom or additional autoscaling metrics + # ref: https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#support-for-custom-metrics + # - type: Pods + # pods: + # metric: + # name: nginx_ingress_controller_nginx_process_requests_total + # target: + # type: AverageValue + # averageValue: 10000m + + # Mutually exclusive with hpa autoscaling + keda: + apiVersion: "keda.sh/v1alpha1" + ## apiVersion changes with keda 1.x vs 2.x + ## 2.x = keda.sh/v1alpha1 + ## 1.x = keda.k8s.io/v1alpha1 + enabled: false + minReplicas: 1 + maxReplicas: 11 + pollingInterval: 30 + cooldownPeriod: 300 + # fallback: + # failureThreshold: 3 + # replicas: 11 + restoreToOriginalReplicaCount: false + scaledObject: + annotations: {} + # Custom annotations for ScaledObject resource + # annotations: + # key: value + triggers: [] + # - type: prometheus + # metadata: + # serverAddress: http://:9090 + # metricName: http_requests_total + # threshold: '100' + # query: sum(rate(http_requests_total{deployment="my-deployment"}[2m])) + + behavior: {} + # scaleDown: + # stabilizationWindowSeconds: 300 + # policies: + # - type: Pods + # value: 1 + # periodSeconds: 180 + # scaleUp: + # stabilizationWindowSeconds: 300 + # policies: + # - type: Pods + # value: 2 + # periodSeconds: 60 + # -- Enable mimalloc as a drop-in replacement for malloc. + ## ref: https://github.com/microsoft/mimalloc + ## + enableMimalloc: true + ## Override NGINX template + customTemplate: + configMapName: "" + configMapKey: "" + service: + # -- Enable controller services or not. This does not influence the creation of either the admission webhook or the metrics service. + enabled: true + external: + # -- Enable the external controller service or not. Useful for internal-only deployments. + enabled: true + # -- Annotations to be added to the external controller service. See `controller.service.internal.annotations` for annotations to be added to the internal controller service. + annotations: {} + # -- Labels to be added to both controller services. + labels: {} + # -- Type of the external controller service. + # Ref: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types + type: LoadBalancer + # -- Pre-defined cluster internal IP address of the external controller service. Take care of collisions with existing services. + # This value is immutable. Set once, it can not be changed without deleting and re-creating the service. + # Ref: https://kubernetes.io/docs/concepts/services-networking/service/#choosing-your-own-ip-address + clusterIP: "" + # -- List of node IP addresses at which the external controller service is available. + # Ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips + externalIPs: [] + # -- Deprecated: Pre-defined IP address of the external controller service. Used by cloud providers to connect the resulting load balancer service to a pre-existing static IP. + # Ref: https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer + loadBalancerIP: "" + # -- Restrict access to the external controller service. Values must be CIDRs. Allows any source address by default. + loadBalancerSourceRanges: [] + # -- Load balancer class of the external controller service. Used by cloud providers to select a load balancer implementation other than the cloud provider default. + # Ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + loadBalancerClass: "" + # -- Enable node port allocation for the external controller service or not. Applies to type `LoadBalancer` only. + # Ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-nodeport-allocation + # allocateLoadBalancerNodePorts: true + + # -- External traffic policy of the external controller service. Set to "Local" to preserve source IP on providers supporting it. + # Ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + externalTrafficPolicy: "" + # -- Session affinity of the external controller service. Must be either "None" or "ClientIP" if set. Defaults to "None". + # Ref: https://kubernetes.io/docs/reference/networking/virtual-ips/#session-affinity + sessionAffinity: "" + # -- Specifies the health check node port (numeric port number) for the external controller service. + # If not specified, the service controller allocates a port from your cluster's node port range. + # Ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + # healthCheckNodePort: 0 + + # -- Represents the dual-stack capabilities of the external controller service. Possible values are SingleStack, PreferDualStack or RequireDualStack. + # Fields `ipFamilies` and `clusterIP` depend on the value of this field. + # Ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services + ipFamilyPolicy: SingleStack + # -- List of IP families (e.g. IPv4, IPv6) assigned to the external controller service. This field is usually assigned automatically based on cluster configuration and the `ipFamilyPolicy` field. + # Ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services + ipFamilies: + - IPv4 + # -- Enable the HTTP listener on both controller services or not. + enableHttp: true + # -- Enable the HTTPS listener on both controller services or not. + enableHttps: true + ports: + # -- Port the external HTTP listener is published with. + http: 80 + # -- Port the external HTTPS listener is published with. + https: 443 + targetPorts: + # -- Port of the ingress controller the external HTTP listener is mapped to. + http: http + # -- Port of the ingress controller the external HTTPS listener is mapped to. + https: https + # -- Declare the app protocol of the external HTTP and HTTPS listeners or not. Supersedes provider-specific annotations for declaring the backend protocol. + # Ref: https://kubernetes.io/docs/concepts/services-networking/service/#application-protocol + appProtocol: true + nodePorts: + # -- Node port allocated for the external HTTP listener. If left empty, the service controller allocates one from the configured node port range. + http: "" + # -- Node port allocated for the external HTTPS listener. If left empty, the service controller allocates one from the configured node port range. + https: "" + # -- Node port mapping for external TCP listeners. If left empty, the service controller allocates them from the configured node port range. + # Example: + # tcp: + # 8080: 30080 + tcp: {} + # -- Node port mapping for external UDP listeners. If left empty, the service controller allocates them from the configured node port range. + # Example: + # udp: + # 53: 30053 + udp: {} + internal: + # -- Enable the internal controller service or not. Remember to configure `controller.service.internal.annotations` when enabling this. + enabled: false + # -- Annotations to be added to the internal controller service. Mandatory for the internal controller service to be created. Varies with the cloud service. + # Ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + annotations: {} + # -- Type of the internal controller service. + # Defaults to the value of `controller.service.type`. + # Ref: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types + type: "" + # -- Pre-defined cluster internal IP address of the internal controller service. Take care of collisions with existing services. + # This value is immutable. Set once, it can not be changed without deleting and re-creating the service. + # Ref: https://kubernetes.io/docs/concepts/services-networking/service/#choosing-your-own-ip-address + clusterIP: "" + # -- List of node IP addresses at which the internal controller service is available. + # Ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips + externalIPs: [] + # -- Deprecated: Pre-defined IP address of the internal controller service. Used by cloud providers to connect the resulting load balancer service to a pre-existing static IP. + # Ref: https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer + loadBalancerIP: "" + # -- Restrict access to the internal controller service. Values must be CIDRs. Allows any source address by default. + loadBalancerSourceRanges: [] + # -- Load balancer class of the internal controller service. Used by cloud providers to select a load balancer implementation other than the cloud provider default. + # Ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + loadBalancerClass: "" + # -- Enable node port allocation for the internal controller service or not. Applies to type `LoadBalancer` only. + # Ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-nodeport-allocation + # allocateLoadBalancerNodePorts: true + + # -- External traffic policy of the internal controller service. Set to "Local" to preserve source IP on providers supporting it. + # Ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + externalTrafficPolicy: "" + # -- Session affinity of the internal controller service. Must be either "None" or "ClientIP" if set. Defaults to "None". + # Ref: https://kubernetes.io/docs/reference/networking/virtual-ips/#session-affinity + sessionAffinity: "" + # -- Specifies the health check node port (numeric port number) for the internal controller service. + # If not specified, the service controller allocates a port from your cluster's node port range. + # Ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + # healthCheckNodePort: 0 + + # -- Represents the dual-stack capabilities of the internal controller service. Possible values are SingleStack, PreferDualStack or RequireDualStack. + # Fields `ipFamilies` and `clusterIP` depend on the value of this field. + # Ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services + ipFamilyPolicy: SingleStack + # -- List of IP families (e.g. IPv4, IPv6) assigned to the internal controller service. This field is usually assigned automatically based on cluster configuration and the `ipFamilyPolicy` field. + # Ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services + ipFamilies: + - IPv4 + ports: {} + # -- Port the internal HTTP listener is published with. + # Defaults to the value of `controller.service.ports.http`. + # http: 80 + # -- Port the internal HTTPS listener is published with. + # Defaults to the value of `controller.service.ports.https`. + # https: 443 + + targetPorts: {} + # -- Port of the ingress controller the internal HTTP listener is mapped to. + # Defaults to the value of `controller.service.targetPorts.http`. + # http: http + # -- Port of the ingress controller the internal HTTPS listener is mapped to. + # Defaults to the value of `controller.service.targetPorts.https`. + # https: https + + # -- Declare the app protocol of the internal HTTP and HTTPS listeners or not. Supersedes provider-specific annotations for declaring the backend protocol. + # Ref: https://kubernetes.io/docs/concepts/services-networking/service/#application-protocol + appProtocol: true + nodePorts: + # -- Node port allocated for the internal HTTP listener. If left empty, the service controller allocates one from the configured node port range. + http: "" + # -- Node port allocated for the internal HTTPS listener. If left empty, the service controller allocates one from the configured node port range. + https: "" + # -- Node port mapping for internal TCP listeners. If left empty, the service controller allocates them from the configured node port range. + # Example: + # tcp: + # 8080: 30080 + tcp: {} + # -- Node port mapping for internal UDP listeners. If left empty, the service controller allocates them from the configured node port range. + # Example: + # udp: + # 53: 30053 + udp: {} + # shareProcessNamespace enables process namespace sharing within the pod. + # This can be used for example to signal log rotation using `kill -USR1` from a sidecar. + shareProcessNamespace: false + # -- Additional containers to be added to the controller pod. + # See https://github.com/lemonldap-ng-controller/lemonldap-ng-controller as example. + extraContainers: [] + # - name: my-sidecar + # image: nginx:latest + # - name: lemonldap-ng-controller + # image: lemonldapng/lemonldap-ng-controller:0.2.0 + # args: + # - /lemonldap-ng-controller + # - --alsologtostderr + # - --configmap=$(POD_NAMESPACE)/lemonldap-ng-configuration + # env: + # - name: POD_NAME + # valueFrom: + # fieldRef: + # fieldPath: metadata.name + # - name: POD_NAMESPACE + # valueFrom: + # fieldRef: + # fieldPath: metadata.namespace + # volumeMounts: + # - name: copy-portal-skins + # mountPath: /srv/var/lib/lemonldap-ng/portal/skins + + # -- Additional volumeMounts to the controller main container. + extraVolumeMounts: [] + # - name: copy-portal-skins + # mountPath: /var/lib/lemonldap-ng/portal/skins + + # -- Additional volumes to the controller pod. + extraVolumes: [] + # - name: copy-portal-skins + # emptyDir: {} + + # -- Containers, which are run before the app containers are started. + extraInitContainers: [] + # - name: init-myservice + # image: busybox + # command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;'] + + # -- Modules, which are mounted into the core nginx image. See values.yaml for a sample to add opentelemetry module + extraModules: [] + # - name: mytestmodule + # image: + # registry: registry.k8s.io + # image: ingress-nginx/mytestmodule + # ## for backwards compatibility consider setting the full image url via the repository value below + # ## use *either* current default registry/image or repository format or installing chart by providing the values.yaml will fail + # ## repository: + # tag: "v1.0.0" + # digest: "" + # distroless: false + # containerSecurityContext: + # runAsNonRoot: true + # runAsUser: + # allowPrivilegeEscalation: false + # seccompProfile: + # type: RuntimeDefault + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # resources: {} + # + # The image must contain a `/usr/local/bin/init_module.sh` executable, which + # will be executed as initContainers, to move its config files within the + # mounted volume. + + opentelemetry: + enabled: false + name: opentelemetry + image: + registry: registry.k8s.io + image: ingress-nginx/opentelemetry-1.25.3 + ## for backwards compatibility consider setting the full image url via the repository value below + ## use *either* current default registry/image or repository format or installing chart by providing the values.yaml will fail + ## repository: + tag: v20240813-b933310d + digest: sha256:f7604ac0547ed64d79b98d92133234e66c2c8aade3c1f4809fed5eec1fb7f922 + distroless: true + containerSecurityContext: + runAsNonRoot: true + # -- The image's default user, inherited from its base image `cgr.dev/chainguard/static`. + runAsUser: 65532 + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + resources: {} + admissionWebhooks: + name: admission + annotations: {} + # ignore-check.kube-linter.io/no-read-only-rootfs: "This deployment needs write access to root filesystem". + + ## Additional annotations to the admission webhooks. + ## These annotations will be added to the ValidatingWebhookConfiguration and + ## the Jobs Spec of the admission webhooks. + enabled: true + # -- Additional environment variables to set + extraEnvs: [] + # extraEnvs: + # - name: FOO + # valueFrom: + # secretKeyRef: + # key: FOO + # name: secret-resource + # -- Admission Webhook failure policy to use + failurePolicy: Fail + # timeoutSeconds: 10 + port: 8443 + certificate: "/usr/local/certificates/cert" + key: "/usr/local/certificates/key" + namespaceSelector: {} + objectSelector: {} + # -- Labels to be added to admission webhooks + labels: {} + # -- Use an existing PSP instead of creating one + existingPsp: "" + service: + annotations: {} + # clusterIP: "" + externalIPs: [] + # loadBalancerIP: "" + loadBalancerSourceRanges: [] + servicePort: 443 + type: ClusterIP + createSecretJob: + name: create + # -- Security context for secret creation containers + securityContext: + runAsNonRoot: true + runAsUser: 65532 + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + resources: {} + # limits: + # cpu: 10m + # memory: 20Mi + # requests: + # cpu: 10m + # memory: 20Mi + patchWebhookJob: + name: patch + # -- Security context for webhook patch containers + securityContext: + runAsNonRoot: true + runAsUser: 65532 + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + resources: {} + patch: + enabled: true + image: + registry: registry.k8s.io + image: ingress-nginx/kube-webhook-certgen + ## for backwards compatibility consider setting the full image url via the repository value below + ## use *either* current default registry/image or repository format or installing chart by providing the values.yaml will fail + ## repository: + tag: v1.4.4 + digest: sha256:a9f03b34a3cbfbb26d103a14046ab2c5130a80c3d69d526ff8063d2b37b9fd3f + pullPolicy: IfNotPresent + # -- Provide a priority class name to the webhook patching job + ## + priorityClassName: "" + podAnnotations: {} + # NetworkPolicy for webhook patch + networkPolicy: + # -- Enable 'networkPolicy' or not + enabled: false + nodeSelector: + kubernetes.io/os: linux + tolerations: [] + # -- Labels to be added to patch job resources + labels: {} + # -- Security context for secret creation & webhook patch pods + securityContext: {} + # -- Admission webhook patch job RBAC + rbac: + # -- Create RBAC or not + create: true + # -- Admission webhook patch job service account + serviceAccount: + # -- Create a service account or not + create: true + # -- Custom service account name + name: "" + # -- Auto-mount service account token or not + automountServiceAccountToken: true + # Use certmanager to generate webhook certs + certManager: + enabled: false + # self-signed root certificate + rootCert: + # default to be 5y + duration: "" + admissionCert: + # default to be 1y + duration: "" + # issuerRef: + # name: "issuer" + # kind: "ClusterIssuer" + metrics: + port: 10254 + portName: metrics + # if this port is changed, change healthz-port: in extraArgs: accordingly + enabled: false + service: + annotations: {} + # prometheus.io/scrape: "true" + # prometheus.io/port: "10254" + # -- Labels to be added to the metrics service resource + labels: {} + # clusterIP: "" + + # -- List of IP addresses at which the stats-exporter service is available + ## Ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips + ## + externalIPs: [] + # loadBalancerIP: "" + loadBalancerSourceRanges: [] + servicePort: 10254 + type: ClusterIP + # externalTrafficPolicy: "" + # nodePort: "" + serviceMonitor: + enabled: false + additionalLabels: {} + # -- Annotations to be added to the ServiceMonitor. + annotations: {} + ## The label to use to retrieve the job name from. + ## jobLabel: "app.kubernetes.io/name" + namespace: "" + namespaceSelector: {} + ## Default: scrape .Release.Namespace or namespaceOverride only + ## To scrape all, use the following: + ## namespaceSelector: + ## any: true + scrapeInterval: 30s + # honorLabels: true + targetLabels: [] + relabelings: [] + metricRelabelings: [] + prometheusRule: + enabled: false + additionalLabels: {} + # namespace: "" + rules: [] + # # These are just examples rules, please adapt them to your needs + # - alert: NGINXConfigFailed + # expr: count(nginx_ingress_controller_config_last_reload_successful == 0) > 0 + # for: 1s + # labels: + # severity: critical + # annotations: + # description: bad ingress config - nginx config test failed + # summary: uninstall the latest ingress changes to allow config reloads to resume + # # By default a fake self-signed certificate is generated as default and + # # it is fine if it expires. If `--default-ssl-certificate` flag is used + # # and a valid certificate passed please do not filter for `host` label! + # # (i.e. delete `{host!="_"}` so also the default SSL certificate is + # # checked for expiration) + # - alert: NGINXCertificateExpiry + # expr: (avg(nginx_ingress_controller_ssl_expire_time_seconds{host!="_"}) by (host) - time()) < 604800 + # for: 1s + # labels: + # severity: critical + # annotations: + # description: ssl certificate(s) will expire in less then a week + # summary: renew expiring certificates to avoid downtime + # - alert: NGINXTooMany500s + # expr: 100 * ( sum( nginx_ingress_controller_requests{status=~"5.+"} ) / sum(nginx_ingress_controller_requests) ) > 5 + # for: 1m + # labels: + # severity: warning + # annotations: + # description: Too many 5XXs + # summary: More than 5% of all requests returned 5XX, this requires your attention + # - alert: NGINXTooMany400s + # expr: 100 * ( sum( nginx_ingress_controller_requests{status=~"4.+"} ) / sum(nginx_ingress_controller_requests) ) > 5 + # for: 1m + # labels: + # severity: warning + # annotations: + # description: Too many 4XXs + # summary: More than 5% of all requests returned 4XX, this requires your attention + # -- Improve connection draining when ingress controller pod is deleted using a lifecycle hook: + # With this new hook, we increased the default terminationGracePeriodSeconds from 30 seconds + # to 300, allowing the draining of connections up to five minutes. + # If the active connections end before that, the pod will terminate gracefully at that time. + # To effectively take advantage of this feature, the Configmap feature + # worker-shutdown-timeout new value is 240s instead of 10s. + ## + lifecycle: + preStop: + exec: + command: + - /wait-shutdown + priorityClassName: "" +# -- Rollback limit +## +revisionHistoryLimit: 10 +## Default 404 backend +## +defaultBackend: + ## + enabled: false + name: defaultbackend + image: + registry: registry.k8s.io + image: defaultbackend-amd64 + ## for backwards compatibility consider setting the full image url via the repository value below + ## use *either* current default registry/image or repository format or installing chart by providing the values.yaml will fail + ## repository: + tag: "1.5" + pullPolicy: IfNotPresent + runAsNonRoot: true + # nobody user -> uid 65534 + runAsUser: 65534 + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + readOnlyRootFilesystem: true + # -- Use an existing PSP instead of creating one + existingPsp: "" + extraArgs: {} + serviceAccount: + create: true + name: "" + automountServiceAccountToken: true + # -- Additional environment variables to set for defaultBackend pods + extraEnvs: [] + port: 8080 + ## Readiness and liveness probes for default backend + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/ + ## + livenessProbe: + failureThreshold: 3 + initialDelaySeconds: 30 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + readinessProbe: + failureThreshold: 6 + initialDelaySeconds: 0 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 5 + # -- The update strategy to apply to the Deployment or DaemonSet + ## + updateStrategy: {} + # rollingUpdate: + # maxUnavailable: 1 + # type: RollingUpdate + + # -- `minReadySeconds` to avoid killing pods before we are ready + ## + minReadySeconds: 0 + # -- Node tolerations for server scheduling to nodes with taints + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + ## + tolerations: [] + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + # -- Affinity and anti-affinity rules for server scheduling to nodes + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + affinity: {} + # # An example of preferred pod anti-affinity, weight is in the range 1-100 + # podAntiAffinity: + # preferredDuringSchedulingIgnoredDuringExecution: + # - weight: 100 + # podAffinityTerm: + # labelSelector: + # matchExpressions: + # - key: app.kubernetes.io/name + # operator: In + # values: + # - '{{ include "ingress-nginx.name" . }}' + # - key: app.kubernetes.io/instance + # operator: In + # values: + # - '{{ .Release.Name }}' + # - key: app.kubernetes.io/component + # operator: In + # values: + # - default-backend + # topologyKey: kubernetes.io/hostname + + # # An example of required pod anti-affinity + # podAntiAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # - labelSelector: + # matchExpressions: + # - key: app.kubernetes.io/name + # operator: In + # values: + # - '{{ include "ingress-nginx.name" . }}' + # - key: app.kubernetes.io/instance + # operator: In + # values: + # - '{{ .Release.Name }}' + # - key: app.kubernetes.io/component + # operator: In + # values: + # - default-backend + # topologyKey: kubernetes.io/hostname + + # -- Topology spread constraints rely on node labels to identify the topology domain(s) that each Node is in. + # Ref.: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + topologySpreadConstraints: [] + # - labelSelector: + # matchLabels: + # app.kubernetes.io/name: '{{ include "ingress-nginx.name" . }}' + # app.kubernetes.io/instance: '{{ .Release.Name }}' + # app.kubernetes.io/component: default-backend + # topologyKey: topology.kubernetes.io/zone + # maxSkew: 1 + # whenUnsatisfiable: ScheduleAnyway + # - labelSelector: + # matchLabels: + # app.kubernetes.io/name: '{{ include "ingress-nginx.name" . }}' + # app.kubernetes.io/instance: '{{ .Release.Name }}' + # app.kubernetes.io/component: default-backend + # topologyKey: kubernetes.io/hostname + # maxSkew: 1 + # whenUnsatisfiable: ScheduleAnyway + # -- Security context for default backend pods + podSecurityContext: {} + # -- Security context for default backend containers + containerSecurityContext: {} + # -- Labels to add to the pod container metadata + podLabels: {} + # key: value + + # -- Node labels for default backend pod assignment + ## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: + kubernetes.io/os: linux + # -- Annotations to be added to default backend pods + ## + podAnnotations: {} + replicaCount: 1 + # -- Minimum available pods set in PodDisruptionBudget. + minAvailable: 1 + resources: {} + # limits: + # cpu: 10m + # memory: 20Mi + # requests: + # cpu: 10m + # memory: 20Mi + + extraVolumeMounts: [] + ## Additional volumeMounts to the default backend container. + # - name: copy-portal-skins + # mountPath: /var/lib/lemonldap-ng/portal/skins + + extraVolumes: [] + ## Additional volumes to the default backend pod. + # - name: copy-portal-skins + # emptyDir: {} + + extraConfigMaps: [] + ## Additional configmaps to the default backend pod. + # - name: my-extra-configmap-1 + # labels: + # type: config-1 + # data: + # extra_file_1.html: | + # + # - name: my-extra-configmap-2 + # labels: + # type: config-2 + # data: + # extra_file_2.html: | + # + + autoscaling: + annotations: {} + enabled: false + minReplicas: 1 + maxReplicas: 2 + targetCPUUtilizationPercentage: 50 + targetMemoryUtilizationPercentage: 50 + # NetworkPolicy for default backend component. + networkPolicy: + # -- Enable 'networkPolicy' or not + enabled: false + service: + annotations: {} + # clusterIP: "" + + # -- List of IP addresses at which the default backend service is available + ## Ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips + ## + externalIPs: [] + # loadBalancerIP: "" + loadBalancerSourceRanges: [] + servicePort: 80 + type: ClusterIP + priorityClassName: "" + # -- Labels to be added to the default backend resources + labels: {} +## Enable RBAC as per https://github.com/kubernetes/ingress-nginx/blob/main/docs/deploy/rbac.md and https://github.com/kubernetes/ingress-nginx/issues/266 +rbac: + create: true + scope: false +## If true, create & use Pod Security Policy resources +## https://kubernetes.io/docs/concepts/policy/pod-security-policy/ +podSecurityPolicy: + enabled: false +serviceAccount: + create: true + name: "" + automountServiceAccountToken: true + # -- Annotations for the controller service account + annotations: {} +# -- Optional array of imagePullSecrets containing private registry credentials +## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ +imagePullSecrets: [] +# - name: secretName + +# -- TCP service key-value pairs +## Ref: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/exposing-tcp-udp-services.md +## +tcp: {} +# "8080": "default/example-tcp-svc:9000" + +# -- UDP service key-value pairs +## Ref: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/exposing-tcp-udp-services.md +## +udp: {} +# "53": "kube-system/kube-dns:53" + +# -- Prefix for TCP and UDP ports names in ingress controller service +## Some cloud providers, like Yandex Cloud may have a requirements for a port name regex to support cloud load balancer integration +portNamePrefix: "" +# -- (string) A base64-encoded Diffie-Hellman parameter. +# This can be generated with: `openssl dhparam 4096 2> /dev/null | base64` +## Ref: https://github.com/kubernetes/ingress-nginx/tree/main/docs/examples/customization/ssl-dh-param +dhParam: "" diff --git a/backing-services/istiod/Chart.yaml b/backing-services/istiod/Chart.yaml new file mode 100644 index 0000000..fd94f0a --- /dev/null +++ b/backing-services/istiod/Chart.yaml @@ -0,0 +1,12 @@ +apiVersion: v2 +appVersion: 1.26.1 +description: Helm chart for istio control plane +icon: https://istio.io/latest/favicons/android-192x192.png +keywords: +- istio +- istiod +- istio-discovery +name: istiod +sources: +- https://github.com/istio/istio +version: 1.26.1 diff --git a/backing-services/istiod/README.md b/backing-services/istiod/README.md new file mode 100644 index 0000000..ddbfbc8 --- /dev/null +++ b/backing-services/istiod/README.md @@ -0,0 +1,73 @@ +# Istiod Helm Chart + +This chart installs an Istiod deployment. + +## Setup Repo Info + +```console +helm repo add istio https://istio-release.storage.googleapis.com/charts +helm repo update +``` + +_See [helm repo](https://helm.sh/docs/helm/helm_repo/) for command documentation._ + +## Installing the Chart + +Before installing, ensure CRDs are installed in the cluster (from the `istio/base` chart). + +To install the chart with the release name `istiod`: + +```console +kubectl create namespace istio-system +helm install istiod istio/istiod --namespace istio-system +``` + +## Uninstalling the Chart + +To uninstall/delete the `istiod` deployment: + +```console +helm delete istiod --namespace istio-system +``` + +## Configuration + +To view support configuration options and documentation, run: + +```console +helm show values istio/istiod +``` + +### Profiles + +Istio Helm charts have a concept of a `profile`, which is a bundled collection of value presets. +These can be set with `--set profile=`. +For example, the `demo` profile offers a preset configuration to try out Istio in a test environment, with additional features enabled and lowered resource requirements. + +For consistency, the same profiles are used across each chart, even if they do not impact a given chart. + +Explicitly set values have highest priority, then profile settings, then chart defaults. + +As an implementation detail of profiles, the default values for the chart are all nested under `defaults`. +When configuring the chart, you should not include this. +That is, `--set some.field=true` should be passed, not `--set defaults.some.field=true`. + +### Examples + +#### Configuring mesh configuration settings + +Any [Mesh Config](https://istio.io/latest/docs/reference/config/istio.mesh.v1alpha1/) options can be configured like below: + +```yaml +meshConfig: + accessLogFile: /dev/stdout +``` + +#### Revisions + +Control plane revisions allow deploying multiple versions of the control plane in the same cluster. +This allows safe [canary upgrades](https://istio.io/latest/docs/setup/upgrade/canary/) + +```yaml +revision: my-revision-name +``` diff --git a/backing-services/istiod/bugx.values.yaml b/backing-services/istiod/bugx.values.yaml new file mode 100644 index 0000000..e69de29 diff --git a/backing-services/istiod/files/gateway-injection-template.yaml b/backing-services/istiod/files/gateway-injection-template.yaml new file mode 100644 index 0000000..fdeab1a --- /dev/null +++ b/backing-services/istiod/files/gateway-injection-template.yaml @@ -0,0 +1,261 @@ +{{- $containers := list }} +{{- range $index, $container := .Spec.Containers }}{{ if not (eq $container.Name "istio-proxy") }}{{ $containers = append $containers $container.Name }}{{end}}{{- end}} +metadata: + labels: + service.istio.io/canonical-name: {{ index .ObjectMeta.Labels `service.istio.io/canonical-name` | default (index .ObjectMeta.Labels `app.kubernetes.io/name`) | default (index .ObjectMeta.Labels `app`) | default .DeploymentMeta.Name | quote }} + service.istio.io/canonical-revision: {{ index .ObjectMeta.Labels `service.istio.io/canonical-revision` | default (index .ObjectMeta.Labels `app.kubernetes.io/version`) | default (index .ObjectMeta.Labels `version`) | default "latest" | quote }} + annotations: + istio.io/rev: {{ .Revision | default "default" | quote }} + {{- if ge (len $containers) 1 }} + {{- if not (isset .ObjectMeta.Annotations `kubectl.kubernetes.io/default-logs-container`) }} + kubectl.kubernetes.io/default-logs-container: "{{ index $containers 0 }}" + {{- end }} + {{- if not (isset .ObjectMeta.Annotations `kubectl.kubernetes.io/default-container`) }} + kubectl.kubernetes.io/default-container: "{{ index $containers 0 }}" + {{- end }} + {{- end }} +spec: + securityContext: + {{- if .Values.gateways.securityContext }} + {{- toYaml .Values.gateways.securityContext | nindent 4 }} + {{- else }} + sysctls: + - name: net.ipv4.ip_unprivileged_port_start + value: "0" + {{- end }} + containers: + - name: istio-proxy + {{- if contains "/" (annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image) }} + image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image }}" + {{- else }} + image: "{{ .ProxyImage }}" + {{- end }} + ports: + - containerPort: 15090 + protocol: TCP + name: http-envoy-prom + args: + - proxy + - router + - --domain + - $(POD_NAMESPACE).svc.{{ .Values.global.proxy.clusterDomain }} + - --proxyLogLevel={{ annotation .ObjectMeta `sidecar.istio.io/logLevel` .Values.global.proxy.logLevel }} + - --proxyComponentLogLevel={{ annotation .ObjectMeta `sidecar.istio.io/componentLogLevel` .Values.global.proxy.componentLogLevel }} + - --log_output_level={{ annotation .ObjectMeta `sidecar.istio.io/agentLogLevel` .Values.global.logging.level }} + {{- if .Values.global.sts.servicePort }} + - --stsPort={{ .Values.global.sts.servicePort }} + {{- end }} + {{- if .Values.global.logAsJson }} + - --log_as_json + {{- end }} + {{- if .Values.global.proxy.lifecycle }} + lifecycle: + {{ toYaml .Values.global.proxy.lifecycle | indent 6 }} + {{- end }} + securityContext: + runAsUser: {{ .ProxyUID | default "1337" }} + runAsGroup: {{ .ProxyGID | default "1337" }} + env: + - name: PILOT_CERT_PROVIDER + value: {{ .Values.global.pilotCertProvider }} + - name: CA_ADDR + {{- if .Values.global.caAddress }} + value: {{ .Values.global.caAddress }} + {{- else }} + value: istiod{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }}.{{ .Values.global.istioNamespace }}.svc:15012 + {{- end }} + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: SERVICE_ACCOUNT + valueFrom: + fieldRef: + fieldPath: spec.serviceAccountName + - name: HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: ISTIO_CPU_LIMIT + valueFrom: + resourceFieldRef: + resource: limits.cpu + - name: PROXY_CONFIG + value: | + {{ protoToJSON .ProxyConfig }} + - name: ISTIO_META_POD_PORTS + value: |- + [ + {{- $first := true }} + {{- range $index1, $c := .Spec.Containers }} + {{- range $index2, $p := $c.Ports }} + {{- if (structToJSON $p) }} + {{if not $first}},{{end}}{{ structToJSON $p }} + {{- $first = false }} + {{- end }} + {{- end}} + {{- end}} + ] + - name: GOMEMLIMIT + valueFrom: + resourceFieldRef: + resource: limits.memory + - name: GOMAXPROCS + valueFrom: + resourceFieldRef: + resource: limits.cpu + {{- if .CompliancePolicy }} + - name: COMPLIANCE_POLICY + value: "{{ .CompliancePolicy }}" + {{- end }} + - name: ISTIO_META_APP_CONTAINERS + value: "{{ $containers | join "," }}" + - name: ISTIO_META_CLUSTER_ID + value: "{{ valueOrDefault .Values.global.multiCluster.clusterName `Kubernetes` }}" + - name: ISTIO_META_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: ISTIO_META_INTERCEPTION_MODE + value: "{{ .ProxyConfig.InterceptionMode.String }}" + {{- if .Values.global.network }} + - name: ISTIO_META_NETWORK + value: "{{ .Values.global.network }}" + {{- end }} + {{- if .DeploymentMeta.Name }} + - name: ISTIO_META_WORKLOAD_NAME + value: "{{ .DeploymentMeta.Name }}" + {{ end }} + {{- if and .TypeMeta.APIVersion .DeploymentMeta.Name }} + - name: ISTIO_META_OWNER + value: kubernetes://apis/{{ .TypeMeta.APIVersion }}/namespaces/{{ valueOrDefault .DeploymentMeta.Namespace `default` }}/{{ toLower .TypeMeta.Kind}}s/{{ .DeploymentMeta.Name }} + {{- end}} + {{- if .Values.global.meshID }} + - name: ISTIO_META_MESH_ID + value: "{{ .Values.global.meshID }}" + {{- else if (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }} + - name: ISTIO_META_MESH_ID + value: "{{ (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }}" + {{- end }} + {{- with (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }} + - name: TRUST_DOMAIN + value: "{{ . }}" + {{- end }} + {{- range $key, $value := .ProxyConfig.ProxyMetadata }} + - name: {{ $key }} + value: "{{ $value }}" + {{- end }} + {{with .Values.global.imagePullPolicy }}imagePullPolicy: "{{.}}"{{end}} + readinessProbe: + httpGet: + path: /healthz/ready + port: 15021 + initialDelaySeconds: {{.Values.global.proxy.readinessInitialDelaySeconds }} + periodSeconds: {{ .Values.global.proxy.readinessPeriodSeconds }} + timeoutSeconds: 3 + failureThreshold: {{ .Values.global.proxy.readinessFailureThreshold }} + volumeMounts: + - name: workload-socket + mountPath: /var/run/secrets/workload-spiffe-uds + - name: credential-socket + mountPath: /var/run/secrets/credential-uds + {{- if eq .Values.global.caName "GkeWorkloadCertificate" }} + - name: gke-workload-certificate + mountPath: /var/run/secrets/workload-spiffe-credentials + readOnly: true + {{- else }} + - name: workload-certs + mountPath: /var/run/secrets/workload-spiffe-credentials + {{- end }} + {{- if eq .Values.global.pilotCertProvider "istiod" }} + - mountPath: /var/run/secrets/istio + name: istiod-ca-cert + {{- end }} + - mountPath: /var/lib/istio/data + name: istio-data + # SDS channel between istioagent and Envoy + - mountPath: /etc/istio/proxy + name: istio-envoy + - mountPath: /var/run/secrets/tokens + name: istio-token + {{- if .Values.global.mountMtlsCerts }} + # Use the key and cert mounted to /etc/certs/ for the in-cluster mTLS communications. + - mountPath: /etc/certs/ + name: istio-certs + readOnly: true + {{- end }} + - name: istio-podinfo + mountPath: /etc/istio/pod + volumes: + - emptyDir: {} + name: workload-socket + - emptyDir: {} + name: credential-socket + {{- if eq .Values.global.caName "GkeWorkloadCertificate" }} + - name: gke-workload-certificate + csi: + driver: workloadcertificates.security.cloud.google.com + {{- else}} + - emptyDir: {} + name: workload-certs + {{- end }} + # SDS channel between istioagent and Envoy + - emptyDir: + medium: Memory + name: istio-envoy + - name: istio-data + emptyDir: {} + - name: istio-podinfo + downwardAPI: + items: + - path: "labels" + fieldRef: + fieldPath: metadata.labels + - path: "annotations" + fieldRef: + fieldPath: metadata.annotations + - name: istio-token + projected: + sources: + - serviceAccountToken: + path: istio-token + expirationSeconds: 43200 + audience: {{ .Values.global.sds.token.aud }} + {{- if eq .Values.global.pilotCertProvider "istiod" }} + - name: istiod-ca-cert + {{- if eq (.Values.pilot.env).ENABLE_CLUSTER_TRUST_BUNDLE_API true }} + projected: + sources: + - clusterTrustBundle: + name: istio.io:istiod-ca:root-cert + path: root-cert.pem + {{- else }} + configMap: + name: istio-ca-root-cert + {{- end }} + {{- end }} + {{- if .Values.global.mountMtlsCerts }} + # Use the key and cert mounted to /etc/certs/ for the in-cluster mTLS communications. + - name: istio-certs + secret: + optional: true + {{ if eq .Spec.ServiceAccountName "" }} + secretName: istio.default + {{ else -}} + secretName: {{ printf "istio.%s" .Spec.ServiceAccountName }} + {{ end -}} + {{- end }} + {{- if .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- range .Values.global.imagePullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} diff --git a/backing-services/istiod/files/grpc-agent.yaml b/backing-services/istiod/files/grpc-agent.yaml new file mode 100644 index 0000000..6f3315b --- /dev/null +++ b/backing-services/istiod/files/grpc-agent.yaml @@ -0,0 +1,318 @@ +{{- define "resources" }} + {{- if or (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPULimit`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemoryLimit`) }} + {{- if or (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory`) }} + requests: + {{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU`) -}} + cpu: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU` }}" + {{ end }} + {{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory`) -}} + memory: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory` }}" + {{ end }} + {{- end }} + {{- if or (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPULimit`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemoryLimit`) }} + limits: + {{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPULimit`) -}} + cpu: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyCPULimit` }}" + {{ end }} + {{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemoryLimit`) -}} + memory: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyMemoryLimit` }}" + {{ end }} + {{- end }} + {{- else }} + {{- if .Values.global.proxy.resources }} + {{ toYaml .Values.global.proxy.resources | indent 6 }} + {{- end }} + {{- end }} +{{- end }} +{{- $containers := list }} +{{- range $index, $container := .Spec.Containers }}{{ if not (eq $container.Name "istio-proxy") }}{{ $containers = append $containers $container.Name }}{{end}}{{- end}} +metadata: + labels: + {{/* security.istio.io/tlsMode: istio must be set by user, if gRPC is using mTLS initialization code. We can't set it automatically. */}} + service.istio.io/canonical-name: {{ index .ObjectMeta.Labels `service.istio.io/canonical-name` | default (index .ObjectMeta.Labels `app.kubernetes.io/name`) | default (index .ObjectMeta.Labels `app`) | default .DeploymentMeta.Name | quote }} + service.istio.io/canonical-revision: {{ index .ObjectMeta.Labels `service.istio.io/canonical-revision` | default (index .ObjectMeta.Labels `app.kubernetes.io/version`) | default (index .ObjectMeta.Labels `version`) | default "latest" | quote }} + annotations: { + istio.io/rev: {{ .Revision | default "default" | quote }}, + {{- if ge (len $containers) 1 }} + {{- if not (isset .ObjectMeta.Annotations `kubectl.kubernetes.io/default-logs-container`) }} + kubectl.kubernetes.io/default-logs-container: "{{ index $containers 0 }}", + {{- end }} + {{- if not (isset .ObjectMeta.Annotations `kubectl.kubernetes.io/default-container`) }} + kubectl.kubernetes.io/default-container: "{{ index $containers 0 }}", + {{- end }} + {{- end }} + sidecar.istio.io/rewriteAppHTTPProbers: "false", + } +spec: + containers: + - name: istio-proxy + {{- if contains "/" (annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image) }} + image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image }}" + {{- else }} + image: "{{ .ProxyImage }}" + {{- end }} + ports: + - containerPort: 15020 + protocol: TCP + name: mesh-metrics + args: + - proxy + - sidecar + - --domain + - $(POD_NAMESPACE).svc.{{ .Values.global.proxy.clusterDomain }} + - --proxyLogLevel={{ annotation .ObjectMeta `sidecar.istio.io/logLevel` .Values.global.proxy.logLevel }} + - --proxyComponentLogLevel={{ annotation .ObjectMeta `sidecar.istio.io/componentLogLevel` .Values.global.proxy.componentLogLevel }} + - --log_output_level={{ annotation .ObjectMeta `sidecar.istio.io/agentLogLevel` .Values.global.logging.level }} + {{- if .Values.global.sts.servicePort }} + - --stsPort={{ .Values.global.sts.servicePort }} + {{- end }} + {{- if .Values.global.logAsJson }} + - --log_as_json + {{- end }} + lifecycle: + postStart: + exec: + command: + - pilot-agent + - wait + - --url=http://localhost:15020/healthz/ready + env: + - name: ISTIO_META_GENERATOR + value: grpc + - name: OUTPUT_CERTS + value: /var/lib/istio/data + {{- if eq .InboundTrafficPolicyMode "localhost" }} + - name: REWRITE_PROBE_LEGACY_LOCALHOST_DESTINATION + value: "true" + {{- end }} + - name: PILOT_CERT_PROVIDER + value: {{ .Values.global.pilotCertProvider }} + - name: CA_ADDR + {{- if .Values.global.caAddress }} + value: {{ .Values.global.caAddress }} + {{- else }} + value: istiod{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }}.{{ .Values.global.istioNamespace }}.svc:15012 + {{- end }} + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: SERVICE_ACCOUNT + valueFrom: + fieldRef: + fieldPath: spec.serviceAccountName + - name: HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: PROXY_CONFIG + value: | + {{ protoToJSON .ProxyConfig }} + - name: ISTIO_META_POD_PORTS + value: |- + [ + {{- $first := true }} + {{- range $index1, $c := .Spec.Containers }} + {{- range $index2, $p := $c.Ports }} + {{- if (structToJSON $p) }} + {{if not $first}},{{end}}{{ structToJSON $p }} + {{- $first = false }} + {{- end }} + {{- end}} + {{- end}} + ] + - name: ISTIO_META_APP_CONTAINERS + value: "{{ $containers | join "," }}" + - name: ISTIO_META_CLUSTER_ID + value: "{{ valueOrDefault .Values.global.multiCluster.clusterName `Kubernetes` }}" + - name: ISTIO_META_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + {{- if .Values.global.network }} + - name: ISTIO_META_NETWORK + value: "{{ .Values.global.network }}" + {{- end }} + {{- if .DeploymentMeta.Name }} + - name: ISTIO_META_WORKLOAD_NAME + value: "{{ .DeploymentMeta.Name }}" + {{ end }} + {{- if and .TypeMeta.APIVersion .DeploymentMeta.Name }} + - name: ISTIO_META_OWNER + value: kubernetes://apis/{{ .TypeMeta.APIVersion }}/namespaces/{{ valueOrDefault .DeploymentMeta.Namespace `default` }}/{{ toLower .TypeMeta.Kind}}s/{{ .DeploymentMeta.Name }} + {{- end}} + {{- if .Values.global.meshID }} + - name: ISTIO_META_MESH_ID + value: "{{ .Values.global.meshID }}" + {{- else if (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }} + - name: ISTIO_META_MESH_ID + value: "{{ (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }}" + {{- end }} + {{- with (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }} + - name: TRUST_DOMAIN + value: "{{ . }}" + {{- end }} + {{- range $key, $value := .ProxyConfig.ProxyMetadata }} + - name: {{ $key }} + value: "{{ $value }}" + {{- end }} + # grpc uses xds:/// to resolve – no need to resolve VIP + - name: ISTIO_META_DNS_CAPTURE + value: "false" + - name: DISABLE_ENVOY + value: "true" + {{with .Values.global.imagePullPolicy }}imagePullPolicy: "{{.}}"{{end}} + {{ if ne (annotation .ObjectMeta `status.sidecar.istio.io/port` .Values.global.proxy.statusPort) `0` }} + readinessProbe: + httpGet: + path: /healthz/ready + port: 15020 + initialDelaySeconds: {{ annotation .ObjectMeta `readiness.status.sidecar.istio.io/initialDelaySeconds` .Values.global.proxy.readinessInitialDelaySeconds }} + periodSeconds: {{ annotation .ObjectMeta `readiness.status.sidecar.istio.io/periodSeconds` .Values.global.proxy.readinessPeriodSeconds }} + timeoutSeconds: 3 + failureThreshold: {{ annotation .ObjectMeta `readiness.status.sidecar.istio.io/failureThreshold` .Values.global.proxy.readinessFailureThreshold }} + resources: + {{ template "resources" . }} + volumeMounts: + - name: workload-socket + mountPath: /var/run/secrets/workload-spiffe-uds + {{- if eq .Values.global.caName "GkeWorkloadCertificate" }} + - name: gke-workload-certificate + mountPath: /var/run/secrets/workload-spiffe-credentials + readOnly: true + {{- else }} + - name: workload-certs + mountPath: /var/run/secrets/workload-spiffe-credentials + {{- end }} + {{- if eq .Values.global.pilotCertProvider "istiod" }} + - mountPath: /var/run/secrets/istio + name: istiod-ca-cert + {{- end }} + - mountPath: /var/lib/istio/data + name: istio-data + # UDS channel between istioagent and gRPC client for XDS/SDS + - mountPath: /etc/istio/proxy + name: istio-xds + - mountPath: /var/run/secrets/tokens + name: istio-token + {{- if .Values.global.mountMtlsCerts }} + # Use the key and cert mounted to /etc/certs/ for the in-cluster mTLS communications. + - mountPath: /etc/certs/ + name: istio-certs + readOnly: true + {{- end }} + - name: istio-podinfo + mountPath: /etc/istio/pod + {{- end }} + {{- if isset .ObjectMeta.Annotations `sidecar.istio.io/userVolumeMount` }} + {{ range $index, $value := fromJSON (index .ObjectMeta.Annotations `sidecar.istio.io/userVolumeMount`) }} + - name: "{{ $index }}" + {{ toYaml $value | indent 6 }} + {{ end }} + {{- end }} +{{- range $index, $container := .Spec.Containers }} +{{ if not (eq $container.Name "istio-proxy") }} + - name: {{ $container.Name }} + env: + - name: "GRPC_XDS_EXPERIMENTAL_SECURITY_SUPPORT" + value: "true" + - name: "GRPC_XDS_BOOTSTRAP" + value: "/etc/istio/proxy/grpc-bootstrap.json" + volumeMounts: + - mountPath: /var/lib/istio/data + name: istio-data + # UDS channel between istioagent and gRPC client for XDS/SDS + - mountPath: /etc/istio/proxy + name: istio-xds + {{- if eq $.Values.global.caName "GkeWorkloadCertificate" }} + - name: gke-workload-certificate + mountPath: /var/run/secrets/workload-spiffe-credentials + readOnly: true + {{- else }} + - name: workload-certs + mountPath: /var/run/secrets/workload-spiffe-credentials + {{- end }} +{{- end }} +{{- end }} + volumes: + - emptyDir: + name: workload-socket + {{- if eq .Values.global.caName "GkeWorkloadCertificate" }} + - name: gke-workload-certificate + csi: + driver: workloadcertificates.security.cloud.google.com + {{- else }} + - emptyDir: + name: workload-certs + {{- end }} + {{- if (isset .ObjectMeta.Annotations `sidecar.istio.io/bootstrapOverride`) }} + - name: custom-bootstrap-volume + configMap: + name: {{ annotation .ObjectMeta `sidecar.istio.io/bootstrapOverride` "" }} + {{- end }} + # SDS channel between istioagent and Envoy + - emptyDir: + medium: Memory + name: istio-xds + - name: istio-data + emptyDir: {} + - name: istio-podinfo + downwardAPI: + items: + - path: "labels" + fieldRef: + fieldPath: metadata.labels + - path: "annotations" + fieldRef: + fieldPath: metadata.annotations + - name: istio-token + projected: + sources: + - serviceAccountToken: + path: istio-token + expirationSeconds: 43200 + audience: {{ .Values.global.sds.token.aud }} + {{- if eq .Values.global.pilotCertProvider "istiod" }} + - name: istiod-ca-cert + {{- if eq (.Values.pilot.env).ENABLE_CLUSTER_TRUST_BUNDLE_API true }} + projected: + sources: + - clusterTrustBundle: + name: istio.io:istiod-ca:root-cert + path: root-cert.pem + {{- else }} + configMap: + name: istio-ca-root-cert + {{- end }} + {{- end }} + {{- if .Values.global.mountMtlsCerts }} + # Use the key and cert mounted to /etc/certs/ for the in-cluster mTLS communications. + - name: istio-certs + secret: + optional: true + {{ if eq .Spec.ServiceAccountName "" }} + secretName: istio.default + {{ else -}} + secretName: {{ printf "istio.%s" .Spec.ServiceAccountName }} + {{ end -}} + {{- end }} + {{- if isset .ObjectMeta.Annotations `sidecar.istio.io/userVolume` }} + {{range $index, $value := fromJSON (index .ObjectMeta.Annotations `sidecar.istio.io/userVolume`) }} + - name: "{{ $index }}" + {{ toYaml $value | indent 4 }} + {{ end }} + {{ end }} + {{- if .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- range .Values.global.imagePullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} diff --git a/backing-services/istiod/files/grpc-simple.yaml b/backing-services/istiod/files/grpc-simple.yaml new file mode 100644 index 0000000..9ba0c7a --- /dev/null +++ b/backing-services/istiod/files/grpc-simple.yaml @@ -0,0 +1,65 @@ +metadata: + annotations: + sidecar.istio.io/rewriteAppHTTPProbers: "false" +spec: + initContainers: + - name: grpc-bootstrap-init + image: busybox:1.28 + volumeMounts: + - mountPath: /var/lib/grpc/data/ + name: grpc-io-proxyless-bootstrap + env: + - name: INSTANCE_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: ISTIO_NAMESPACE + value: | + {{ .Values.global.istioNamespace }} + command: + - sh + - "-c" + - |- + NODE_ID="sidecar~${INSTANCE_IP}~${POD_NAME}.${POD_NAMESPACE}~cluster.local" + SERVER_URI="dns:///istiod.${ISTIO_NAMESPACE}.svc:15010" + echo ' + { + "xds_servers": [ + { + "server_uri": "'${SERVER_URI}'", + "channel_creds": [{"type": "insecure"}], + "server_features" : ["xds_v3"] + } + ], + "node": { + "id": "'${NODE_ID}'", + "metadata": { + "GENERATOR": "grpc" + } + } + }' > /var/lib/grpc/data/bootstrap.json + containers: + {{- range $index, $container := .Spec.Containers }} + - name: {{ $container.Name }} + env: + - name: GRPC_XDS_BOOTSTRAP + value: /var/lib/grpc/data/bootstrap.json + - name: GRPC_GO_LOG_VERBOSITY_LEVEL + value: "99" + - name: GRPC_GO_LOG_SEVERITY_LEVEL + value: info + volumeMounts: + - mountPath: /var/lib/grpc/data/ + name: grpc-io-proxyless-bootstrap + {{- end }} + volumes: + - name: grpc-io-proxyless-bootstrap + emptyDir: {} diff --git a/backing-services/istiod/files/injection-template.yaml b/backing-services/istiod/files/injection-template.yaml new file mode 100644 index 0000000..d8b96ff --- /dev/null +++ b/backing-services/istiod/files/injection-template.yaml @@ -0,0 +1,530 @@ +{{- define "resources" }} + {{- if or (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPULimit`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemoryLimit`) }} + {{- if or (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory`) }} + requests: + {{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU`) -}} + cpu: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU` }}" + {{ end }} + {{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory`) -}} + memory: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory` }}" + {{ end }} + {{- end }} + {{- if or (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPULimit`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemoryLimit`) }} + limits: + {{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPULimit`) -}} + cpu: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyCPULimit` }}" + {{ end }} + {{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemoryLimit`) -}} + memory: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyMemoryLimit` }}" + {{ end }} + {{- end }} + {{- else }} + {{- if .Values.global.proxy.resources }} + {{ toYaml .Values.global.proxy.resources | indent 6 }} + {{- end }} + {{- end }} +{{- end }} +{{ $nativeSidecar := (or (and (not (isset .ObjectMeta.Annotations `sidecar.istio.io/nativeSidecar`)) (eq (env "ENABLE_NATIVE_SIDECARS" "false") "true")) (eq (index .ObjectMeta.Annotations `sidecar.istio.io/nativeSidecar`) "true")) }} +{{- $containers := list }} +{{- range $index, $container := .Spec.Containers }}{{ if not (eq $container.Name "istio-proxy") }}{{ $containers = append $containers $container.Name }}{{end}}{{- end}} +metadata: + labels: + security.istio.io/tlsMode: {{ index .ObjectMeta.Labels `security.istio.io/tlsMode` | default "istio" | quote }} + {{- if eq (index .ProxyConfig.ProxyMetadata "ISTIO_META_ENABLE_HBONE") "true" }} + networking.istio.io/tunnel: {{ index .ObjectMeta.Labels `networking.istio.io/tunnel` | default "http" | quote }} + {{- end }} + service.istio.io/canonical-name: {{ index .ObjectMeta.Labels `service.istio.io/canonical-name` | default (index .ObjectMeta.Labels `app.kubernetes.io/name`) | default (index .ObjectMeta.Labels `app`) | default .DeploymentMeta.Name | trunc 63 | trimSuffix "-" | quote }} + service.istio.io/canonical-revision: {{ index .ObjectMeta.Labels `service.istio.io/canonical-revision` | default (index .ObjectMeta.Labels `app.kubernetes.io/version`) | default (index .ObjectMeta.Labels `version`) | default "latest" | quote }} + annotations: { + istio.io/rev: {{ .Revision | default "default" | quote }}, + {{- if ge (len $containers) 1 }} + {{- if not (isset .ObjectMeta.Annotations `kubectl.kubernetes.io/default-logs-container`) }} + kubectl.kubernetes.io/default-logs-container: "{{ index $containers 0 }}", + {{- end }} + {{- if not (isset .ObjectMeta.Annotations `kubectl.kubernetes.io/default-container`) }} + kubectl.kubernetes.io/default-container: "{{ index $containers 0 }}", + {{- end }} + {{- end }} +{{- if .Values.pilot.cni.enabled }} + {{- if eq .Values.pilot.cni.provider "multus" }} + k8s.v1.cni.cncf.io/networks: '{{ appendMultusNetwork (index .ObjectMeta.Annotations `k8s.v1.cni.cncf.io/networks`) `default/istio-cni` }}', + {{- end }} + sidecar.istio.io/interceptionMode: "{{ annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode }}", + {{ with annotation .ObjectMeta `traffic.sidecar.istio.io/includeOutboundIPRanges` .Values.global.proxy.includeIPRanges }}traffic.sidecar.istio.io/includeOutboundIPRanges: "{{.}}",{{ end }} + {{ with annotation .ObjectMeta `traffic.sidecar.istio.io/excludeOutboundIPRanges` .Values.global.proxy.excludeIPRanges }}traffic.sidecar.istio.io/excludeOutboundIPRanges: "{{.}}",{{ end }} + traffic.sidecar.istio.io/includeInboundPorts: "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/includeInboundPorts` .Values.global.proxy.includeInboundPorts }}", + traffic.sidecar.istio.io/excludeInboundPorts: "{{ excludeInboundPort (annotation .ObjectMeta `status.sidecar.istio.io/port` .Values.global.proxy.statusPort) (annotation .ObjectMeta `traffic.sidecar.istio.io/excludeInboundPorts` .Values.global.proxy.excludeInboundPorts) }}", + {{ if or (isset .ObjectMeta.Annotations `traffic.sidecar.istio.io/includeOutboundPorts`) (ne (valueOrDefault .Values.global.proxy.includeOutboundPorts "") "") }} + traffic.sidecar.istio.io/includeOutboundPorts: "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/includeOutboundPorts` .Values.global.proxy.includeOutboundPorts }}", + {{- end }} + {{ if or (isset .ObjectMeta.Annotations `traffic.sidecar.istio.io/excludeOutboundPorts`) (ne .Values.global.proxy.excludeOutboundPorts "") }} + traffic.sidecar.istio.io/excludeOutboundPorts: "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/excludeOutboundPorts` .Values.global.proxy.excludeOutboundPorts }}", + {{- end }} + {{ with index .ObjectMeta.Annotations `traffic.sidecar.istio.io/kubevirtInterfaces` }}traffic.sidecar.istio.io/kubevirtInterfaces: "{{.}}",{{ end }} + {{ with index .ObjectMeta.Annotations `istio.io/reroute-virtual-interfaces` }}istio.io/reroute-virtual-interfaces: "{{.}}",{{ end }} + {{ with index .ObjectMeta.Annotations `traffic.sidecar.istio.io/excludeInterfaces` }}traffic.sidecar.istio.io/excludeInterfaces: "{{.}}",{{ end }} +{{- end }} + } +spec: + {{- $holdProxy := and + (or .ProxyConfig.HoldApplicationUntilProxyStarts.GetValue .Values.global.proxy.holdApplicationUntilProxyStarts) + (not $nativeSidecar) }} + {{- $noInitContainer := and + (eq (annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode) `NONE`) + (not $nativeSidecar) }} + {{ if $noInitContainer }} + initContainers: [] + {{ else -}} + initContainers: + {{ if ne (annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode) `NONE` }} + {{ if .Values.pilot.cni.enabled -}} + - name: istio-validation + {{ else -}} + - name: istio-init + {{ end -}} + {{- if contains "/" (annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy_init.image) }} + image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy_init.image }}" + {{- else }} + image: "{{ .ProxyImage }}" + {{- end }} + args: + - istio-iptables + - "-p" + - {{ .MeshConfig.ProxyListenPort | default "15001" | quote }} + - "-z" + - {{ .MeshConfig.ProxyInboundListenPort | default "15006" | quote }} + - "-u" + - {{ .ProxyUID | default "1337" | quote }} + - "-m" + - "{{ annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode }}" + - "-i" + - "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/includeOutboundIPRanges` .Values.global.proxy.includeIPRanges }}" + - "-x" + - "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/excludeOutboundIPRanges` .Values.global.proxy.excludeIPRanges }}" + - "-b" + - "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/includeInboundPorts` .Values.global.proxy.includeInboundPorts }}" + - "-d" + {{- if excludeInboundPort (annotation .ObjectMeta `status.sidecar.istio.io/port` .Values.global.proxy.statusPort) (annotation .ObjectMeta `traffic.sidecar.istio.io/excludeInboundPorts` .Values.global.proxy.excludeInboundPorts) }} + - "15090,15021,{{ excludeInboundPort (annotation .ObjectMeta `status.sidecar.istio.io/port` .Values.global.proxy.statusPort) (annotation .ObjectMeta `traffic.sidecar.istio.io/excludeInboundPorts` .Values.global.proxy.excludeInboundPorts) }}" + {{- else }} + - "15090,15021" + {{- end }} + {{ if or (isset .ObjectMeta.Annotations `traffic.sidecar.istio.io/includeOutboundPorts`) (ne (valueOrDefault .Values.global.proxy.includeOutboundPorts "") "") -}} + - "-q" + - "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/includeOutboundPorts` .Values.global.proxy.includeOutboundPorts }}" + {{ end -}} + {{ if or (isset .ObjectMeta.Annotations `traffic.sidecar.istio.io/excludeOutboundPorts`) (ne (valueOrDefault .Values.global.proxy.excludeOutboundPorts "") "") -}} + - "-o" + - "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/excludeOutboundPorts` .Values.global.proxy.excludeOutboundPorts }}" + {{ end -}} + {{ if (isset .ObjectMeta.Annotations `traffic.sidecar.istio.io/kubevirtInterfaces`) -}} + - "-k" + - "{{ index .ObjectMeta.Annotations `traffic.sidecar.istio.io/kubevirtInterfaces` }}" + {{ end -}} + {{ if (isset .ObjectMeta.Annotations `istio.io/reroute-virtual-interfaces`) -}} + - "-k" + - "{{ index .ObjectMeta.Annotations `istio.io/reroute-virtual-interfaces` }}" + {{ end -}} + {{ if (isset .ObjectMeta.Annotations `traffic.sidecar.istio.io/excludeInterfaces`) -}} + - "-c" + - "{{ index .ObjectMeta.Annotations `traffic.sidecar.istio.io/excludeInterfaces` }}" + {{ end -}} + - "--log_output_level={{ annotation .ObjectMeta `sidecar.istio.io/agentLogLevel` .Values.global.logging.level }}" + {{ if .Values.global.logAsJson -}} + - "--log_as_json" + {{ end -}} + {{ if .Values.pilot.cni.enabled -}} + - "--run-validation" + - "--skip-rule-apply" + {{ else if .Values.global.proxy_init.forceApplyIptables -}} + - "--force-apply" + {{ end -}} + {{with .Values.global.imagePullPolicy }}imagePullPolicy: "{{.}}"{{end}} + {{- if .ProxyConfig.ProxyMetadata }} + env: + {{- range $key, $value := .ProxyConfig.ProxyMetadata }} + - name: {{ $key }} + value: "{{ $value }}" + {{- end }} + {{- end }} + resources: + {{ template "resources" . }} + securityContext: + allowPrivilegeEscalation: {{ .Values.global.proxy.privileged }} + privileged: {{ .Values.global.proxy.privileged }} + capabilities: + {{- if not .Values.pilot.cni.enabled }} + add: + - NET_ADMIN + - NET_RAW + {{- end }} + drop: + - ALL + {{- if not .Values.pilot.cni.enabled }} + readOnlyRootFilesystem: false + runAsGroup: 0 + runAsNonRoot: false + runAsUser: 0 + {{- else }} + readOnlyRootFilesystem: true + runAsGroup: {{ .ProxyGID | default "1337" }} + runAsUser: {{ .ProxyUID | default "1337" }} + runAsNonRoot: true + {{- end }} + {{ end -}} + {{ end -}} + {{ if not $nativeSidecar }} + containers: + {{ end }} + - name: istio-proxy + {{- if contains "/" (annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image) }} + image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image }}" + {{- else }} + image: "{{ .ProxyImage }}" + {{- end }} + {{ if $nativeSidecar }}restartPolicy: Always{{end}} + ports: + - containerPort: 15090 + protocol: TCP + name: http-envoy-prom + args: + - proxy + - sidecar + - --domain + - $(POD_NAMESPACE).svc.{{ .Values.global.proxy.clusterDomain }} + - --proxyLogLevel={{ annotation .ObjectMeta `sidecar.istio.io/logLevel` .Values.global.proxy.logLevel }} + - --proxyComponentLogLevel={{ annotation .ObjectMeta `sidecar.istio.io/componentLogLevel` .Values.global.proxy.componentLogLevel }} + - --log_output_level={{ annotation .ObjectMeta `sidecar.istio.io/agentLogLevel` .Values.global.logging.level }} + {{- if .Values.global.sts.servicePort }} + - --stsPort={{ .Values.global.sts.servicePort }} + {{- end }} + {{- if .Values.global.logAsJson }} + - --log_as_json + {{- end }} + {{- if .Values.global.proxy.outlierLogPath }} + - --outlierLogPath={{ .Values.global.proxy.outlierLogPath }} + {{- end}} + {{- if .Values.global.proxy.lifecycle }} + lifecycle: + {{ toYaml .Values.global.proxy.lifecycle | indent 6 }} + {{- else if $holdProxy }} + lifecycle: + postStart: + exec: + command: + - pilot-agent + - wait + {{- else if $nativeSidecar }} + {{- /* preStop is called when the pod starts shutdown. Initialize drain. We will get SIGTERM once applications are torn down. */}} + lifecycle: + preStop: + exec: + command: + - pilot-agent + - request + - --debug-port={{(annotation .ObjectMeta `status.sidecar.istio.io/port` .Values.global.proxy.statusPort)}} + - POST + - drain + {{- end }} + env: + {{- if eq .InboundTrafficPolicyMode "localhost" }} + - name: REWRITE_PROBE_LEGACY_LOCALHOST_DESTINATION + value: "true" + {{- end }} + - name: PILOT_CERT_PROVIDER + value: {{ .Values.global.pilotCertProvider }} + - name: CA_ADDR + {{- if .Values.global.caAddress }} + value: {{ .Values.global.caAddress }} + {{- else }} + value: istiod{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }}.{{ .Values.global.istioNamespace }}.svc:15012 + {{- end }} + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: SERVICE_ACCOUNT + valueFrom: + fieldRef: + fieldPath: spec.serviceAccountName + - name: HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: ISTIO_CPU_LIMIT + valueFrom: + resourceFieldRef: + resource: limits.cpu + - name: PROXY_CONFIG + value: | + {{ protoToJSON .ProxyConfig }} + - name: ISTIO_META_POD_PORTS + value: |- + [ + {{- $first := true }} + {{- range $index1, $c := .Spec.Containers }} + {{- range $index2, $p := $c.Ports }} + {{- if (structToJSON $p) }} + {{if not $first}},{{end}}{{ structToJSON $p }} + {{- $first = false }} + {{- end }} + {{- end}} + {{- end}} + ] + - name: ISTIO_META_APP_CONTAINERS + value: "{{ $containers | join "," }}" + - name: GOMEMLIMIT + valueFrom: + resourceFieldRef: + resource: limits.memory + - name: GOMAXPROCS + valueFrom: + resourceFieldRef: + resource: limits.cpu + {{- if .CompliancePolicy }} + - name: COMPLIANCE_POLICY + value: "{{ .CompliancePolicy }}" + {{- end }} + - name: ISTIO_META_CLUSTER_ID + value: "{{ valueOrDefault .Values.global.multiCluster.clusterName `Kubernetes` }}" + - name: ISTIO_META_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: ISTIO_META_INTERCEPTION_MODE + value: "{{ or (index .ObjectMeta.Annotations `sidecar.istio.io/interceptionMode`) .ProxyConfig.InterceptionMode.String }}" + {{- if .Values.global.network }} + - name: ISTIO_META_NETWORK + value: "{{ .Values.global.network }}" + {{- end }} + {{- with (index .ObjectMeta.Labels `service.istio.io/workload-name` | default .DeploymentMeta.Name) }} + - name: ISTIO_META_WORKLOAD_NAME + value: "{{ . }}" + {{ end }} + {{- if and .TypeMeta.APIVersion .DeploymentMeta.Name }} + - name: ISTIO_META_OWNER + value: kubernetes://apis/{{ .TypeMeta.APIVersion }}/namespaces/{{ valueOrDefault .DeploymentMeta.Namespace `default` }}/{{ toLower .TypeMeta.Kind}}s/{{ .DeploymentMeta.Name }} + {{- end}} + {{- if (isset .ObjectMeta.Annotations `sidecar.istio.io/bootstrapOverride`) }} + - name: ISTIO_BOOTSTRAP_OVERRIDE + value: "/etc/istio/custom-bootstrap/custom_bootstrap.json" + {{- end }} + {{- if .Values.global.meshID }} + - name: ISTIO_META_MESH_ID + value: "{{ .Values.global.meshID }}" + {{- else if (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }} + - name: ISTIO_META_MESH_ID + value: "{{ (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }}" + {{- end }} + {{- with (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }} + - name: TRUST_DOMAIN + value: "{{ . }}" + {{- end }} + {{- if and (eq .Values.global.proxy.tracer "datadog") (isset .ObjectMeta.Annotations `apm.datadoghq.com/env`) }} + {{- range $key, $value := fromJSON (index .ObjectMeta.Annotations `apm.datadoghq.com/env`) }} + - name: {{ $key }} + value: "{{ $value }}" + {{- end }} + {{- end }} + {{- range $key, $value := .ProxyConfig.ProxyMetadata }} + - name: {{ $key }} + value: "{{ $value }}" + {{- end }} + {{with .Values.global.imagePullPolicy }}imagePullPolicy: "{{.}}"{{end}} + {{ if ne (annotation .ObjectMeta `status.sidecar.istio.io/port` .Values.global.proxy.statusPort) `0` }} + {{ if .Values.global.proxy.startupProbe.enabled }} + startupProbe: + httpGet: + path: /healthz/ready + port: 15021 + initialDelaySeconds: 0 + periodSeconds: 1 + timeoutSeconds: 3 + failureThreshold: {{ .Values.global.proxy.startupProbe.failureThreshold }} + {{ end }} + readinessProbe: + httpGet: + path: /healthz/ready + port: 15021 + initialDelaySeconds: {{ annotation .ObjectMeta `readiness.status.sidecar.istio.io/initialDelaySeconds` .Values.global.proxy.readinessInitialDelaySeconds }} + periodSeconds: {{ annotation .ObjectMeta `readiness.status.sidecar.istio.io/periodSeconds` .Values.global.proxy.readinessPeriodSeconds }} + timeoutSeconds: 3 + failureThreshold: {{ annotation .ObjectMeta `readiness.status.sidecar.istio.io/failureThreshold` .Values.global.proxy.readinessFailureThreshold }} + {{ end -}} + securityContext: + {{- if eq (index .ProxyConfig.ProxyMetadata "IPTABLES_TRACE_LOGGING") "true" }} + allowPrivilegeEscalation: true + capabilities: + add: + - NET_ADMIN + drop: + - ALL + privileged: true + readOnlyRootFilesystem: true + runAsGroup: {{ .ProxyGID | default "1337" }} + runAsNonRoot: false + runAsUser: 0 + {{- else }} + allowPrivilegeEscalation: {{ .Values.global.proxy.privileged }} + capabilities: + {{ if or (eq (annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode) `TPROXY`) (eq (annotation .ObjectMeta `sidecar.istio.io/capNetBindService` .Values.global.proxy.capNetBindService) `true`) -}} + add: + {{ if eq (annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode) `TPROXY` -}} + - NET_ADMIN + {{- end }} + {{ if eq (annotation .ObjectMeta `sidecar.istio.io/capNetBindService` .Values.global.proxy.capNetBindService) `true` -}} + - NET_BIND_SERVICE + {{- end }} + {{- end }} + drop: + - ALL + privileged: {{ .Values.global.proxy.privileged }} + readOnlyRootFilesystem: true + runAsGroup: {{ .ProxyGID | default "1337" }} + {{ if or (eq (annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode) `TPROXY`) (eq (annotation .ObjectMeta `sidecar.istio.io/capNetBindService` .Values.global.proxy.capNetBindService) `true`) -}} + runAsNonRoot: false + runAsUser: 0 + {{- else -}} + runAsNonRoot: true + runAsUser: {{ .ProxyUID | default "1337" }} + {{- end }} + {{- end }} + resources: + {{ template "resources" . }} + volumeMounts: + - name: workload-socket + mountPath: /var/run/secrets/workload-spiffe-uds + - name: credential-socket + mountPath: /var/run/secrets/credential-uds + {{- if eq .Values.global.caName "GkeWorkloadCertificate" }} + - name: gke-workload-certificate + mountPath: /var/run/secrets/workload-spiffe-credentials + readOnly: true + {{- else }} + - name: workload-certs + mountPath: /var/run/secrets/workload-spiffe-credentials + {{- end }} + {{- if eq .Values.global.pilotCertProvider "istiod" }} + - mountPath: /var/run/secrets/istio + name: istiod-ca-cert + {{- end }} + - mountPath: /var/lib/istio/data + name: istio-data + {{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/bootstrapOverride`) }} + - mountPath: /etc/istio/custom-bootstrap + name: custom-bootstrap-volume + {{- end }} + # SDS channel between istioagent and Envoy + - mountPath: /etc/istio/proxy + name: istio-envoy + - mountPath: /var/run/secrets/tokens + name: istio-token + {{- if .Values.global.mountMtlsCerts }} + # Use the key and cert mounted to /etc/certs/ for the in-cluster mTLS communications. + - mountPath: /etc/certs/ + name: istio-certs + readOnly: true + {{- end }} + - name: istio-podinfo + mountPath: /etc/istio/pod + {{- if and (eq .Values.global.proxy.tracer "lightstep") .ProxyConfig.GetTracing.GetTlsSettings }} + - mountPath: {{ directory .ProxyConfig.GetTracing.GetTlsSettings.GetCaCertificates }} + name: lightstep-certs + readOnly: true + {{- end }} + {{- if isset .ObjectMeta.Annotations `sidecar.istio.io/userVolumeMount` }} + {{ range $index, $value := fromJSON (index .ObjectMeta.Annotations `sidecar.istio.io/userVolumeMount`) }} + - name: "{{ $index }}" + {{ toYaml $value | indent 6 }} + {{ end }} + {{- end }} + volumes: + - emptyDir: + name: workload-socket + - emptyDir: + name: credential-socket + {{- if eq .Values.global.caName "GkeWorkloadCertificate" }} + - name: gke-workload-certificate + csi: + driver: workloadcertificates.security.cloud.google.com + {{- else }} + - emptyDir: + name: workload-certs + {{- end }} + {{- if (isset .ObjectMeta.Annotations `sidecar.istio.io/bootstrapOverride`) }} + - name: custom-bootstrap-volume + configMap: + name: {{ annotation .ObjectMeta `sidecar.istio.io/bootstrapOverride` "" }} + {{- end }} + # SDS channel between istioagent and Envoy + - emptyDir: + medium: Memory + name: istio-envoy + - name: istio-data + emptyDir: {} + - name: istio-podinfo + downwardAPI: + items: + - path: "labels" + fieldRef: + fieldPath: metadata.labels + - path: "annotations" + fieldRef: + fieldPath: metadata.annotations + - name: istio-token + projected: + sources: + - serviceAccountToken: + path: istio-token + expirationSeconds: 43200 + audience: {{ .Values.global.sds.token.aud }} + {{- if eq .Values.global.pilotCertProvider "istiod" }} + - name: istiod-ca-cert + {{- if eq (.Values.pilot.env).ENABLE_CLUSTER_TRUST_BUNDLE_API true }} + projected: + sources: + - clusterTrustBundle: + name: istio.io:istiod-ca:root-cert + path: root-cert.pem + {{- else }} + configMap: + name: istio-ca-root-cert + {{- end }} + {{- end }} + {{- if .Values.global.mountMtlsCerts }} + # Use the key and cert mounted to /etc/certs/ for the in-cluster mTLS communications. + - name: istio-certs + secret: + optional: true + {{ if eq .Spec.ServiceAccountName "" }} + secretName: istio.default + {{ else -}} + secretName: {{ printf "istio.%s" .Spec.ServiceAccountName }} + {{ end -}} + {{- end }} + {{- if isset .ObjectMeta.Annotations `sidecar.istio.io/userVolume` }} + {{range $index, $value := fromJSON (index .ObjectMeta.Annotations `sidecar.istio.io/userVolume`) }} + - name: "{{ $index }}" + {{ toYaml $value | indent 4 }} + {{ end }} + {{ end }} + {{- if and (eq .Values.global.proxy.tracer "lightstep") .ProxyConfig.GetTracing.GetTlsSettings }} + - name: lightstep-certs + secret: + optional: true + secretName: lightstep.cacert + {{- end }} + {{- if .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- range .Values.global.imagePullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} diff --git a/backing-services/istiod/files/kube-gateway.yaml b/backing-services/istiod/files/kube-gateway.yaml new file mode 100644 index 0000000..447ecae --- /dev/null +++ b/backing-services/istiod/files/kube-gateway.yaml @@ -0,0 +1,401 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{.ServiceAccount | quote}} + namespace: {{.Namespace | quote}} + annotations: + {{- toJsonMap (omit .InfrastructureAnnotations "kubectl.kubernetes.io/last-applied-configuration" "gateway.istio.io/name-override" "gateway.istio.io/service-account" "gateway.istio.io/controller-version") | nindent 4 }} + labels: + {{- toJsonMap + .InfrastructureLabels + (strdict + "gateway.networking.k8s.io/gateway-name" .Name + ) | nindent 4 }} + {{- if ge .KubeVersion 128 }} + # Safe since 1.28: https://github.com/kubernetes/kubernetes/pull/117412 + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1beta1 + kind: Gateway + name: "{{.Name}}" + uid: "{{.UID}}" + {{- end }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{.DeploymentName | quote}} + namespace: {{.Namespace | quote}} + annotations: + {{- toJsonMap (omit .InfrastructureAnnotations "kubectl.kubernetes.io/last-applied-configuration" "gateway.istio.io/name-override" "gateway.istio.io/service-account" "gateway.istio.io/controller-version") | nindent 4 }} + labels: + {{- toJsonMap + .InfrastructureLabels + (strdict + "gateway.networking.k8s.io/gateway-name" .Name + "gateway.istio.io/managed" "istio.io-gateway-controller" + ) | nindent 4 }} + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1beta1 + kind: Gateway + name: {{.Name}} + uid: "{{.UID}}" +spec: + selector: + matchLabels: + "{{.GatewayNameLabel}}": {{.Name}} + template: + metadata: + annotations: + {{- toJsonMap + (omit .InfrastructureAnnotations "kubectl.kubernetes.io/last-applied-configuration" "gateway.istio.io/name-override" "gateway.istio.io/service-account" "gateway.istio.io/controller-version") + (strdict "istio.io/rev" (.Revision | default "default")) + (strdict + "prometheus.io/path" "/stats/prometheus" + "prometheus.io/port" "15020" + "prometheus.io/scrape" "true" + ) | nindent 8 }} + labels: + {{- toJsonMap + (strdict + "sidecar.istio.io/inject" "false" + "service.istio.io/canonical-name" .DeploymentName + "service.istio.io/canonical-revision" "latest" + ) + .InfrastructureLabels + (strdict + "gateway.networking.k8s.io/gateway-name" .Name + "gateway.istio.io/managed" "istio.io-gateway-controller" + ) | nindent 8 }} + spec: + securityContext: + {{- if .Values.gateways.securityContext }} + {{- toYaml .Values.gateways.securityContext | nindent 8 }} + {{- else }} + sysctls: + - name: net.ipv4.ip_unprivileged_port_start + value: "0" + {{- if .Values.gateways.seccompProfile }} + seccompProfile: + {{- toYaml .Values.gateways.seccompProfile | nindent 10 }} + {{- end }} + {{- end }} + serviceAccountName: {{.ServiceAccount | quote}} + containers: + - name: istio-proxy + {{- if contains "/" (annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image) }} + image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image }}" + {{- else }} + image: "{{ .ProxyImage }}" + {{- end }} + {{- if .Values.global.proxy.resources }} + resources: + {{- toYaml .Values.global.proxy.resources | nindent 10 }} + {{- end }} + {{with .Values.global.imagePullPolicy }}imagePullPolicy: "{{.}}"{{end}} + securityContext: + capabilities: + drop: + - ALL + allowPrivilegeEscalation: false + privileged: false + readOnlyRootFilesystem: true + runAsUser: {{ .ProxyUID | default "1337" }} + runAsGroup: {{ .ProxyGID | default "1337" }} + runAsNonRoot: true + ports: + - containerPort: 15020 + name: metrics + protocol: TCP + - containerPort: 15021 + name: status-port + protocol: TCP + - containerPort: 15090 + protocol: TCP + name: http-envoy-prom + args: + - proxy + - router + - --domain + - $(POD_NAMESPACE).svc.{{ .Values.global.proxy.clusterDomain }} + - --proxyLogLevel + - {{ annotation .ObjectMeta `sidecar.istio.io/logLevel` .Values.global.proxy.logLevel | quote}} + - --proxyComponentLogLevel + - {{ annotation .ObjectMeta `sidecar.istio.io/componentLogLevel` .Values.global.proxy.componentLogLevel | quote}} + - --log_output_level + - {{ annotation .ObjectMeta `sidecar.istio.io/agentLogLevel` .Values.global.logging.level | quote}} + {{- if .Values.global.sts.servicePort }} + - --stsPort={{ .Values.global.sts.servicePort }} + {{- end }} + {{- if .Values.global.logAsJson }} + - --log_as_json + {{- end }} + {{- if .Values.global.proxy.lifecycle }} + lifecycle: + {{- toYaml .Values.global.proxy.lifecycle | nindent 10 }} + {{- end }} + env: + - name: PILOT_CERT_PROVIDER + value: {{ .Values.global.pilotCertProvider }} + - name: CA_ADDR + {{- if .Values.global.caAddress }} + value: {{ .Values.global.caAddress }} + {{- else }} + value: istiod{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }}.{{ .Values.global.istioNamespace }}.svc:15012 + {{- end }} + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: SERVICE_ACCOUNT + valueFrom: + fieldRef: + fieldPath: spec.serviceAccountName + - name: HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: ISTIO_CPU_LIMIT + valueFrom: + resourceFieldRef: + resource: limits.cpu + - name: PROXY_CONFIG + value: | + {{ protoToJSON .ProxyConfig }} + - name: ISTIO_META_POD_PORTS + value: "[]" + - name: ISTIO_META_APP_CONTAINERS + value: "" + - name: GOMEMLIMIT + valueFrom: + resourceFieldRef: + resource: limits.memory + - name: GOMAXPROCS + valueFrom: + resourceFieldRef: + resource: limits.cpu + - name: ISTIO_META_CLUSTER_ID + value: "{{ valueOrDefault .Values.global.multiCluster.clusterName .ClusterID }}" + - name: ISTIO_META_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: ISTIO_META_INTERCEPTION_MODE + value: "{{ .ProxyConfig.InterceptionMode.String }}" + {{- with (valueOrDefault (index .InfrastructureLabels "topology.istio.io/network") .Values.global.network) }} + - name: ISTIO_META_NETWORK + value: {{.|quote}} + {{- end }} + - name: ISTIO_META_WORKLOAD_NAME + value: {{.DeploymentName|quote}} + - name: ISTIO_META_OWNER + value: "kubernetes://apis/apps/v1/namespaces/{{.Namespace}}/deployments/{{.DeploymentName}}" + {{- if .Values.global.meshID }} + - name: ISTIO_META_MESH_ID + value: "{{ .Values.global.meshID }}" + {{- else if (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }} + - name: ISTIO_META_MESH_ID + value: "{{ (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }}" + {{- end }} + {{- with (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }} + - name: TRUST_DOMAIN + value: "{{ . }}" + {{- end }} + {{- range $key, $value := .ProxyConfig.ProxyMetadata }} + - name: {{ $key }} + value: "{{ $value }}" + {{- end }} + {{- with (index .InfrastructureLabels "topology.istio.io/network") }} + - name: ISTIO_META_REQUESTED_NETWORK_VIEW + value: {{.|quote}} + {{- end }} + startupProbe: + failureThreshold: 30 + httpGet: + path: /healthz/ready + port: 15021 + scheme: HTTP + initialDelaySeconds: 1 + periodSeconds: 1 + successThreshold: 1 + timeoutSeconds: 1 + readinessProbe: + failureThreshold: 4 + httpGet: + path: /healthz/ready + port: 15021 + scheme: HTTP + initialDelaySeconds: 0 + periodSeconds: 15 + successThreshold: 1 + timeoutSeconds: 1 + volumeMounts: + - name: workload-socket + mountPath: /var/run/secrets/workload-spiffe-uds + - name: credential-socket + mountPath: /var/run/secrets/credential-uds + {{- if eq .Values.global.caName "GkeWorkloadCertificate" }} + - name: gke-workload-certificate + mountPath: /var/run/secrets/workload-spiffe-credentials + readOnly: true + {{- else }} + - name: workload-certs + mountPath: /var/run/secrets/workload-spiffe-credentials + {{- end }} + {{- if eq .Values.global.pilotCertProvider "istiod" }} + - mountPath: /var/run/secrets/istio + name: istiod-ca-cert + {{- end }} + - mountPath: /var/lib/istio/data + name: istio-data + # SDS channel between istioagent and Envoy + - mountPath: /etc/istio/proxy + name: istio-envoy + - mountPath: /var/run/secrets/tokens + name: istio-token + - name: istio-podinfo + mountPath: /etc/istio/pod + volumes: + - emptyDir: {} + name: workload-socket + - emptyDir: {} + name: credential-socket + {{- if eq .Values.global.caName "GkeWorkloadCertificate" }} + - name: gke-workload-certificate + csi: + driver: workloadcertificates.security.cloud.google.com + {{- else}} + - emptyDir: {} + name: workload-certs + {{- end }} + # SDS channel between istioagent and Envoy + - emptyDir: + medium: Memory + name: istio-envoy + - name: istio-data + emptyDir: {} + - name: istio-podinfo + downwardAPI: + items: + - path: "labels" + fieldRef: + fieldPath: metadata.labels + - path: "annotations" + fieldRef: + fieldPath: metadata.annotations + - name: istio-token + projected: + sources: + - serviceAccountToken: + path: istio-token + expirationSeconds: 43200 + audience: {{ .Values.global.sds.token.aud }} + {{- if eq .Values.global.pilotCertProvider "istiod" }} + - name: istiod-ca-cert + {{- if eq ((.Values.pilot).env).ENABLE_CLUSTER_TRUST_BUNDLE_API true }} + projected: + sources: + - clusterTrustBundle: + name: istio.io:istiod-ca:root-cert + path: root-cert.pem + {{- else }} + configMap: + name: istio-ca-root-cert + {{- end }} + {{- end }} + {{- if .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- range .Values.global.imagePullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + {{ toJsonMap (omit .InfrastructureAnnotations "kubectl.kubernetes.io/last-applied-configuration" "gateway.istio.io/name-override" "gateway.istio.io/service-account" "gateway.istio.io/controller-version") | nindent 4 }} + labels: + {{- toJsonMap + .InfrastructureLabels + (strdict + "gateway.networking.k8s.io/gateway-name" .Name + ) | nindent 4 }} + name: {{.DeploymentName | quote}} + namespace: {{.Namespace | quote}} + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1beta1 + kind: Gateway + name: {{.Name}} + uid: {{.UID}} +spec: + ipFamilyPolicy: PreferDualStack + ports: + {{- range $key, $val := .Ports }} + - name: {{ $val.Name | quote }} + port: {{ $val.Port }} + protocol: TCP + appProtocol: {{ $val.AppProtocol }} + {{- end }} + selector: + "{{.GatewayNameLabel}}": {{.Name}} + {{- if and (.Spec.Addresses) (eq .ServiceType "LoadBalancer") }} + loadBalancerIP: {{ (index .Spec.Addresses 0).Value | quote}} + {{- end }} + type: {{ .ServiceType | quote }} +--- +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{.DeploymentName | quote}} + namespace: {{.Namespace | quote}} + annotations: + {{- toJsonMap (omit .InfrastructureAnnotations "kubectl.kubernetes.io/last-applied-configuration" "gateway.istio.io/name-override" "gateway.istio.io/service-account" "gateway.istio.io/controller-version") | nindent 4 }} + labels: + {{- toJsonMap + .InfrastructureLabels + (strdict + "gateway.networking.k8s.io/gateway-name" .Name + ) | nindent 4 }} + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1beta1 + kind: Gateway + name: {{.Name}} + uid: "{{.UID}}" +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{.DeploymentName | quote}} + maxReplicas: 1 +--- +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{.DeploymentName | quote}} + namespace: {{.Namespace | quote}} + annotations: + {{- toJsonMap (omit .InfrastructureAnnotations "kubectl.kubernetes.io/last-applied-configuration" "gateway.istio.io/name-override" "gateway.istio.io/service-account" "gateway.istio.io/controller-version") | nindent 4 }} + labels: + {{- toJsonMap + .InfrastructureLabels + (strdict + "gateway.networking.k8s.io/gateway-name" .Name + ) | nindent 4 }} + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1beta1 + kind: Gateway + name: {{.Name}} + uid: "{{.UID}}" +spec: + selector: + matchLabels: + gateway.networking.k8s.io/gateway-name: {{.Name|quote}} + diff --git a/backing-services/istiod/files/profile-ambient.yaml b/backing-services/istiod/files/profile-ambient.yaml new file mode 100644 index 0000000..2805fe4 --- /dev/null +++ b/backing-services/istiod/files/profile-ambient.yaml @@ -0,0 +1,17 @@ +# WARNING: DO NOT EDIT, THIS FILE IS A COPY. +# The original version of this file is located at /manifests/helm-profiles directory. +# If you want to make a change in this file, edit the original one and run "make gen". + +# The ambient profile enables ambient mode. The Istiod, CNI, and ztunnel charts must be deployed +meshConfig: + defaultConfig: + proxyMetadata: + ISTIO_META_ENABLE_HBONE: "true" +global: + variant: distroless +pilot: + env: + PILOT_ENABLE_AMBIENT: "true" +cni: + ambient: + enabled: true diff --git a/backing-services/istiod/files/profile-compatibility-version-1.23.yaml b/backing-services/istiod/files/profile-compatibility-version-1.23.yaml new file mode 100644 index 0000000..dac910f --- /dev/null +++ b/backing-services/istiod/files/profile-compatibility-version-1.23.yaml @@ -0,0 +1,25 @@ +# WARNING: DO NOT EDIT, THIS FILE IS A COPY. +# The original version of this file is located at /manifests/helm-profiles directory. +# If you want to make a change in this file, edit the original one and run "make gen". + +pilot: + env: + # 1.24 behavioral changes + ENABLE_INBOUND_RETRY_POLICY: "false" + EXCLUDE_UNSAFE_503_FROM_DEFAULT_RETRY: "false" + PREFER_DESTINATIONRULE_TLS_FOR_EXTERNAL_SERVICES: "false" + ENABLE_ENHANCED_DESTINATIONRULE_MERGE: "false" + PILOT_UNIFIED_SIDECAR_SCOPE: "false" + +meshConfig: + defaultConfig: + proxyMetadata: + # 1.24 behaviour changes + ENABLE_DEFERRED_STATS_CREATION: "false" + BYPASS_OVERLOAD_MANAGER_FOR_STATIC_LISTENERS: "false" + +ambient: + # Not present in <1.24, defaults to `true` in 1.25+ + reconcileIptablesOnStartup: false + # 1.26 behavioral changes + shareHostNetworkNamespace: true diff --git a/backing-services/istiod/files/profile-compatibility-version-1.24.yaml b/backing-services/istiod/files/profile-compatibility-version-1.24.yaml new file mode 100644 index 0000000..b211c82 --- /dev/null +++ b/backing-services/istiod/files/profile-compatibility-version-1.24.yaml @@ -0,0 +1,13 @@ +# WARNING: DO NOT EDIT, THIS FILE IS A COPY. +# The original version of this file is located at /manifests/helm-profiles directory. +# If you want to make a change in this file, edit the original one and run "make gen". + +pilot: + env: + # 1.24 behavioral changes + PILOT_ENABLE_IP_AUTOALLOCATE: "false" +ambient: + dnsCapture: false + reconcileIptablesOnStartup: false + # 1.26 behavioral changes + shareHostNetworkNamespace: true diff --git a/backing-services/istiod/files/profile-compatibility-version-1.25.yaml b/backing-services/istiod/files/profile-compatibility-version-1.25.yaml new file mode 100644 index 0000000..eb8827c --- /dev/null +++ b/backing-services/istiod/files/profile-compatibility-version-1.25.yaml @@ -0,0 +1,7 @@ +# WARNING: DO NOT EDIT, THIS FILE IS A COPY. +# The original version of this file is located at /manifests/helm-profiles directory. +# If you want to make a change in this file, edit the original one and run "make gen". + +ambient: + # 1.26 behavioral changes + shareHostNetworkNamespace: true diff --git a/backing-services/istiod/files/profile-demo.yaml b/backing-services/istiod/files/profile-demo.yaml new file mode 100644 index 0000000..d6dc36d --- /dev/null +++ b/backing-services/istiod/files/profile-demo.yaml @@ -0,0 +1,94 @@ +# WARNING: DO NOT EDIT, THIS FILE IS A COPY. +# The original version of this file is located at /manifests/helm-profiles directory. +# If you want to make a change in this file, edit the original one and run "make gen". + +# The demo profile enables a variety of things to try out Istio in non-production environments. +# * Lower resource utilization. +# * Some additional features are enabled by default; especially ones used in some tasks in istio.io. +# * More ports enabled on the ingress, which is used in some tasks. +meshConfig: + accessLogFile: /dev/stdout + extensionProviders: + - name: otel + envoyOtelAls: + service: opentelemetry-collector.observability.svc.cluster.local + port: 4317 + - name: skywalking + skywalking: + service: tracing.istio-system.svc.cluster.local + port: 11800 + - name: otel-tracing + opentelemetry: + port: 4317 + service: opentelemetry-collector.observability.svc.cluster.local + - name: jaeger + opentelemetry: + port: 4317 + service: jaeger-collector.istio-system.svc.cluster.local + +cni: + resources: + requests: + cpu: 10m + memory: 40Mi + +ztunnel: + resources: + requests: + cpu: 10m + memory: 40Mi + +global: + proxy: + resources: + requests: + cpu: 10m + memory: 40Mi + waypoint: + resources: + requests: + cpu: 10m + memory: 40Mi + +pilot: + autoscaleEnabled: false + traceSampling: 100 + resources: + requests: + cpu: 10m + memory: 100Mi + +gateways: + istio-egressgateway: + autoscaleEnabled: false + resources: + requests: + cpu: 10m + memory: 40Mi + istio-ingressgateway: + autoscaleEnabled: false + ports: + ## You can add custom gateway ports in user values overrides, but it must include those ports since helm replaces. + # Note that AWS ELB will by default perform health checks on the first port + # on this list. Setting this to the health check port will ensure that health + # checks always work. https://github.com/istio/istio/issues/12503 + - port: 15021 + targetPort: 15021 + name: status-port + - port: 80 + targetPort: 8080 + name: http2 + - port: 443 + targetPort: 8443 + name: https + - port: 31400 + targetPort: 31400 + name: tcp + # This is the port where sni routing happens + - port: 15443 + targetPort: 15443 + name: tls + resources: + requests: + cpu: 10m + memory: 40Mi \ No newline at end of file diff --git a/backing-services/istiod/files/profile-platform-gke.yaml b/backing-services/istiod/files/profile-platform-gke.yaml new file mode 100644 index 0000000..dfe8a7d --- /dev/null +++ b/backing-services/istiod/files/profile-platform-gke.yaml @@ -0,0 +1,10 @@ +# WARNING: DO NOT EDIT, THIS FILE IS A COPY. +# The original version of this file is located at /manifests/helm-profiles directory. +# If you want to make a change in this file, edit the original one and run "make gen". + +cni: + cniBinDir: "" # intentionally unset for gke to allow template-based autodetection to work + resourceQuotas: + enabled: true +resourceQuotas: + enabled: true diff --git a/backing-services/istiod/files/profile-platform-k3d.yaml b/backing-services/istiod/files/profile-platform-k3d.yaml new file mode 100644 index 0000000..cd86d9e --- /dev/null +++ b/backing-services/istiod/files/profile-platform-k3d.yaml @@ -0,0 +1,7 @@ +# WARNING: DO NOT EDIT, THIS FILE IS A COPY. +# The original version of this file is located at /manifests/helm-profiles directory. +# If you want to make a change in this file, edit the original one and run "make gen". + +cni: + cniConfDir: /var/lib/rancher/k3s/agent/etc/cni/net.d + cniBinDir: /bin diff --git a/backing-services/istiod/files/profile-platform-k3s.yaml b/backing-services/istiod/files/profile-platform-k3s.yaml new file mode 100644 index 0000000..0782010 --- /dev/null +++ b/backing-services/istiod/files/profile-platform-k3s.yaml @@ -0,0 +1,7 @@ +# WARNING: DO NOT EDIT, THIS FILE IS A COPY. +# The original version of this file is located at /manifests/helm-profiles directory. +# If you want to make a change in this file, edit the original one and run "make gen". + +cni: + cniConfDir: /var/lib/rancher/k3s/agent/etc/cni/net.d + cniBinDir: /var/lib/rancher/k3s/data/cni diff --git a/backing-services/istiod/files/profile-platform-microk8s.yaml b/backing-services/istiod/files/profile-platform-microk8s.yaml new file mode 100644 index 0000000..57d7f5e --- /dev/null +++ b/backing-services/istiod/files/profile-platform-microk8s.yaml @@ -0,0 +1,7 @@ +# WARNING: DO NOT EDIT, THIS FILE IS A COPY. +# The original version of this file is located at /manifests/helm-profiles directory. +# If you want to make a change in this file, edit the original one and run "make gen". + +cni: + cniConfDir: /var/snap/microk8s/current/args/cni-network + cniBinDir: /var/snap/microk8s/current/opt/cni/bin diff --git a/backing-services/istiod/files/profile-platform-minikube.yaml b/backing-services/istiod/files/profile-platform-minikube.yaml new file mode 100644 index 0000000..fa9992e --- /dev/null +++ b/backing-services/istiod/files/profile-platform-minikube.yaml @@ -0,0 +1,6 @@ +# WARNING: DO NOT EDIT, THIS FILE IS A COPY. +# The original version of this file is located at /manifests/helm-profiles directory. +# If you want to make a change in this file, edit the original one and run "make gen". + +cni: + cniNetnsDir: /var/run/docker/netns diff --git a/backing-services/istiod/files/profile-platform-openshift.yaml b/backing-services/istiod/files/profile-platform-openshift.yaml new file mode 100644 index 0000000..8ddc5e1 --- /dev/null +++ b/backing-services/istiod/files/profile-platform-openshift.yaml @@ -0,0 +1,19 @@ +# WARNING: DO NOT EDIT, THIS FILE IS A COPY. +# The original version of this file is located at /manifests/helm-profiles directory. +# If you want to make a change in this file, edit the original one and run "make gen". + +# The OpenShift profile provides a basic set of settings to run Istio on OpenShift +cni: + cniBinDir: /var/lib/cni/bin + cniConfDir: /etc/cni/multus/net.d + chained: false + cniConfFileName: "istio-cni.conf" + provider: "multus" +pilot: + cni: + enabled: true + provider: "multus" +seLinuxOptions: + type: spc_t +# Openshift requires privileged pods to run in kube-system +trustedZtunnelNamespace: "kube-system" diff --git a/backing-services/istiod/files/profile-preview.yaml b/backing-services/istiod/files/profile-preview.yaml new file mode 100644 index 0000000..181d7bd --- /dev/null +++ b/backing-services/istiod/files/profile-preview.yaml @@ -0,0 +1,13 @@ +# WARNING: DO NOT EDIT, THIS FILE IS A COPY. +# The original version of this file is located at /manifests/helm-profiles directory. +# If you want to make a change in this file, edit the original one and run "make gen". + +# The preview profile contains features that are experimental. +# This is intended to explore new features coming to Istio. +# Stability, security, and performance are not guaranteed - use at your own risk. +meshConfig: + defaultConfig: + proxyMetadata: + # Enable Istio agent to handle DNS requests for known hosts + # Unknown hosts will automatically be resolved using upstream dns servers in resolv.conf + ISTIO_META_DNS_CAPTURE: "true" diff --git a/backing-services/istiod/files/profile-remote.yaml b/backing-services/istiod/files/profile-remote.yaml new file mode 100644 index 0000000..d17b9a8 --- /dev/null +++ b/backing-services/istiod/files/profile-remote.yaml @@ -0,0 +1,13 @@ +# WARNING: DO NOT EDIT, THIS FILE IS A COPY. +# The original version of this file is located at /manifests/helm-profiles directory. +# If you want to make a change in this file, edit the original one and run "make gen". + +# The remote profile enables installing istio with a remote control plane. The `base` and `istio-discovery` charts must be deployed with this profile. +istiodRemote: + enabled: true +configMap: false +telemetry: + enabled: false +global: + # TODO BML maybe a different profile for a configcluster/revisit this + omitSidecarInjectorConfigMap: true diff --git a/backing-services/istiod/files/profile-stable.yaml b/backing-services/istiod/files/profile-stable.yaml new file mode 100644 index 0000000..358282e --- /dev/null +++ b/backing-services/istiod/files/profile-stable.yaml @@ -0,0 +1,8 @@ +# WARNING: DO NOT EDIT, THIS FILE IS A COPY. +# The original version of this file is located at /manifests/helm-profiles directory. +# If you want to make a change in this file, edit the original one and run "make gen". + +# The stable profile deploys admission control to ensure that only stable resources and fields are used +# THIS IS CURRENTLY EXPERIMENTAL AND SUBJECT TO CHANGE +experimental: + stableValidationPolicy: true diff --git a/backing-services/istiod/files/waypoint.yaml b/backing-services/istiod/files/waypoint.yaml new file mode 100644 index 0000000..421cabe --- /dev/null +++ b/backing-services/istiod/files/waypoint.yaml @@ -0,0 +1,396 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{.ServiceAccount | quote}} + namespace: {{.Namespace | quote}} + annotations: + {{- toJsonMap (omit .InfrastructureAnnotations "kubectl.kubernetes.io/last-applied-configuration" "gateway.istio.io/name-override" "gateway.istio.io/service-account" "gateway.istio.io/controller-version") | nindent 4 }} + labels: + {{- toJsonMap + .InfrastructureLabels + (strdict + "gateway.networking.k8s.io/gateway-name" .Name + ) | nindent 4 }} + {{- if ge .KubeVersion 128 }} + # Safe since 1.28: https://github.com/kubernetes/kubernetes/pull/117412 + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1beta1 + kind: Gateway + name: "{{.Name}}" + uid: "{{.UID}}" + {{- end }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{.DeploymentName | quote}} + namespace: {{.Namespace | quote}} + annotations: + {{- toJsonMap (omit .InfrastructureAnnotations "kubectl.kubernetes.io/last-applied-configuration" "gateway.istio.io/name-override" "gateway.istio.io/service-account" "gateway.istio.io/controller-version") | nindent 4 }} + labels: + {{- toJsonMap + .InfrastructureLabels + (strdict + "gateway.networking.k8s.io/gateway-name" .Name + "gateway.istio.io/managed" "istio.io-mesh-controller" + ) | nindent 4 }} + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1beta1 + kind: Gateway + name: "{{.Name}}" + uid: "{{.UID}}" +spec: + selector: + matchLabels: + "{{.GatewayNameLabel}}": "{{.Name}}" + template: + metadata: + annotations: + {{- toJsonMap + (omit .InfrastructureAnnotations "kubectl.kubernetes.io/last-applied-configuration" "gateway.istio.io/name-override" "gateway.istio.io/service-account" "gateway.istio.io/controller-version") + (strdict "istio.io/rev" (.Revision | default "default")) + (strdict + "prometheus.io/path" "/stats/prometheus" + "prometheus.io/port" "15020" + "prometheus.io/scrape" "true" + ) | nindent 8 }} + labels: + {{- toJsonMap + (strdict + "sidecar.istio.io/inject" "false" + "istio.io/dataplane-mode" "none" + "service.istio.io/canonical-name" .DeploymentName + "service.istio.io/canonical-revision" "latest" + ) + .InfrastructureLabels + (strdict + "gateway.networking.k8s.io/gateway-name" .Name + "gateway.istio.io/managed" "istio.io-mesh-controller" + ) | nindent 8}} + spec: + {{- if .Values.global.waypoint.affinity }} + affinity: + {{- toYaml .Values.global.waypoint.affinity | nindent 8 }} + {{- end }} + {{- if .Values.global.waypoint.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml .Values.global.waypoint.topologySpreadConstraints | nindent 8 }} + {{- end }} + {{- if .Values.global.waypoint.nodeSelector }} + nodeSelector: + {{- toYaml .Values.global.waypoint.nodeSelector | nindent 8 }} + {{- end }} + {{- if .Values.global.waypoint.tolerations }} + tolerations: + {{- toYaml .Values.global.waypoint.tolerations | nindent 8 }} + {{- end }} + terminationGracePeriodSeconds: 2 + serviceAccountName: {{.ServiceAccount | quote}} + containers: + - name: istio-proxy + ports: + - containerPort: 15020 + name: metrics + protocol: TCP + - containerPort: 15021 + name: status-port + protocol: TCP + - containerPort: 15090 + protocol: TCP + name: http-envoy-prom + {{- if contains "/" (annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image) }} + image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image }}" + {{- else }} + image: "{{ .ProxyImage }}" + {{- end }} + {{with .Values.global.imagePullPolicy }}imagePullPolicy: "{{.}}"{{end}} + args: + - proxy + - waypoint + - --domain + - $(POD_NAMESPACE).svc.{{ .Values.global.proxy.clusterDomain }} + - --serviceCluster + - {{.ServiceAccount}}.$(POD_NAMESPACE) + - --proxyLogLevel + - {{ annotation .ObjectMeta `sidecar.istio.io/logLevel` .Values.global.proxy.logLevel | quote}} + - --proxyComponentLogLevel + - {{ annotation .ObjectMeta `sidecar.istio.io/componentLogLevel` .Values.global.proxy.componentLogLevel | quote}} + - --log_output_level + - {{ annotation .ObjectMeta `sidecar.istio.io/agentLogLevel` .Values.global.logging.level | quote}} + {{- if .Values.global.logAsJson }} + - --log_as_json + {{- end }} + {{- if .Values.global.proxy.outlierLogPath }} + - --outlierLogPath={{ .Values.global.proxy.outlierLogPath }} + {{- end}} + env: + - name: ISTIO_META_SERVICE_ACCOUNT + valueFrom: + fieldRef: + fieldPath: spec.serviceAccountName + - name: ISTIO_META_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: PILOT_CERT_PROVIDER + value: {{ .Values.global.pilotCertProvider }} + - name: CA_ADDR + {{- if .Values.global.caAddress }} + value: {{ .Values.global.caAddress }} + {{- else }} + value: istiod{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }}.{{ .Values.global.istioNamespace }}.svc:15012 + {{- end }} + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: SERVICE_ACCOUNT + valueFrom: + fieldRef: + fieldPath: spec.serviceAccountName + - name: HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: ISTIO_CPU_LIMIT + valueFrom: + resourceFieldRef: + resource: limits.cpu + - name: PROXY_CONFIG + value: | + {{ protoToJSON .ProxyConfig }} + {{- if .ProxyConfig.ProxyMetadata }} + {{- range $key, $value := .ProxyConfig.ProxyMetadata }} + - name: {{ $key }} + value: "{{ $value }}" + {{- end }} + {{- end }} + - name: GOMEMLIMIT + valueFrom: + resourceFieldRef: + resource: limits.memory + - name: GOMAXPROCS + valueFrom: + resourceFieldRef: + resource: limits.cpu + - name: ISTIO_META_CLUSTER_ID + value: "{{ valueOrDefault .Values.global.multiCluster.clusterName `Kubernetes` }}" + {{- $network := valueOrDefault (index .InfrastructureLabels `topology.istio.io/network`) .Values.global.network }} + {{- if $network }} + - name: ISTIO_META_NETWORK + value: "{{ $network }}" + {{- end }} + - name: ISTIO_META_INTERCEPTION_MODE + value: REDIRECT + - name: ISTIO_META_WORKLOAD_NAME + value: {{.DeploymentName}} + - name: ISTIO_META_OWNER + value: kubernetes://apis/apps/v1/namespaces/{{.Namespace}}/deployments/{{.DeploymentName}} + {{- if .Values.global.meshID }} + - name: ISTIO_META_MESH_ID + value: "{{ .Values.global.meshID }}" + {{- else if (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }} + - name: ISTIO_META_MESH_ID + value: "{{ (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }}" + {{- end }} + {{- with (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }} + - name: TRUST_DOMAIN + value: "{{ . }}" + {{- end }} + {{- if .Values.global.waypoint.resources }} + resources: + {{- toYaml .Values.global.waypoint.resources | nindent 10 }} + {{- end }} + startupProbe: + failureThreshold: 30 + httpGet: + path: /healthz/ready + port: 15021 + scheme: HTTP + initialDelaySeconds: 1 + periodSeconds: 1 + successThreshold: 1 + timeoutSeconds: 1 + readinessProbe: + failureThreshold: 4 + httpGet: + path: /healthz/ready + port: 15021 + scheme: HTTP + initialDelaySeconds: 0 + periodSeconds: 15 + successThreshold: 1 + timeoutSeconds: 1 + securityContext: + privileged: false + {{- if not (eq .Values.global.platform "openshift") }} + runAsGroup: 1337 + runAsUser: 1337 + {{- end }} + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: + - ALL +{{- if .Values.gateways.seccompProfile }} + seccompProfile: +{{- toYaml .Values.gateways.seccompProfile | nindent 12 }} +{{- end }} + volumeMounts: + - mountPath: /var/run/secrets/workload-spiffe-uds + name: workload-socket + - mountPath: /var/run/secrets/istio + name: istiod-ca-cert + - mountPath: /var/lib/istio/data + name: istio-data + - mountPath: /etc/istio/proxy + name: istio-envoy + - mountPath: /var/run/secrets/tokens + name: istio-token + - mountPath: /etc/istio/pod + name: istio-podinfo + volumes: + - emptyDir: {} + name: workload-socket + - emptyDir: + medium: Memory + name: istio-envoy + - emptyDir: + medium: Memory + name: go-proxy-envoy + - emptyDir: {} + name: istio-data + - emptyDir: {} + name: go-proxy-data + - downwardAPI: + items: + - fieldRef: + fieldPath: metadata.labels + path: labels + - fieldRef: + fieldPath: metadata.annotations + path: annotations + name: istio-podinfo + - name: istio-token + projected: + sources: + - serviceAccountToken: + audience: istio-ca + expirationSeconds: 43200 + path: istio-token + - name: istiod-ca-cert + {{- if eq (.Values.pilot.env).ENABLE_CLUSTER_TRUST_BUNDLE_API true }} + projected: + sources: + - clusterTrustBundle: + name: istio.io:istiod-ca:root-cert + path: root-cert.pem + {{- else }} + configMap: + name: istio-ca-root-cert + {{- end }} + {{- if .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- range .Values.global.imagePullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + {{ toJsonMap + (strdict "networking.istio.io/traffic-distribution" "PreferClose") + (omit .InfrastructureAnnotations + "kubectl.kubernetes.io/last-applied-configuration" + "gateway.istio.io/name-override" + "gateway.istio.io/service-account" + "gateway.istio.io/controller-version" + ) | nindent 4 }} + labels: + {{- toJsonMap + .InfrastructureLabels + (strdict + "gateway.networking.k8s.io/gateway-name" .Name + ) | nindent 4 }} + name: {{.DeploymentName | quote}} + namespace: {{.Namespace | quote}} + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1beta1 + kind: Gateway + name: "{{.Name}}" + uid: "{{.UID}}" +spec: + ipFamilyPolicy: PreferDualStack + ports: + {{- range $key, $val := .Ports }} + - name: {{ $val.Name | quote }} + port: {{ $val.Port }} + protocol: TCP + appProtocol: {{ $val.AppProtocol }} + {{- end }} + selector: + "{{.GatewayNameLabel}}": "{{.Name}}" + {{- if and (.Spec.Addresses) (eq .ServiceType "LoadBalancer") }} + loadBalancerIP: {{ (index .Spec.Addresses 0).Value | quote}} + {{- end }} + type: {{ .ServiceType | quote }} +--- +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{.DeploymentName | quote}} + namespace: {{.Namespace | quote}} + annotations: + {{- toJsonMap (omit .InfrastructureAnnotations "kubectl.kubernetes.io/last-applied-configuration" "gateway.istio.io/name-override" "gateway.istio.io/service-account" "gateway.istio.io/controller-version") | nindent 4 }} + labels: + {{- toJsonMap + .InfrastructureLabels + (strdict + "gateway.networking.k8s.io/gateway-name" .Name + ) | nindent 4 }} + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1beta1 + kind: Gateway + name: {{.Name}} + uid: "{{.UID}}" +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{.DeploymentName | quote}} + maxReplicas: 1 +--- +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{.DeploymentName | quote}} + namespace: {{.Namespace | quote}} + annotations: + {{- toJsonMap (omit .InfrastructureAnnotations "kubectl.kubernetes.io/last-applied-configuration" "gateway.istio.io/name-override" "gateway.istio.io/service-account" "gateway.istio.io/controller-version") | nindent 4 }} + labels: + {{- toJsonMap + .InfrastructureLabels + (strdict + "gateway.networking.k8s.io/gateway-name" .Name + ) | nindent 4 }} + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1beta1 + kind: Gateway + name: {{.Name}} + uid: "{{.UID}}" +spec: + selector: + matchLabels: + gateway.networking.k8s.io/gateway-name: {{.Name|quote}} + diff --git a/backing-services/istiod/templates/NOTES.txt b/backing-services/istiod/templates/NOTES.txt new file mode 100644 index 0000000..0d07ea7 --- /dev/null +++ b/backing-services/istiod/templates/NOTES.txt @@ -0,0 +1,82 @@ +"istiod{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }}" successfully installed! + +To learn more about the release, try: + $ helm status {{ .Release.Name }} -n {{ .Release.Namespace }} + $ helm get all {{ .Release.Name }} -n {{ .Release.Namespace }} + +Next steps: +{{- $profile := default "" .Values.profile }} +{{- if (eq $profile "ambient") }} + * Get started with ambient: https://istio.io/latest/docs/ops/ambient/getting-started/ + * Review ambient's architecture: https://istio.io/latest/docs/ops/ambient/architecture/ +{{- else }} + * Deploy a Gateway: https://istio.io/latest/docs/setup/additional-setup/gateway/ + * Try out our tasks to get started on common configurations: + * https://istio.io/latest/docs/tasks/traffic-management + * https://istio.io/latest/docs/tasks/security/ + * https://istio.io/latest/docs/tasks/policy-enforcement/ +{{- end }} + * Review the list of actively supported releases, CVE publications and our hardening guide: + * https://istio.io/latest/docs/releases/supported-releases/ + * https://istio.io/latest/news/security/ + * https://istio.io/latest/docs/ops/best-practices/security/ + +For further documentation see https://istio.io website + +{{- + $deps := dict + "global.outboundTrafficPolicy" "meshConfig.outboundTrafficPolicy" + "global.certificates" "meshConfig.certificates" + "global.localityLbSetting" "meshConfig.localityLbSetting" + "global.policyCheckFailOpen" "meshConfig.policyCheckFailOpen" + "global.enableTracing" "meshConfig.enableTracing" + "global.proxy.accessLogFormat" "meshConfig.accessLogFormat" + "global.proxy.accessLogFile" "meshConfig.accessLogFile" + "global.proxy.concurrency" "meshConfig.defaultConfig.concurrency" + "global.proxy.envoyAccessLogService" "meshConfig.defaultConfig.envoyAccessLogService" + "global.proxy.envoyAccessLogService.enabled" "meshConfig.enableEnvoyAccessLogService" + "global.proxy.envoyMetricsService" "meshConfig.defaultConfig.envoyMetricsService" + "global.proxy.protocolDetectionTimeout" "meshConfig.protocolDetectionTimeout" + "global.proxy.holdApplicationUntilProxyStarts" "meshConfig.defaultConfig.holdApplicationUntilProxyStarts" + "pilot.ingress" "meshConfig.ingressService, meshConfig.ingressControllerMode, and meshConfig.ingressClass" + "global.mtls.enabled" "the PeerAuthentication resource" + "global.mtls.auto" "meshConfig.enableAutoMtls" + "global.tracer.lightstep.address" "meshConfig.defaultConfig.tracing.lightstep.address" + "global.tracer.lightstep.accessToken" "meshConfig.defaultConfig.tracing.lightstep.accessToken" + "global.tracer.zipkin.address" "meshConfig.defaultConfig.tracing.zipkin.address" + "global.tracer.datadog.address" "meshConfig.defaultConfig.tracing.datadog.address" + "global.meshExpansion.enabled" "Gateway and other Istio networking resources, such as in samples/multicluster/" + "istiocoredns.enabled" "the in-proxy DNS capturing (ISTIO_META_DNS_CAPTURE)" +}} +{{- range $dep, $replace := $deps }} +{{- /* Complex logic to turn the string above into a null-safe traversal like ((.Values.global).certificates */}} +{{- $res := tpl (print "{{" (repeat (split "." $dep | len) "(") ".Values." (replace "." ")." $dep) ")}}") $}} +{{- if not (eq $res "")}} +WARNING: {{$dep|quote}} is deprecated; use {{$replace|quote}} instead. +{{- end }} +{{- end }} +{{- + $failDeps := dict + "telemetry.v2.prometheus.configOverride" + "telemetry.v2.stackdriver.configOverride" + "telemetry.v2.stackdriver.disableOutbound" + "telemetry.v2.stackdriver.outboundAccessLogging" + "global.tracer.stackdriver.debug" "meshConfig.defaultConfig.tracing.stackdriver.debug" + "global.tracer.stackdriver.maxNumberOfAttributes" "meshConfig.defaultConfig.tracing.stackdriver.maxNumberOfAttributes" + "global.tracer.stackdriver.maxNumberOfAnnotations" "meshConfig.defaultConfig.tracing.stackdriver.maxNumberOfAnnotations" + "global.tracer.stackdriver.maxNumberOfMessageEvents" "meshConfig.defaultConfig.tracing.stackdriver.maxNumberOfMessageEvents" + "meshConfig.defaultConfig.tracing.stackdriver.debug" "Istio supported tracers" + "meshConfig.defaultConfig.tracing.stackdriver.maxNumberOfAttributes" "Istio supported tracers" + "meshConfig.defaultConfig.tracing.stackdriver.maxNumberOfAnnotations" "Istio supported tracers" + "meshConfig.defaultConfig.tracing.stackdriver.maxNumberOfMessageEvents" "Istio supported tracers" +}} +{{- range $dep, $replace := $failDeps }} +{{- /* Complex logic to turn the string above into a null-safe traversal like ((.Values.global).certificates */}} +{{- $res := tpl (print "{{" (repeat (split "." $dep | len) "(") ".Values." (replace "." ")." $dep) ")}}") $}} +{{- if not (eq $res "")}} +{{fail (print $dep " is removed")}} +{{- end }} +{{- end }} +{{- if eq $.Values.global.pilotCertProvider "kubernetes" }} +{{- fail "pilotCertProvider=kubernetes is not supported" }} +{{- end }} \ No newline at end of file diff --git a/backing-services/istiod/templates/_helpers.tpl b/backing-services/istiod/templates/_helpers.tpl new file mode 100644 index 0000000..042c925 --- /dev/null +++ b/backing-services/istiod/templates/_helpers.tpl @@ -0,0 +1,23 @@ +{{/* Default Prometheus is enabled if its enabled and there are no config overrides set */}} +{{ define "default-prometheus" }} +{{- and + (not .Values.meshConfig.defaultProviders) + .Values.telemetry.enabled .Values.telemetry.v2.enabled .Values.telemetry.v2.prometheus.enabled +}} +{{- end }} + +{{/* SD has metrics and logging split. Default metrics are enabled if SD is enabled */}} +{{ define "default-sd-metrics" }} +{{- and + (not .Values.meshConfig.defaultProviders) + .Values.telemetry.enabled .Values.telemetry.v2.enabled .Values.telemetry.v2.stackdriver.enabled +}} +{{- end }} + +{{/* SD has metrics and logging split. */}} +{{ define "default-sd-logs" }} +{{- and + (not .Values.meshConfig.defaultProviders) + .Values.telemetry.enabled .Values.telemetry.v2.enabled .Values.telemetry.v2.stackdriver.enabled +}} +{{- end }} diff --git a/backing-services/istiod/templates/autoscale.yaml b/backing-services/istiod/templates/autoscale.yaml new file mode 100644 index 0000000..363a834 --- /dev/null +++ b/backing-services/istiod/templates/autoscale.yaml @@ -0,0 +1,44 @@ +# Not created if istiod is running remotely +{{- if not .Values.istiodRemote.enabled }} +{{- if and .Values.autoscaleEnabled .Values.autoscaleMin .Values.autoscaleMax }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: istiod{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }} + namespace: {{ .Release.Namespace }} + labels: + app: istiod + release: {{ .Release.Name }} + istio.io/rev: {{ .Values.revision | default "default" | quote }} + install.operator.istio.io/owning-resource: {{ .Values.ownerName | default "unknown" }} + operator.istio.io/component: "Pilot" + app.kubernetes.io/name: "istiod" + {{- include "istio.labels" . | nindent 4 }} +spec: + maxReplicas: {{ .Values.autoscaleMax }} + minReplicas: {{ .Values.autoscaleMin }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: istiod{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }} + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.cpu.targetAverageUtilization }} + {{- if .Values.memory.targetAverageUtilization }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.memory.targetAverageUtilization }} + {{- end }} + {{- if .Values.autoscaleBehavior }} + behavior: {{ toYaml .Values.autoscaleBehavior | nindent 4 }} + {{- end }} +--- +{{- end }} +{{- end }} diff --git a/backing-services/istiod/templates/clusterrole.yaml b/backing-services/istiod/templates/clusterrole.yaml new file mode 100644 index 0000000..f515760 --- /dev/null +++ b/backing-services/istiod/templates/clusterrole.yaml @@ -0,0 +1,206 @@ +# Created if this is not a remote istiod, OR if it is and is also a config cluster +{{- if or (and .Values.istiodRemote.enabled .Values.global.configCluster) (not .Values.istiodRemote.enabled) }} +{{ $mcsAPIGroup := or .Values.env.MCS_API_GROUP "multicluster.x-k8s.io" }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: istiod-clusterrole{{- if not (eq .Values.revision "")}}-{{ .Values.revision }}{{- end }}-{{ .Release.Namespace }} + labels: + app: istiod + release: {{ .Release.Name }} + app.kubernetes.io/name: "istiod" + {{- include "istio.labels" . | nindent 4 }} +rules: + # sidecar injection controller + - apiGroups: ["admissionregistration.k8s.io"] + resources: ["mutatingwebhookconfigurations"] + verbs: ["get", "list", "watch", "update", "patch"] + + # configuration validation webhook controller + - apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations"] + verbs: ["get", "list", "watch", "update"] + + # istio configuration + # removing CRD permissions can break older versions of Istio running alongside this control plane (https://github.com/istio/istio/issues/29382) + # please proceed with caution + - apiGroups: ["config.istio.io", "security.istio.io", "networking.istio.io", "authentication.istio.io", "rbac.istio.io", "telemetry.istio.io", "extensions.istio.io"] + verbs: ["get", "watch", "list"] + resources: ["*"] +{{- if .Values.global.istiod.enableAnalysis }} + - apiGroups: ["config.istio.io", "security.istio.io", "networking.istio.io", "authentication.istio.io", "rbac.istio.io", "telemetry.istio.io", "extensions.istio.io"] + verbs: ["update", "patch"] + resources: + - authorizationpolicies/status + - destinationrules/status + - envoyfilters/status + - gateways/status + - peerauthentications/status + - proxyconfigs/status + - requestauthentications/status + - serviceentries/status + - sidecars/status + - telemetries/status + - virtualservices/status + - wasmplugins/status + - workloadentries/status + - workloadgroups/status +{{- end }} + - apiGroups: ["networking.istio.io"] + verbs: [ "get", "watch", "list", "update", "patch", "create", "delete" ] + resources: [ "workloadentries" ] + - apiGroups: ["networking.istio.io"] + verbs: [ "get", "watch", "list", "update", "patch", "create", "delete" ] + resources: [ "workloadentries/status", "serviceentries/status" ] + - apiGroups: ["security.istio.io"] + verbs: [ "get", "watch", "list", "update", "patch", "create", "delete" ] + resources: [ "authorizationpolicies/status" ] + - apiGroups: [""] + verbs: [ "get", "watch", "list", "update", "patch", "create", "delete" ] + resources: [ "services/status" ] + + # auto-detect installed CRD definitions + - apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch"] + + # discovery and routing + - apiGroups: [""] + resources: ["pods", "nodes", "services", "namespaces", "endpoints"] + verbs: ["get", "list", "watch"] + - apiGroups: ["discovery.k8s.io"] + resources: ["endpointslices"] + verbs: ["get", "list", "watch"] + +{{- if .Values.taint.enabled }} + - apiGroups: [""] + resources: ["nodes"] + verbs: ["patch"] +{{- end }} + + # ingress controller +{{- if .Values.global.istiod.enableAnalysis }} + - apiGroups: ["extensions", "networking.k8s.io"] + resources: ["ingresses"] + verbs: ["get", "list", "watch"] + - apiGroups: ["extensions", "networking.k8s.io"] + resources: ["ingresses/status"] + verbs: ["*"] +{{- end}} + - apiGroups: ["networking.k8s.io"] + resources: ["ingresses", "ingressclasses"] + verbs: ["get", "list", "watch"] + - apiGroups: ["networking.k8s.io"] + resources: ["ingresses/status"] + verbs: ["*"] + + # required for CA's namespace controller + - apiGroups: [""] + resources: ["configmaps"] + verbs: ["create", "get", "list", "watch", "update"] + + # Istiod and bootstrap. +{{- $omitCertProvidersForClusterRole := list "istiod" "custom" "none"}} +{{- if or .Values.env.EXTERNAL_CA (not (has .Values.global.pilotCertProvider $omitCertProvidersForClusterRole)) }} + - apiGroups: ["certificates.k8s.io"] + resources: + - "certificatesigningrequests" + - "certificatesigningrequests/approval" + - "certificatesigningrequests/status" + verbs: ["update", "create", "get", "delete", "watch"] + - apiGroups: ["certificates.k8s.io"] + resources: + - "signers" + resourceNames: +{{- range .Values.global.certSigners }} + - {{ . | quote }} +{{- end }} + verbs: ["approve"] +{{- end}} +{{- if eq (.Values.env).ENABLE_CLUSTER_TRUST_BUNDLE_API true }} + - apiGroups: ["certificates.k8s.io"] + resources: ["clustertrustbundles"] + verbs: ["update", "create", "delete"] + - apiGroups: ["certificates.k8s.io"] + resources: ["signers"] + resourceNames: ["istio.io/istiod-ca"] + verbs: ["attest"] +{{- end }} + + # Used by Istiod to verify the JWT tokens + - apiGroups: ["authentication.k8s.io"] + resources: ["tokenreviews"] + verbs: ["create"] + + # Used by Istiod to verify gateway SDS + - apiGroups: ["authorization.k8s.io"] + resources: ["subjectaccessreviews"] + verbs: ["create"] + + # Use for Kubernetes Service APIs + - apiGroups: ["gateway.networking.k8s.io", "gateway.networking.x-k8s.io"] + resources: ["*"] + verbs: ["get", "watch", "list"] + - apiGroups: ["gateway.networking.x-k8s.io"] + resources: + - xbackendtrafficpolicies/status + verbs: ["update", "patch"] + - apiGroups: ["gateway.networking.k8s.io"] + resources: + - backendtlspolicies/status + - gatewayclasses/status + - gateways/status + - grpcroutes/status + - httproutes/status + - referencegrants/status + - tcproutes/status + - tlsroutes/status + - udproutes/status + verbs: ["update", "patch"] + - apiGroups: ["gateway.networking.k8s.io"] + resources: ["gatewayclasses"] + verbs: ["create", "update", "patch", "delete"] + + # Needed for multicluster secret reading, possibly ingress certs in the future + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "watch", "list"] + + # Used for MCS serviceexport management + - apiGroups: ["{{ $mcsAPIGroup }}"] + resources: ["serviceexports"] + verbs: [ "get", "watch", "list", "create", "delete"] + + # Used for MCS serviceimport management + - apiGroups: ["{{ $mcsAPIGroup }}"] + resources: ["serviceimports"] + verbs: ["get", "watch", "list"] +--- +{{- if not (eq (toString .Values.env.PILOT_ENABLE_GATEWAY_API_DEPLOYMENT_CONTROLLER) "false") }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: istiod-gateway-controller{{- if not (eq .Values.revision "")}}-{{ .Values.revision }}{{- end }}-{{ .Release.Namespace }} + labels: + app: istiod + release: {{ .Release.Name }} + app.kubernetes.io/name: "istiod" + {{- include "istio.labels" . | nindent 4 }} +rules: + - apiGroups: ["apps"] + verbs: [ "get", "watch", "list", "update", "patch", "create", "delete" ] + resources: [ "deployments" ] + - apiGroups: ["autoscaling"] + verbs: [ "get", "watch", "list", "update", "patch", "create", "delete" ] + resources: [ "horizontalpodautoscalers" ] + - apiGroups: ["policy"] + verbs: [ "get", "watch", "list", "update", "patch", "create", "delete" ] + resources: [ "poddisruptionbudgets" ] + - apiGroups: [""] + verbs: [ "get", "watch", "list", "update", "patch", "create", "delete" ] + resources: [ "services" ] + - apiGroups: [""] + verbs: [ "get", "watch", "list", "update", "patch", "create", "delete" ] + resources: [ "serviceaccounts"] +{{- end }} +{{- end }} diff --git a/backing-services/istiod/templates/clusterrolebinding.yaml b/backing-services/istiod/templates/clusterrolebinding.yaml new file mode 100644 index 0000000..10781b4 --- /dev/null +++ b/backing-services/istiod/templates/clusterrolebinding.yaml @@ -0,0 +1,40 @@ +# Created if this is not a remote istiod, OR if it is and is also a config cluster +{{- if or (and .Values.istiodRemote.enabled .Values.global.configCluster) (not .Values.istiodRemote.enabled) }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: istiod-clusterrole{{- if not (eq .Values.revision "")}}-{{ .Values.revision }}{{- end }}-{{ .Release.Namespace }} + labels: + app: istiod + release: {{ .Release.Name }} + app.kubernetes.io/name: "istiod" + {{- include "istio.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istiod-clusterrole{{- if not (eq .Values.revision "")}}-{{ .Values.revision }}{{- end }}-{{ .Release.Namespace }} +subjects: + - kind: ServiceAccount + name: istiod{{- if not (eq .Values.revision "")}}-{{ .Values.revision }}{{- end }} + namespace: {{ .Values.global.istioNamespace }} +--- +{{- if not (eq (toString .Values.env.PILOT_ENABLE_GATEWAY_API_DEPLOYMENT_CONTROLLER) "false") }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: istiod-gateway-controller{{- if not (eq .Values.revision "")}}-{{ .Values.revision }}{{- end }}-{{ .Release.Namespace }} + labels: + app: istiod + release: {{ .Release.Name }} + app.kubernetes.io/name: "istiod" + {{- include "istio.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istiod-gateway-controller{{- if not (eq .Values.revision "")}}-{{ .Values.revision }}{{- end }}-{{ .Release.Namespace }} +subjects: +- kind: ServiceAccount + name: istiod{{- if not (eq .Values.revision "")}}-{{ .Values.revision }}{{- end }} + namespace: {{ .Values.global.istioNamespace }} +{{- end }} +{{- end }} diff --git a/backing-services/istiod/templates/configmap-jwks.yaml b/backing-services/istiod/templates/configmap-jwks.yaml new file mode 100644 index 0000000..6d4ce6c --- /dev/null +++ b/backing-services/istiod/templates/configmap-jwks.yaml @@ -0,0 +1,19 @@ +# Not created if istiod is running remotely +{{- if not .Values.istiodRemote.enabled }} +{{- if .Values.jwksResolverExtraRootCA }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: pilot-jwks-extra-cacerts{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }} + namespace: {{ .Release.Namespace }} + labels: + release: {{ .Release.Name }} + istio.io/rev: {{ .Values.revision | default "default" | quote }} + install.operator.istio.io/owning-resource: {{ .Values.ownerName | default "unknown" }} + operator.istio.io/component: "Pilot" + app.kubernetes.io/name: "istiod" + {{- include "istio.labels" . | nindent 4 }} +data: + extra.pem: {{ .Values.jwksResolverExtraRootCA | quote }} +{{- end }} +{{- end }} diff --git a/backing-services/istiod/templates/configmap-values.yaml b/backing-services/istiod/templates/configmap-values.yaml new file mode 100644 index 0000000..a7e6036 --- /dev/null +++ b/backing-services/istiod/templates/configmap-values.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: values{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }} + namespace: {{ .Release.Namespace }} + annotations: + kubernetes.io/description: This ConfigMap contains the Helm values used during chart rendering. This ConfigMap is rendered for debugging purposes and external tooling; modifying these values has no effect. + labels: + istio.io/rev: {{ .Values.revision | default "default" | quote }} + install.operator.istio.io/owning-resource: {{ .Values.ownerName | default "unknown" }} + operator.istio.io/component: "Pilot" + release: {{ .Release.Name }} + app.kubernetes.io/name: "istiod" + {{- include "istio.labels" . | nindent 4 }} +data: + original-values: |- +{{ .Values._original | toPrettyJson | indent 4 }} +{{- $_ := unset $.Values "_original" }} + merged-values: |- +{{ .Values | toPrettyJson | indent 4 }} diff --git a/backing-services/istiod/templates/configmap.yaml b/backing-services/istiod/templates/configmap.yaml new file mode 100644 index 0000000..5b73699 --- /dev/null +++ b/backing-services/istiod/templates/configmap.yaml @@ -0,0 +1,107 @@ +{{- define "mesh" }} + # The trust domain corresponds to the trust root of a system. + # Refer to https://github.com/spiffe/spiffe/blob/master/standards/SPIFFE-ID.md#21-trust-domain + trustDomain: "cluster.local" + + # The namespace to treat as the administrative root namespace for Istio configuration. + # When processing a leaf namespace Istio will search for declarations in that namespace first + # and if none are found it will search in the root namespace. Any matching declaration found in the root namespace + # is processed as if it were declared in the leaf namespace. + rootNamespace: {{ .Values.meshConfig.rootNamespace | default .Values.global.istioNamespace }} + + {{ $prom := include "default-prometheus" . | eq "true" }} + {{ $sdMetrics := include "default-sd-metrics" . | eq "true" }} + {{ $sdLogs := include "default-sd-logs" . | eq "true" }} + {{- if or $prom $sdMetrics $sdLogs }} + defaultProviders: + {{- if or $prom $sdMetrics }} + metrics: + {{ if $prom }}- prometheus{{ end }} + {{ if and $sdMetrics $sdLogs }}- stackdriver{{ end }} + {{- end }} + {{- if and $sdMetrics $sdLogs }} + accessLogging: + - stackdriver + {{- end }} + {{- end }} + + defaultConfig: + {{- if .Values.global.meshID }} + meshId: "{{ .Values.global.meshID }}" + {{- end }} + {{- with (.Values.global.proxy.variant | default .Values.global.variant) }} + image: + imageType: {{. | quote}} + {{- end }} + {{- if not (eq .Values.global.proxy.tracer "none") }} + tracing: + {{- if eq .Values.global.proxy.tracer "lightstep" }} + lightstep: + # Address of the LightStep Satellite pool + address: {{ .Values.global.tracer.lightstep.address }} + # Access Token used to communicate with the Satellite pool + accessToken: {{ .Values.global.tracer.lightstep.accessToken }} + {{- else if eq .Values.global.proxy.tracer "zipkin" }} + zipkin: + # Address of the Zipkin collector + address: {{ ((.Values.global.tracer).zipkin).address | default (print "zipkin." .Values.global.istioNamespace ":9411") }} + {{- else if eq .Values.global.proxy.tracer "datadog" }} + datadog: + # Address of the Datadog Agent + address: {{ ((.Values.global.tracer).datadog).address | default "$(HOST_IP):8126" }} + {{- else if eq .Values.global.proxy.tracer "stackdriver" }} + stackdriver: + # enables trace output to stdout. + debug: {{ (($.Values.global.tracer).stackdriver).debug | default "false" }} + # The global default max number of attributes per span. + maxNumberOfAttributes: {{ (($.Values.global.tracer).stackdriver).maxNumberOfAttributes | default "200" }} + # The global default max number of annotation events per span. + maxNumberOfAnnotations: {{ (($.Values.global.tracer).stackdriver).maxNumberOfAnnotations | default "200" }} + # The global default max number of message events per span. + maxNumberOfMessageEvents: {{ (($.Values.global.tracer).stackdriver).maxNumberOfMessageEvents | default "200" }} + {{- end }} + {{- end }} + {{- if .Values.global.remotePilotAddress }} + discoveryAddress: {{ printf "istiod.%s.svc" .Release.Namespace }}:15012 + {{- else }} + discoveryAddress: istiod{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }}.{{.Release.Namespace}}.svc:15012 + {{- end }} +{{- end }} + +{{/* We take the mesh config above, defined with individual values.yaml, and merge with .Values.meshConfig */}} +{{/* The intent here is that meshConfig.foo becomes the API, rather than re-inventing the API in values.yaml */}} +{{- $originalMesh := include "mesh" . | fromYaml }} +{{- $mesh := mergeOverwrite $originalMesh .Values.meshConfig }} + +{{- if .Values.configMap }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: istio{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }} + namespace: {{ .Release.Namespace }} + labels: + istio.io/rev: {{ .Values.revision | default "default" | quote }} + install.operator.istio.io/owning-resource: {{ .Values.ownerName | default "unknown" }} + operator.istio.io/component: "Pilot" + release: {{ .Release.Name }} + app.kubernetes.io/name: "istiod" + {{- include "istio.labels" . | nindent 4 }} +data: + + # Configuration file for the mesh networks to be used by the Split Horizon EDS. + meshNetworks: |- + {{- if .Values.global.meshNetworks }} + networks: +{{ toYaml .Values.global.meshNetworks | trim | indent 6 }} + {{- else }} + networks: {} + {{- end }} + + mesh: |- +{{- if .Values.meshConfig }} +{{ $mesh | toYaml | indent 4 }} +{{- else }} +{{- include "mesh" . }} +{{- end }} +--- +{{- end }} diff --git a/backing-services/istiod/templates/deployment.yaml b/backing-services/istiod/templates/deployment.yaml new file mode 100644 index 0000000..408eae7 --- /dev/null +++ b/backing-services/istiod/templates/deployment.yaml @@ -0,0 +1,306 @@ +# Not created if istiod is running remotely +{{- if not .Values.istiodRemote.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: istiod{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }} + namespace: {{ .Release.Namespace }} + labels: + app: istiod + istio.io/rev: {{ .Values.revision | default "default" | quote }} + install.operator.istio.io/owning-resource: {{ .Values.ownerName | default "unknown" }} + operator.istio.io/component: "Pilot" + istio: pilot + release: {{ .Release.Name }} + app.kubernetes.io/name: "istiod" + {{- include "istio.labels" . | nindent 4 }} +{{- range $key, $val := .Values.deploymentLabels }} + {{ $key }}: "{{ $val }}" +{{- end }} +spec: +{{- if not .Values.autoscaleEnabled }} +{{- if .Values.replicaCount }} + replicas: {{ .Values.replicaCount }} +{{- end }} +{{- end }} + strategy: + rollingUpdate: + maxSurge: {{ .Values.rollingMaxSurge }} + maxUnavailable: {{ .Values.rollingMaxUnavailable }} + selector: + matchLabels: + {{- if ne .Values.revision "" }} + app: istiod + istio.io/rev: {{ .Values.revision | default "default" | quote }} + {{- else }} + istio: pilot + {{- end }} + template: + metadata: + labels: + app: istiod + istio.io/rev: {{ .Values.revision | default "default" | quote }} + install.operator.istio.io/owning-resource: {{ .Values.ownerName | default "unknown" }} + sidecar.istio.io/inject: "false" + operator.istio.io/component: "Pilot" + {{- if ne .Values.revision "" }} + istio: istiod + {{- else }} + istio: pilot + {{- end }} + {{- range $key, $val := .Values.podLabels }} + {{ $key }}: "{{ $val }}" + {{- end }} + istio.io/dataplane-mode: none + app.kubernetes.io/name: "istiod" + {{- include "istio.labels" . | nindent 8 }} + annotations: + prometheus.io/port: "15014" + prometheus.io/scrape: "true" + sidecar.istio.io/inject: "false" + {{- if .Values.podAnnotations }} +{{ toYaml .Values.podAnnotations | indent 8 }} + {{- end }} + spec: +{{- if .Values.nodeSelector }} + nodeSelector: +{{ toYaml .Values.nodeSelector | indent 8 }} +{{- end }} +{{- with .Values.affinity }} + affinity: +{{- toYaml . | nindent 8 }} +{{- end }} + tolerations: + - key: cni.istio.io/not-ready + operator: "Exists" +{{- with .Values.tolerations }} +{{- toYaml . | nindent 8 }} +{{- end }} +{{- with .Values.topologySpreadConstraints }} + topologySpreadConstraints: +{{- toYaml . | nindent 8 }} +{{- end }} + serviceAccountName: istiod{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }} +{{- if .Values.global.priorityClassName }} + priorityClassName: "{{ .Values.global.priorityClassName }}" +{{- end }} +{{- with .Values.initContainers }} + initContainers: + {{- tpl (toYaml .) $ | nindent 8 }} +{{- end }} + containers: + - name: discovery +{{- if contains "/" .Values.image }} + image: "{{ .Values.image }}" +{{- else }} + image: "{{ .Values.hub | default .Values.global.hub }}/{{ .Values.image | default "pilot" }}:{{ .Values.tag | default .Values.global.tag }}{{with (.Values.variant | default .Values.global.variant)}}-{{.}}{{end}}" +{{- end }} +{{- if .Values.global.imagePullPolicy }} + imagePullPolicy: {{ .Values.global.imagePullPolicy }} +{{- end }} + args: + - "discovery" + - --monitoringAddr=:15014 +{{- if .Values.global.logging.level }} + - --log_output_level={{ .Values.global.logging.level }} +{{- end}} +{{- if .Values.global.logAsJson }} + - --log_as_json +{{- end }} + - --domain + - {{ .Values.global.proxy.clusterDomain }} +{{- if .Values.taint.namespace }} + - --cniNamespace={{ .Values.taint.namespace }} +{{- end }} + - --keepaliveMaxServerConnectionAge + - "{{ .Values.keepaliveMaxServerConnectionAge }}" +{{- if .Values.extraContainerArgs }} + {{- with .Values.extraContainerArgs }} + {{- toYaml . | nindent 10 }} + {{- end }} +{{- end }} + ports: + - containerPort: 8080 + protocol: TCP + name: http-debug + - containerPort: 15010 + protocol: TCP + name: grpc-xds + - containerPort: 15012 + protocol: TCP + name: tls-xds + - containerPort: 15017 + protocol: TCP + name: https-webhooks + - containerPort: 15014 + protocol: TCP + name: http-monitoring + readinessProbe: + httpGet: + path: /ready + port: 8080 + initialDelaySeconds: 1 + periodSeconds: 3 + timeoutSeconds: 5 + env: + - name: REVISION + value: "{{ .Values.revision | default `default` }}" + - name: PILOT_CERT_PROVIDER + value: {{ .Values.global.pilotCertProvider }} + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: SERVICE_ACCOUNT + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.serviceAccountName + - name: KUBECONFIG + value: /var/run/secrets/remote/config + # If you explicitly told us where ztunnel lives, use that. + # Otherwise, assume it lives in our namespace + # Also, check for an explicit ENV override (legacy approach) and prefer that + # if present + {{ $ztTrustedNS := or .Values.trustedZtunnelNamespace .Release.Namespace }} + {{ $ztTrustedName := or .Values.trustedZtunnelName "ztunnel" }} + {{- if not .Values.env.CA_TRUSTED_NODE_ACCOUNTS }} + - name: CA_TRUSTED_NODE_ACCOUNTS + value: "{{ $ztTrustedNS }}/{{ $ztTrustedName }}" + {{- end }} + {{- if .Values.env }} + {{- range $key, $val := .Values.env }} + - name: {{ $key }} + value: "{{ $val }}" + {{- end }} + {{- end }} + {{- with .Values.envVarFrom }} + {{- toYaml . | nindent 10 }} + {{- end }} +{{- if .Values.traceSampling }} + - name: PILOT_TRACE_SAMPLING + value: "{{ .Values.traceSampling }}" +{{- end }} +# If externalIstiod is set via Values.Global, then enable the pilot env variable. However, if it's set via Values.pilot.env, then +# don't set it here to avoid duplication. +# TODO (nshankar13): Move from Helm chart to code: https://github.com/istio/istio/issues/52449 +{{- if and .Values.global.externalIstiod (not (and .Values.env .Values.env.EXTERNAL_ISTIOD)) }} + - name: EXTERNAL_ISTIOD + value: "{{ .Values.global.externalIstiod }}" +{{- end }} + - name: PILOT_ENABLE_ANALYSIS + value: "{{ .Values.global.istiod.enableAnalysis }}" + - name: CLUSTER_ID + value: "{{ $.Values.global.multiCluster.clusterName | default `Kubernetes` }}" + - name: GOMEMLIMIT + valueFrom: + resourceFieldRef: + resource: limits.memory + divisor: "1" + - name: GOMAXPROCS + valueFrom: + resourceFieldRef: + resource: limits.cpu + divisor: "1" + - name: PLATFORM + value: "{{ coalesce .Values.global.platform .Values.platform }}" + resources: +{{- if .Values.resources }} +{{ toYaml .Values.resources | trim | indent 12 }} +{{- else }} +{{ toYaml .Values.global.defaultResources | trim | indent 12 }} +{{- end }} + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: + - ALL +{{- if .Values.seccompProfile }} + seccompProfile: +{{ toYaml .Values.seccompProfile | trim | indent 14 }} +{{- end }} + volumeMounts: + - name: istio-token + mountPath: /var/run/secrets/tokens + readOnly: true + - name: local-certs + mountPath: /var/run/secrets/istio-dns + - name: cacerts + mountPath: /etc/cacerts + readOnly: true + - name: istio-kubeconfig + mountPath: /var/run/secrets/remote + readOnly: true + {{- if .Values.jwksResolverExtraRootCA }} + - name: extracacerts + mountPath: /cacerts + {{- end }} + - name: istio-csr-dns-cert + mountPath: /var/run/secrets/istiod/tls + readOnly: true + - name: istio-csr-ca-configmap + mountPath: /var/run/secrets/istiod/ca + readOnly: true + {{- with .Values.volumeMounts }} + {{- toYaml . | nindent 10 }} + {{- end }} + volumes: + # Technically not needed on this pod - but it helps debugging/testing SDS + # Should be removed after everything works. + - emptyDir: + medium: Memory + name: local-certs + - name: istio-token + projected: + sources: + - serviceAccountToken: + audience: {{ .Values.global.sds.token.aud }} + expirationSeconds: 43200 + path: istio-token + # Optional: user-generated root + - name: cacerts + secret: + secretName: cacerts + optional: true + - name: istio-kubeconfig + secret: + secretName: istio-kubeconfig + optional: true + # Optional: istio-csr dns pilot certs + - name: istio-csr-dns-cert + secret: + secretName: istiod-tls + optional: true + - name: istio-csr-ca-configmap + {{- if eq (.Values.env).ENABLE_CLUSTER_TRUST_BUNDLE_API true }} + projected: + sources: + - clusterTrustBundle: + name: istio.io:istiod-ca:root-cert + path: root-cert.pem + optional: true + {{- else }} + configMap: + name: istio-ca-root-cert + defaultMode: 420 + optional: true + {{- end }} + {{- if .Values.jwksResolverExtraRootCA }} + - name: extracacerts + configMap: + name: pilot-jwks-extra-cacerts{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }} + {{- end }} + {{- with .Values.volumes }} + {{- toYaml . | nindent 6}} + {{- end }} + +--- +{{- end }} diff --git a/backing-services/istiod/templates/gateway-class-configmap.yaml b/backing-services/istiod/templates/gateway-class-configmap.yaml new file mode 100644 index 0000000..06e343f --- /dev/null +++ b/backing-services/istiod/templates/gateway-class-configmap.yaml @@ -0,0 +1,21 @@ +{{ range $key, $value := .Values.gatewayClasses }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: istio-{{ $.Values.revision | default "default" }}-gatewayclass-{{$key}} + namespace: {{ $.Release.Namespace }} + labels: + istio.io/rev: {{ $.Values.revision | default "default" | quote }} + install.operator.istio.io/owning-resource: {{ $.Values.ownerName | default "unknown" }} + operator.istio.io/component: "Pilot" + release: {{ $.Release.Name }} + app.kubernetes.io/name: "istiod" + gateway.istio.io/defaults-for-class: {{$key|quote}} + {{- include "istio.labels" $ | nindent 4 }} +data: +{{ range $kind, $overlay := $value }} + {{$kind}}: | +{{$overlay|toYaml|trim|indent 4}} +{{ end }} +--- +{{ end }} diff --git a/backing-services/istiod/templates/istiod-injector-configmap.yaml b/backing-services/istiod/templates/istiod-injector-configmap.yaml new file mode 100644 index 0000000..27b2c85 --- /dev/null +++ b/backing-services/istiod/templates/istiod-injector-configmap.yaml @@ -0,0 +1,82 @@ +{{- if not .Values.global.omitSidecarInjectorConfigMap }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: istio-sidecar-injector{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }} + namespace: {{ .Release.Namespace }} + labels: + istio.io/rev: {{ .Values.revision | default "default" | quote }} + install.operator.istio.io/owning-resource: {{ .Values.ownerName | default "unknown" }} + operator.istio.io/component: "Pilot" + release: {{ .Release.Name }} + app.kubernetes.io/name: "istiod" + {{- include "istio.labels" . | nindent 4 }} +data: +{{/* Scope the values to just top level fields used in the template, to reduce the size. */}} + values: |- +{{ $vals := pick .Values "global" "sidecarInjectorWebhook" "revision" -}} +{{ $pilotVals := pick .Values "cni" "env" -}} +{{ $vals = set $vals "pilot" $pilotVals -}} +{{ $gatewayVals := pick .Values.gateways "securityContext" "seccompProfile" -}} +{{ $vals = set $vals "gateways" $gatewayVals -}} +{{ $vals | toPrettyJson | indent 4 }} + + # To disable injection: use omitSidecarInjectorConfigMap, which disables the webhook patching + # and istiod webhook functionality. + # + # New fields should not use Values - it is a 'primary' config object, users should be able + # to fine tune it or use it with kube-inject. + config: |- + # defaultTemplates defines the default template to use for pods that do not explicitly specify a template + {{- if .Values.sidecarInjectorWebhook.defaultTemplates }} + defaultTemplates: +{{- range .Values.sidecarInjectorWebhook.defaultTemplates}} + - {{ . }} +{{- end }} + {{- else }} + defaultTemplates: [sidecar] + {{- end }} + policy: {{ .Values.global.proxy.autoInject }} + alwaysInjectSelector: +{{ toYaml .Values.sidecarInjectorWebhook.alwaysInjectSelector | trim | indent 6 }} + neverInjectSelector: +{{ toYaml .Values.sidecarInjectorWebhook.neverInjectSelector | trim | indent 6 }} + injectedAnnotations: + {{- range $key, $val := .Values.sidecarInjectorWebhook.injectedAnnotations }} + "{{ $key }}": {{ $val | quote }} + {{- end }} + {{- /* If someone ends up with this new template, but an older Istiod image, they will attempt to render this template + which will fail with "Pod injection failed: template: inject:1: function "Istio_1_9_Required_Template_And_Version_Mismatched" not defined". + This should make it obvious that their installation is broken. + */}} + template: {{ `{{ Template_Version_And_Istio_Version_Mismatched_Check_Installation }}` | quote }} + templates: +{{- if not (hasKey .Values.sidecarInjectorWebhook.templates "sidecar") }} + sidecar: | +{{ .Files.Get "files/injection-template.yaml" | trim | indent 8 }} +{{- end }} +{{- if not (hasKey .Values.sidecarInjectorWebhook.templates "gateway") }} + gateway: | +{{ .Files.Get "files/gateway-injection-template.yaml" | trim | indent 8 }} +{{- end }} +{{- if not (hasKey .Values.sidecarInjectorWebhook.templates "grpc-simple") }} + grpc-simple: | +{{ .Files.Get "files/grpc-simple.yaml" | trim | indent 8 }} +{{- end }} +{{- if not (hasKey .Values.sidecarInjectorWebhook.templates "grpc-agent") }} + grpc-agent: | +{{ .Files.Get "files/grpc-agent.yaml" | trim | indent 8 }} +{{- end }} +{{- if not (hasKey .Values.sidecarInjectorWebhook.templates "waypoint") }} + waypoint: | +{{ .Files.Get "files/waypoint.yaml" | trim | indent 8 }} +{{- end }} +{{- if not (hasKey .Values.sidecarInjectorWebhook.templates "kube-gateway") }} + kube-gateway: | +{{ .Files.Get "files/kube-gateway.yaml" | trim | indent 8 }} +{{- end }} +{{- with .Values.sidecarInjectorWebhook.templates }} +{{ toYaml . | trim | indent 6 }} +{{- end }} + +{{- end }} diff --git a/backing-services/istiod/templates/mutatingwebhook.yaml b/backing-services/istiod/templates/mutatingwebhook.yaml new file mode 100644 index 0000000..c1428bf --- /dev/null +++ b/backing-services/istiod/templates/mutatingwebhook.yaml @@ -0,0 +1,165 @@ +# TODO BML istiodRemote.injectionURL is invalid to set if `istiodRemote.enabled` is false, we should express that. +{{- /* Core defines the common configuration used by all webhook segments */}} +{{/* Copy just what we need to avoid expensive deepCopy */}} +{{- $whv := dict + "revision" .Values.revision + "injectionPath" .Values.istiodRemote.injectionPath + "injectionURL" .Values.istiodRemote.injectionURL + "reinvocationPolicy" .Values.sidecarInjectorWebhook.reinvocationPolicy + "caBundle" .Values.istiodRemote.injectionCABundle + "namespace" .Release.Namespace }} +{{- define "core" }} +{{- /* Kubernetes unfortunately requires a unique name for the webhook in some newer versions, so we assign +a unique prefix to each. */}} +- name: {{.Prefix}}sidecar-injector.istio.io + clientConfig: + {{- if .injectionURL }} + url: "{{ .injectionURL }}" + {{- else }} + service: + name: istiod{{- if not (eq .revision "") }}-{{ .revision }}{{- end }} + namespace: {{ .namespace }} + path: "{{ .injectionPath }}" + port: 443 + {{- end }} + {{- if .caBundle }} + caBundle: "{{ .caBundle }}" + {{- end }} + sideEffects: None + rules: + - operations: [ "CREATE" ] + apiGroups: [""] + apiVersions: ["v1"] + resources: ["pods"] + failurePolicy: Fail + reinvocationPolicy: "{{ .reinvocationPolicy }}" + admissionReviewVersions: ["v1"] +{{- end }} +{{- /* Installed for each revision - not installed for cluster resources ( cluster roles, bindings, crds) */}} +{{- if not .Values.global.operatorManageWebhooks }} +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: +{{- if eq .Release.Namespace "istio-system"}} + name: istio-sidecar-injector{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }} +{{- else }} + name: istio-sidecar-injector{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }}-{{ .Release.Namespace }} +{{- end }} + labels: + istio.io/rev: {{ .Values.revision | default "default" | quote }} + install.operator.istio.io/owning-resource: {{ .Values.ownerName | default "unknown" }} + operator.istio.io/component: "Pilot" + app: sidecar-injector + release: {{ .Release.Name }} + app.kubernetes.io/name: "istiod" + {{- include "istio.labels" . | nindent 4 }} +{{- if $.Values.sidecarInjectorWebhookAnnotations }} + annotations: +{{ toYaml $.Values.sidecarInjectorWebhookAnnotations | indent 4 }} +{{- end }} +webhooks: +{{- /* Set up the selectors. First section is for revision, rest is for "default" revision */}} + +{{- /* Case 1: namespace selector matches, and object doesn't disable */}} +{{- /* Note: if both revision and legacy selector, we give precedence to the legacy one */}} +{{- include "core" (mergeOverwrite (deepCopy $whv) (dict "Prefix" "rev.namespace.") ) }} + namespaceSelector: + matchExpressions: + - key: istio.io/rev + operator: In + values: + {{- if (eq .Values.revision "") }} + - "default" + {{- else }} + - "{{ .Values.revision }}" + {{- end }} + - key: istio-injection + operator: DoesNotExist + objectSelector: + matchExpressions: + - key: sidecar.istio.io/inject + operator: NotIn + values: + - "false" + +{{- /* Case 2: No namespace selector, but object selects our revision (and doesn't disable) */}} +{{- include "core" (mergeOverwrite (deepCopy $whv) (dict "Prefix" "rev.object.") ) }} + namespaceSelector: + matchExpressions: + - key: istio.io/rev + operator: DoesNotExist + - key: istio-injection + operator: DoesNotExist + objectSelector: + matchExpressions: + - key: sidecar.istio.io/inject + operator: NotIn + values: + - "false" + - key: istio.io/rev + operator: In + values: + {{- if (eq .Values.revision "") }} + - "default" + {{- else }} + - "{{ .Values.revision }}" + {{- end }} + + +{{- /* Webhooks for default revision */}} +{{- if (eq .Values.revision "") }} + +{{- /* Case 1: Namespace selector enabled, and object selector is not injected */}} +{{- include "core" (mergeOverwrite (deepCopy $whv) (dict "Prefix" "namespace.") ) }} + namespaceSelector: + matchExpressions: + - key: istio-injection + operator: In + values: + - enabled + objectSelector: + matchExpressions: + - key: sidecar.istio.io/inject + operator: NotIn + values: + - "false" + +{{- /* Case 2: no namespace label, but object selector is enabled (and revision label is not, which has priority) */}} +{{- include "core" (mergeOverwrite (deepCopy $whv) (dict "Prefix" "object.") ) }} + namespaceSelector: + matchExpressions: + - key: istio-injection + operator: DoesNotExist + - key: istio.io/rev + operator: DoesNotExist + objectSelector: + matchExpressions: + - key: sidecar.istio.io/inject + operator: In + values: + - "true" + - key: istio.io/rev + operator: DoesNotExist + +{{- if .Values.sidecarInjectorWebhook.enableNamespacesByDefault }} +{{- /* Special case 3: no labels at all */}} +{{- include "core" (mergeOverwrite (deepCopy $whv) (dict "Prefix" "auto.") ) }} + namespaceSelector: + matchExpressions: + - key: istio-injection + operator: DoesNotExist + - key: istio.io/rev + operator: DoesNotExist + - key: "kubernetes.io/metadata.name" + operator: "NotIn" + values: ["kube-system","kube-public","kube-node-lease","local-path-storage"] + objectSelector: + matchExpressions: + - key: sidecar.istio.io/inject + operator: DoesNotExist + - key: istio.io/rev + operator: DoesNotExist +{{- end }} + +{{- end }} +{{- end }} diff --git a/backing-services/istiod/templates/poddisruptionbudget.yaml b/backing-services/istiod/templates/poddisruptionbudget.yaml new file mode 100644 index 0000000..8ba27dc --- /dev/null +++ b/backing-services/istiod/templates/poddisruptionbudget.yaml @@ -0,0 +1,30 @@ +# Not created if istiod is running remotely +{{- if not .Values.istiodRemote.enabled }} +{{- if .Values.global.defaultPodDisruptionBudget.enabled }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: istiod{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }} + namespace: {{ .Release.Namespace }} + labels: + app: istiod + istio.io/rev: {{ .Values.revision | default "default" | quote }} + install.operator.istio.io/owning-resource: {{ .Values.ownerName | default "unknown" }} + operator.istio.io/component: "Pilot" + release: {{ .Release.Name }} + istio: pilot + app.kubernetes.io/name: "istiod" + {{- include "istio.labels" . | nindent 4 }} +spec: + minAvailable: 1 + selector: + matchLabels: + app: istiod + {{- if ne .Values.revision "" }} + istio.io/rev: {{ .Values.revision | quote }} + {{- else }} + istio: pilot + {{- end }} +--- +{{- end }} +{{- end }} diff --git a/backing-services/istiod/templates/reader-clusterrole.yaml b/backing-services/istiod/templates/reader-clusterrole.yaml new file mode 100644 index 0000000..4707c7e --- /dev/null +++ b/backing-services/istiod/templates/reader-clusterrole.yaml @@ -0,0 +1,64 @@ +{{ $mcsAPIGroup := or .Values.env.MCS_API_GROUP "multicluster.x-k8s.io" }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: istio-reader-clusterrole{{- if not (eq .Values.revision "")}}-{{ .Values.revision }}{{- end }}-{{ .Release.Namespace }} + labels: + app: istio-reader + release: {{ .Release.Name }} + app.kubernetes.io/name: "istio-reader" + {{- include "istio.labels" . | nindent 4 }} +rules: + - apiGroups: + - "config.istio.io" + - "security.istio.io" + - "networking.istio.io" + - "authentication.istio.io" + - "rbac.istio.io" + - "telemetry.istio.io" + - "extensions.istio.io" + resources: ["*"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + # TODO(keithmattix): See if we can conditionally give permission to read secrets and configmaps iff externalIstiod + # is enabled. Best I can tell, these two resources are only needed for configuring proxy TLS (i.e. CA certs). + resources: ["endpoints", "pods", "services", "nodes", "replicationcontrollers", "namespaces", "secrets", "configmaps"] + verbs: ["get", "list", "watch"] + - apiGroups: ["networking.istio.io"] + verbs: [ "get", "watch", "list" ] + resources: [ "workloadentries" ] + - apiGroups: ["networking.x-k8s.io", "gateway.networking.k8s.io"] + resources: ["gateways"] + verbs: ["get", "watch", "list"] + - apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch"] + - apiGroups: ["discovery.k8s.io"] + resources: ["endpointslices"] + verbs: ["get", "list", "watch"] + - apiGroups: ["{{ $mcsAPIGroup }}"] + resources: ["serviceexports"] + verbs: ["get", "list", "watch", "create", "delete"] + - apiGroups: ["{{ $mcsAPIGroup }}"] + resources: ["serviceimports"] + verbs: ["get", "list", "watch"] + - apiGroups: ["apps"] + resources: ["replicasets"] + verbs: ["get", "list", "watch"] + - apiGroups: ["authentication.k8s.io"] + resources: ["tokenreviews"] + verbs: ["create"] + - apiGroups: ["authorization.k8s.io"] + resources: ["subjectaccessreviews"] + verbs: ["create"] +{{- if .Values.istiodRemote.enabled }} + - apiGroups: [""] + resources: ["configmaps"] + verbs: ["create", "get", "list", "watch", "update"] + - apiGroups: ["admissionregistration.k8s.io"] + resources: ["mutatingwebhookconfigurations"] + verbs: ["get", "list", "watch", "update", "patch"] + - apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations"] + verbs: ["get", "list", "watch", "update"] +{{- end}} diff --git a/backing-services/istiod/templates/reader-clusterrolebinding.yaml b/backing-services/istiod/templates/reader-clusterrolebinding.yaml new file mode 100644 index 0000000..aea9f01 --- /dev/null +++ b/backing-services/istiod/templates/reader-clusterrolebinding.yaml @@ -0,0 +1,17 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: istio-reader-clusterrole{{- if not (eq .Values.revision "")}}-{{ .Values.revision }}{{- end }}-{{ .Release.Namespace }} + labels: + app: istio-reader + release: {{ .Release.Name }} + app.kubernetes.io/name: "istio-reader" + {{- include "istio.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-reader-clusterrole{{- if not (eq .Values.revision "")}}-{{ .Values.revision }}{{- end }}-{{ .Release.Namespace }} +subjects: + - kind: ServiceAccount + name: istio-reader-service-account + namespace: {{ .Values.global.istioNamespace }} diff --git a/backing-services/istiod/templates/remote-istiod-endpoints.yaml b/backing-services/istiod/templates/remote-istiod-endpoints.yaml new file mode 100644 index 0000000..a6de571 --- /dev/null +++ b/backing-services/istiod/templates/remote-istiod-endpoints.yaml @@ -0,0 +1,25 @@ +# This file is only used for remote `istiod` installs. +{{- if .Values.istiodRemote.enabled }} +# if the remotePilotAddress is an IP addr +{{- if regexMatch "^([0-9]*\\.){3}[0-9]*$" .Values.global.remotePilotAddress }} +apiVersion: v1 +kind: Endpoints +metadata: + name: istiod{{- if .Values.revision }}-{{ .Values.revision}}{{- end }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: "istiod" + {{- include "istio.labels" . | nindent 4 }} +subsets: +- addresses: + - ip: {{ .Values.global.remotePilotAddress }} + ports: + - port: 15012 + name: tcp-istiod + protocol: TCP + - port: 15017 + name: tcp-webhook + protocol: TCP +--- +{{- end }} +{{- end }} diff --git a/backing-services/istiod/templates/remote-istiod-service.yaml b/backing-services/istiod/templates/remote-istiod-service.yaml new file mode 100644 index 0000000..d3f872f --- /dev/null +++ b/backing-services/istiod/templates/remote-istiod-service.yaml @@ -0,0 +1,35 @@ +# This file is only used for remote `istiod` installs. +{{- if .Values.global.remotePilotAddress }} +apiVersion: v1 +kind: Service +metadata: + name: istiod{{- if .Values.revision }}-{{ .Values.revision}}{{- end }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: "istiod" + {{ include "istio.labels" . | nindent 4 }} +spec: + ports: + - port: 15012 + name: tcp-istiod + protocol: TCP + - port: 443 + targetPort: 15017 + name: tcp-webhook + protocol: TCP + {{- if and .Values.global.remotePilotAddress (not (regexMatch "^([0-9]*\\.){3}[0-9]*$" .Values.global.remotePilotAddress)) }} + # if the remotePilotAddress is not an IP addr, we use ExternalName + type: ExternalName + externalName: {{ .Values.global.remotePilotAddress }} + {{- end }} +{{- if .Values.global.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.global.ipFamilyPolicy }} +{{- end }} +{{- if .Values.global.ipFamilies }} + ipFamilies: +{{- range .Values.global.ipFamilies }} + - {{ . }} +{{- end }} +{{- end }} +--- +{{- end }} diff --git a/backing-services/istiod/templates/revision-tags.yaml b/backing-services/istiod/templates/revision-tags.yaml new file mode 100644 index 0000000..059a6ab --- /dev/null +++ b/backing-services/istiod/templates/revision-tags.yaml @@ -0,0 +1,149 @@ +# Adapted from istio-discovery/templates/mutatingwebhook.yaml +# Removed paths for legacy and default selectors since a revision tag +# is inherently created from a specific revision +# TODO BML istiodRemote.injectionURL is invalid to set if `istiodRemote.enabled` is false, we should express that. +{{- $whv := dict + "revision" .Values.revision + "injectionPath" .Values.istiodRemote.injectionPath + "injectionURL" .Values.istiodRemote.injectionURL + "reinvocationPolicy" .Values.sidecarInjectorWebhook.reinvocationPolicy + "namespace" .Release.Namespace }} +{{- define "core" }} +{{- /* Kubernetes unfortunately requires a unique name for the webhook in some newer versions, so we assign +a unique prefix to each. */}} +- name: {{.Prefix}}sidecar-injector.istio.io + clientConfig: + {{- if .injectionURL }} + url: "{{ .injectionURL }}" + {{- else }} + service: + name: istiod{{- if not (eq .revision "") }}-{{ .revision }}{{- end }} + namespace: {{ .namespace }} + path: "{{ .injectionPath }}" + port: 443 + {{- end }} + sideEffects: None + rules: + - operations: [ "CREATE" ] + apiGroups: [""] + apiVersions: ["v1"] + resources: ["pods"] + failurePolicy: Fail + reinvocationPolicy: "{{ .reinvocationPolicy }}" + admissionReviewVersions: ["v1"] +{{- end }} +{{- range $tagName := $.Values.revisionTags }} +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: +{{- if eq $.Release.Namespace "istio-system"}} + name: istio-revision-tag-{{ $tagName }} +{{- else }} + name: istio-revision-tag-{{ $tagName }}-{{ $.Release.Namespace }} +{{- end }} + labels: + istio.io/tag: {{ $tagName }} + istio.io/rev: {{ $.Values.revision | default "default" | quote }} + install.operator.istio.io/owning-resource: {{ $.Values.ownerName | default "unknown" }} + operator.istio.io/component: "Pilot" + app: sidecar-injector + release: {{ $.Release.Name }} + app.kubernetes.io/name: "istiod" + {{- include "istio.labels" $ | nindent 4 }} +{{- if $.Values.sidecarInjectorWebhookAnnotations }} + annotations: +{{ toYaml $.Values.sidecarInjectorWebhookAnnotations | indent 4 }} +{{- end }} +webhooks: +{{- include "core" (mergeOverwrite (deepCopy $whv) (dict "Prefix" "rev.namespace.") ) }} + namespaceSelector: + matchExpressions: + - key: istio.io/rev + operator: In + values: + - "{{ $tagName }}" + - key: istio-injection + operator: DoesNotExist + objectSelector: + matchExpressions: + - key: sidecar.istio.io/inject + operator: NotIn + values: + - "false" +{{- include "core" (mergeOverwrite (deepCopy $whv) (dict "Prefix" "rev.object.") ) }} + namespaceSelector: + matchExpressions: + - key: istio.io/rev + operator: DoesNotExist + - key: istio-injection + operator: DoesNotExist + objectSelector: + matchExpressions: + - key: sidecar.istio.io/inject + operator: NotIn + values: + - "false" + - key: istio.io/rev + operator: In + values: + - "{{ $tagName }}" + +{{- /* When the tag is "default" we want to create webhooks for the default revision */}} +{{- /* These webhooks should be kept in sync with istio-discovery/templates/mutatingwebhook.yaml */}} +{{- if (eq $tagName "default") }} + +{{- /* Case 1: Namespace selector enabled, and object selector is not injected */}} +{{- include "core" (mergeOverwrite (deepCopy $whv) (dict "Prefix" "namespace.") ) }} + namespaceSelector: + matchExpressions: + - key: istio-injection + operator: In + values: + - enabled + objectSelector: + matchExpressions: + - key: sidecar.istio.io/inject + operator: NotIn + values: + - "false" + +{{- /* Case 2: no namespace label, but object selector is enabled (and revision label is not, which has priority) */}} +{{- include "core" (mergeOverwrite (deepCopy $whv) (dict "Prefix" "object.") ) }} + namespaceSelector: + matchExpressions: + - key: istio-injection + operator: DoesNotExist + - key: istio.io/rev + operator: DoesNotExist + objectSelector: + matchExpressions: + - key: sidecar.istio.io/inject + operator: In + values: + - "true" + - key: istio.io/rev + operator: DoesNotExist + +{{- if $.Values.sidecarInjectorWebhook.enableNamespacesByDefault }} +{{- /* Special case 3: no labels at all */}} +{{- include "core" (mergeOverwrite (deepCopy $whv) (dict "Prefix" "auto.") ) }} + namespaceSelector: + matchExpressions: + - key: istio-injection + operator: DoesNotExist + - key: istio.io/rev + operator: DoesNotExist + - key: "kubernetes.io/metadata.name" + operator: "NotIn" + values: ["kube-system","kube-public","kube-node-lease","local-path-storage"] + objectSelector: + matchExpressions: + - key: sidecar.istio.io/inject + operator: DoesNotExist + - key: istio.io/rev + operator: DoesNotExist +{{- end }} + +{{- end }} +--- +{{- end }} diff --git a/backing-services/istiod/templates/role.yaml b/backing-services/istiod/templates/role.yaml new file mode 100644 index 0000000..10d89e8 --- /dev/null +++ b/backing-services/istiod/templates/role.yaml @@ -0,0 +1,35 @@ +# Created if this is not a remote istiod, OR if it is and is also a config cluster +{{- if or (and .Values.istiodRemote.enabled .Values.global.configCluster) (not .Values.istiodRemote.enabled) }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: istiod{{- if not (eq .Values.revision "")}}-{{ .Values.revision }}{{- end }} + namespace: {{ .Values.global.istioNamespace }} + labels: + app: istiod + release: {{ .Release.Name }} + app.kubernetes.io/name: "istiod" + {{- include "istio.labels" . | nindent 4 }} +rules: +# permissions to verify the webhook is ready and rejecting +# invalid config. We use --server-dry-run so no config is persisted. +- apiGroups: ["networking.istio.io"] + verbs: ["create"] + resources: ["gateways"] + +# For storing CA secret +- apiGroups: [""] + resources: ["secrets"] + # TODO lock this down to istio-ca-cert if not using the DNS cert mesh config + verbs: ["create", "get", "watch", "list", "update", "delete"] + +# For status controller, so it can delete the distribution report configmap +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["delete"] + +# For gateway deployment controller +- apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["get", "update", "patch", "create"] +{{- end }} diff --git a/backing-services/istiod/templates/rolebinding.yaml b/backing-services/istiod/templates/rolebinding.yaml new file mode 100644 index 0000000..a42f4ec --- /dev/null +++ b/backing-services/istiod/templates/rolebinding.yaml @@ -0,0 +1,21 @@ +# Created if this is not a remote istiod, OR if it is and is also a config cluster +{{- if or (and .Values.istiodRemote.enabled .Values.global.configCluster) (not .Values.istiodRemote.enabled) }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: istiod{{- if not (eq .Values.revision "")}}-{{ .Values.revision }}{{- end }} + namespace: {{ .Values.global.istioNamespace }} + labels: + app: istiod + release: {{ .Release.Name }} + app.kubernetes.io/name: "istiod" + {{- include "istio.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: istiod{{- if not (eq .Values.revision "")}}-{{ .Values.revision }}{{- end }} +subjects: + - kind: ServiceAccount + name: istiod{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }} + namespace: {{ .Values.global.istioNamespace }} +{{- end }} diff --git a/backing-services/istiod/templates/service.yaml b/backing-services/istiod/templates/service.yaml new file mode 100644 index 0000000..8829f0f --- /dev/null +++ b/backing-services/istiod/templates/service.yaml @@ -0,0 +1,55 @@ +# Not created if istiod is running remotely +{{- if not .Values.istiodRemote.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: istiod{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }} + namespace: {{ .Release.Namespace }} + {{- if .Values.serviceAnnotations }} + annotations: +{{ toYaml .Values.serviceAnnotations | indent 4 }} + {{- end }} + labels: + istio.io/rev: {{ .Values.revision | default "default" | quote }} + install.operator.istio.io/owning-resource: {{ .Values.ownerName | default "unknown" }} + operator.istio.io/component: "Pilot" + app: istiod + istio: pilot + release: {{ .Release.Name }} + app.kubernetes.io/name: "istiod" + {{- include "istio.labels" . | nindent 4 }} +spec: + ports: + - port: 15010 + name: grpc-xds # plaintext + protocol: TCP + - port: 15012 + name: https-dns # mTLS with k8s-signed cert + protocol: TCP + - port: 443 + name: https-webhook # validation and injection + targetPort: 15017 + protocol: TCP + - port: 15014 + name: http-monitoring # prometheus stats + protocol: TCP + selector: + app: istiod + {{- if ne .Values.revision "" }} + istio.io/rev: {{ .Values.revision | quote }} + {{- else }} + # Label used by the 'default' service. For versioned deployments we match with app and version. + # This avoids default deployment picking the canary + istio: pilot + {{- end }} + {{- if .Values.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.ipFamilyPolicy }} + {{- end }} + {{- if .Values.ipFamilies }} + ipFamilies: + {{- range .Values.ipFamilies }} + - {{ . }} + {{- end }} + {{- end }} +--- +{{- end }} diff --git a/backing-services/istiod/templates/serviceaccount.yaml b/backing-services/istiod/templates/serviceaccount.yaml new file mode 100644 index 0000000..a673a4d --- /dev/null +++ b/backing-services/istiod/templates/serviceaccount.yaml @@ -0,0 +1,24 @@ +# Created if this is not a remote istiod, OR if it is and is also a config cluster +{{- if or (and .Values.istiodRemote.enabled .Values.global.configCluster) (not .Values.istiodRemote.enabled) }} +apiVersion: v1 +kind: ServiceAccount + {{- if .Values.global.imagePullSecrets }} +imagePullSecrets: + {{- range .Values.global.imagePullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} +metadata: + name: istiod{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }} + namespace: {{ .Values.global.istioNamespace }} + labels: + app: istiod + release: {{ .Release.Name }} + app.kubernetes.io/name: "istiod" + {{- include "istio.labels" . | nindent 4 }} + {{- if .Values.serviceAccountAnnotations }} + annotations: +{{- toYaml .Values.serviceAccountAnnotations | nindent 4 }} + {{- end }} +{{- end }} +--- diff --git a/backing-services/istiod/templates/validatingadmissionpolicy.yaml b/backing-services/istiod/templates/validatingadmissionpolicy.yaml new file mode 100644 index 0000000..d36eef6 --- /dev/null +++ b/backing-services/istiod/templates/validatingadmissionpolicy.yaml @@ -0,0 +1,63 @@ +# Created if this is not a remote istiod, OR if it is and is also a config cluster +{{- if or (and .Values.istiodRemote.enabled .Values.global.configCluster) (not .Values.istiodRemote.enabled) }} +{{- if .Values.experimental.stableValidationPolicy }} +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicy +metadata: + name: "stable-channel-policy{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }}-{{ .Values.global.istioNamespace }}.istio.io" + labels: + app.kubernetes.io/name: "istiod" + {{- include "istio.labels" . | nindent 4 }} +spec: + failurePolicy: Fail + matchConstraints: + resourceRules: + - apiGroups: + - security.istio.io + - networking.istio.io + - telemetry.istio.io + - extensions.istio.io + apiVersions: ["*"] + operations: ["CREATE", "UPDATE"] + resources: ["*"] + objectSelector: + matchExpressions: + - key: istio.io/rev + operator: In + values: + {{- if (eq .Values.revision "") }} + - "default" + {{- else }} + - "{{ .Values.revision }}" + {{- end }} + variables: + - name: isEnvoyFilter + expression: "object.kind == 'EnvoyFilter'" + - name: isWasmPlugin + expression: "object.kind == 'WasmPlugin'" + - name: isProxyConfig + expression: "object.kind == 'ProxyConfig'" + - name: isTelemetry + expression: "object.kind == 'Telemetry'" + validations: + - expression: "!variables.isEnvoyFilter" + - expression: "!variables.isWasmPlugin" + - expression: "!variables.isProxyConfig" + - expression: | + !( + variables.isTelemetry && ( + (has(object.spec.tracing) ? object.spec.tracing : {}).exists(t, has(t.useRequestIdForTraceSampling)) || + (has(object.spec.metrics) ? object.spec.metrics : {}).exists(m, has(m.reportingInterval)) || + (has(object.spec.accessLogging) ? object.spec.accessLogging : {}).exists(l, has(l.filter)) + ) + ) +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicyBinding +metadata: + name: "stable-channel-policy-binding{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }}-{{ .Values.global.istioNamespace }}.istio.io" +spec: + policyName: "stable-channel-policy{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }}-{{ .Values.global.istioNamespace }}.istio.io" + validationActions: [Deny] +{{- end }} +{{- end }} diff --git a/backing-services/istiod/templates/validatingwebhookconfiguration.yaml b/backing-services/istiod/templates/validatingwebhookconfiguration.yaml new file mode 100644 index 0000000..fb28836 --- /dev/null +++ b/backing-services/istiod/templates/validatingwebhookconfiguration.yaml @@ -0,0 +1,68 @@ +# Created if this is not a remote istiod, OR if it is and is also a config cluster +{{- if or (and .Values.istiodRemote.enabled .Values.global.configCluster) (not .Values.istiodRemote.enabled) }} +{{- if .Values.global.configValidation }} +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: istio-validator{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }}-{{ .Values.global.istioNamespace }} + labels: + app: istiod + release: {{ .Release.Name }} + istio: istiod + istio.io/rev: {{ .Values.revision | default "default" | quote }} + app.kubernetes.io/name: "istiod" + {{- include "istio.labels" . | nindent 4 }} +webhooks: + # Webhook handling per-revision validation. Mostly here so we can determine whether webhooks + # are rejecting invalid configs on a per-revision basis. + - name: rev.validation.istio.io + clientConfig: + # Should change from base but cannot for API compat + {{- if .Values.base.validationURL }} + url: {{ .Values.base.validationURL }} + {{- else }} + service: + name: istiod{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }} + namespace: {{ .Values.global.istioNamespace }} + path: "/validate" + {{- end }} + {{- if .Values.base.validationCABundle }} + caBundle: "{{ .Values.base.validationCABundle }}" + {{- end }} + rules: + - operations: + - CREATE + - UPDATE + apiGroups: + - security.istio.io + - networking.istio.io + - telemetry.istio.io + - extensions.istio.io + apiVersions: + - "*" + resources: + - "*" + {{- if .Values.base.validationCABundle }} + # Disable webhook controller in Pilot to stop patching it + failurePolicy: Fail + {{- else }} + # Fail open until the validation webhook is ready. The webhook controller + # will update this to `Fail` and patch in the `caBundle` when the webhook + # endpoint is ready. + failurePolicy: Ignore + {{- end }} + sideEffects: None + admissionReviewVersions: ["v1"] + objectSelector: + matchExpressions: + - key: istio.io/rev + operator: In + values: + {{- if (eq .Values.revision "") }} + - "default" + {{- else }} + - "{{ .Values.revision }}" + {{- end }} +--- +{{- end }} +{{- end }} diff --git a/backing-services/istiod/templates/zzy_descope_legacy.yaml b/backing-services/istiod/templates/zzy_descope_legacy.yaml new file mode 100644 index 0000000..ae8fced --- /dev/null +++ b/backing-services/istiod/templates/zzy_descope_legacy.yaml @@ -0,0 +1,3 @@ +{{/* Copy anything under `.pilot` to `.`, to avoid the need to specify a redundant prefix. +Due to the file naming, this always happens after zzz_profile.yaml */}} +{{- $_ := mustMergeOverwrite $.Values (index $.Values "pilot") }} \ No newline at end of file diff --git a/backing-services/istiod/templates/zzz_profile.yaml b/backing-services/istiod/templates/zzz_profile.yaml new file mode 100644 index 0000000..3d84956 --- /dev/null +++ b/backing-services/istiod/templates/zzz_profile.yaml @@ -0,0 +1,75 @@ +{{/* +WARNING: DO NOT EDIT, THIS FILE IS A PROBABLY COPY. +The original version of this file is located at /manifests directory. +If you want to make a change in this file, edit the original one and run "make gen". + +Complex logic ahead... +We have three sets of values, in order of precedence (last wins): +1. The builtin values.yaml defaults +2. The profile the user selects +3. Users input (-f or --set) + +Unfortunately, Helm provides us (1) and (3) together (as .Values), making it hard to insert (2). + +However, we can workaround this by placing all of (1) under a specific key (.Values.defaults). +We can then merge the profile onto the defaults, then the user settings onto that. +Finally, we can set all of that under .Values so the chart behaves without awareness. +*/}} +{{- if $.Values.defaults}} +{{ fail (cat + "Setting with .default prefix found; remove it. For example, replace `--set defaults.hub=foo` with `--set hub=foo`. Defaults set:\n" + ($.Values.defaults | toYaml |nindent 4) +) }} +{{- end }} +{{- $defaults := $.Values._internal_defaults_do_not_set }} +{{- $_ := unset $.Values "_internal_defaults_do_not_set" }} +{{- $profile := dict }} +{{- with (coalesce ($.Values).profile ($.Values.global).profile) }} +{{- with $.Files.Get (printf "files/profile-%s.yaml" .)}} +{{- $profile = (. | fromYaml) }} +{{- else }} +{{ fail (cat "unknown profile" .) }} +{{- end }} +{{- end }} +{{- with .Values.compatibilityVersion }} +{{- with $.Files.Get (printf "files/profile-compatibility-version-%s.yaml" .) }} +{{- $ignore := mustMergeOverwrite $profile (. | fromYaml) }} +{{- else }} +{{ fail (cat "unknown compatibility version" $.Values.compatibilityVersion) }} +{{- end }} +{{- end }} +{{- with (coalesce ($.Values).platform ($.Values.global).platform) }} +{{- with $.Files.Get (printf "files/profile-platform-%s.yaml" .) }} +{{- $ignore := mustMergeOverwrite $profile (. | fromYaml) }} +{{- else }} +{{ fail (cat "unknown platform" .) }} +{{- end }} +{{- end }} +{{- if $profile }} +{{- $a := mustMergeOverwrite $defaults $profile }} +{{- end }} +# Flatten globals, if defined on a per-chart basis +{{- if false }} +{{- $a := mustMergeOverwrite $defaults ($profile.global) ($.Values.global | default dict) }} +{{- end }} +{{- $x := set $.Values "_original" (deepCopy $.Values) }} +{{- $b := set $ "Values" (mustMergeOverwrite $defaults $.Values) }} + +{{/* +Labels that should be applied to ALL resources. +*/}} +{{- define "istio.labels" -}} +{{- if .Release.Service -}} +app.kubernetes.io/managed-by: {{ .Release.Service | quote }} +{{- end }} +{{- if .Release.Name }} +app.kubernetes.io/instance: {{ .Release.Name | quote }} +{{- end }} +app.kubernetes.io/part-of: "istio" +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +{{- if and .Chart.Name .Chart.Version }} +helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end -}} diff --git a/backing-services/istiod/values.yaml b/backing-services/istiod/values.yaml new file mode 100644 index 0000000..e00514b --- /dev/null +++ b/backing-services/istiod/values.yaml @@ -0,0 +1,553 @@ +# "_internal_defaults_do_not_set" is a workaround for Helm limitations. Users should NOT set "._internal_defaults_do_not_set" explicitly, but rather directly set the fields internally. +# For instance, instead of `--set _internal_defaults_do_not_set.foo=bar``, just set `--set foo=bar`. +_internal_defaults_do_not_set: + autoscaleEnabled: true + autoscaleMin: 1 + autoscaleMax: 5 + autoscaleBehavior: {} + replicaCount: 1 + rollingMaxSurge: 100% + rollingMaxUnavailable: 25% + + hub: "" + tag: "" + variant: "" + + # Can be a full hub/image:tag + image: pilot + traceSampling: 1.0 + + # Resources for a small pilot install + resources: + requests: + cpu: 500m + memory: 2048Mi + + # Set to `type: RuntimeDefault` to use the default profile if available. + seccompProfile: {} + + # Whether to use an existing CNI installation + cni: + enabled: false + provider: default + + # Additional container arguments + extraContainerArgs: [] + + env: {} + + envVarFrom: [] + + # Settings related to the untaint controller + # This controller will remove `cni.istio.io/not-ready` from nodes when the istio-cni pod becomes ready + # It should be noted that cluster operator/owner is responsible for having the taint set by their infrastructure provider when new nodes are added to the cluster; the untaint controller does not taint nodes + taint: + # Controls whether or not the untaint controller is active + enabled: false + # What namespace the untaint controller should watch for istio-cni pods. This is only required when istio-cni is running in a different namespace than istiod + namespace: "" + + affinity: {} + + tolerations: [] + + cpu: + targetAverageUtilization: 80 + memory: {} + # targetAverageUtilization: 80 + + # Additional volumeMounts to the istiod container + volumeMounts: [] + + # Additional volumes to the istiod pod + volumes: [] + + # Inject initContainers into the istiod pod + initContainers: [] + + nodeSelector: {} + podAnnotations: {} + serviceAnnotations: {} + serviceAccountAnnotations: {} + sidecarInjectorWebhookAnnotations: {} + + topologySpreadConstraints: [] + + # You can use jwksResolverExtraRootCA to provide a root certificate + # in PEM format. This will then be trusted by pilot when resolving + # JWKS URIs. + jwksResolverExtraRootCA: "" + + # The following is used to limit how long a sidecar can be connected + # to a pilot. It balances out load across pilot instances at the cost of + # increasing system churn. + keepaliveMaxServerConnectionAge: 30m + + # Additional labels to apply to the deployment. + deploymentLabels: {} + + ## Mesh config settings + + # Install the mesh config map, generated from values.yaml. + # If false, pilot wil use default values (by default) or user-supplied values. + configMap: true + + # Additional labels to apply on the pod level for monitoring and logging configuration. + podLabels: {} + + # Setup how istiod Service is configured. See https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services + ipFamilyPolicy: "" + ipFamilies: [] + + # Ambient mode only. + # Set this if you install ztunnel to a different namespace from `istiod`. + # If set, `istiod` will allow connections from trusted node proxy ztunnels + # in the provided namespace. + # If unset, `istiod` will assume the trusted node proxy ztunnel resides + # in the same namespace as itself. + trustedZtunnelNamespace: "" + # Set this if you install ztunnel with a name different from the default. + trustedZtunnelName: "" + + sidecarInjectorWebhook: + # You can use the field called alwaysInjectSelector and neverInjectSelector which will always inject the sidecar or + # always skip the injection on pods that match that label selector, regardless of the global policy. + # See https://istio.io/docs/setup/kubernetes/additional-setup/sidecar-injection/#more-control-adding-exceptions + neverInjectSelector: [] + alwaysInjectSelector: [] + + # injectedAnnotations are additional annotations that will be added to the pod spec after injection + # This is primarily to support PSP annotations. For example, if you defined a PSP with the annotations: + # + # annotations: + # apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default + # apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default + # + # The PSP controller would add corresponding annotations to the pod spec for each container. However, this happens before + # the inject adds additional containers, so we must specify them explicitly here. With the above example, we could specify: + # injectedAnnotations: + # container.apparmor.security.beta.kubernetes.io/istio-init: runtime/default + # container.apparmor.security.beta.kubernetes.io/istio-proxy: runtime/default + injectedAnnotations: {} + + # This enables injection of sidecar in all namespaces, + # with the exception of namespaces with "istio-injection:disabled" annotation + # Only one environment should have this enabled. + enableNamespacesByDefault: false + + # Mutations that occur after the sidecar injector are not handled by default, as the Istio sidecar injector is only run + # once. For example, an OPA sidecar injected after the Istio sidecar will not have it's liveness/readiness probes rewritten. + # Setting this to `IfNeeded` will result in the sidecar injector being run again if additional mutations occur. + reinvocationPolicy: Never + + rewriteAppHTTPProbe: true + + # Templates defines a set of custom injection templates that can be used. For example, defining: + # + # templates: + # hello: | + # metadata: + # labels: + # hello: world + # + # Then starting a pod with the `inject.istio.io/templates: hello` annotation, will result in the pod + # being injected with the hello=world labels. + # This is intended for advanced configuration only; most users should use the built in template + templates: {} + + # Default templates specifies a set of default templates that are used in sidecar injection. + # By default, a template `sidecar` is always provided, which contains the template of default sidecar. + # To inject other additional templates, define it using the `templates` option, and add it to + # the default templates list. + # For example: + # + # templates: + # hello: | + # metadata: + # labels: + # hello: world + # + # defaultTemplates: ["sidecar", "hello"] + defaultTemplates: [] + istiodRemote: + # If `true`, indicates that this cluster/install should consume a "remote istiod" installation, + # and istiod itself will NOT be installed in this cluster - only the support resources necessary + # to utilize a remote instance. + enabled: false + # Sidecar injector mutating webhook configuration clientConfig.url value. + # For example: https://$remotePilotAddress:15017/inject + # The host should not refer to a service running in the cluster; use a service reference by specifying + # the clientConfig.service field instead. + injectionURL: "" + + # Sidecar injector mutating webhook configuration path value for the clientConfig.service field. + # Override to pass env variables, for example: /inject/cluster/remote/net/network2 + injectionPath: "/inject" + + injectionCABundle: "" + telemetry: + enabled: true + v2: + # For Null VM case now. + # This also enables metadata exchange. + enabled: true + # Indicate if prometheus stats filter is enabled or not + prometheus: + enabled: true + # stackdriver filter settings. + stackdriver: + enabled: false + # Revision is set as 'version' label and part of the resource names when installing multiple control planes. + revision: "" + + # Revision tags are aliases to Istio control plane revisions + revisionTags: [] + + # For Helm compatibility. + ownerName: "" + + # meshConfig defines runtime configuration of components, including Istiod and istio-agent behavior + # See https://istio.io/docs/reference/config/istio.mesh.v1alpha1/ for all available options + meshConfig: + enablePrometheusMerge: true + + experimental: + stableValidationPolicy: false + + global: + # Used to locate istiod. + istioNamespace: istio-system + # List of cert-signers to allow "approve" action in the istio cluster role + # + # certSigners: + # - clusterissuers.cert-manager.io/istio-ca + certSigners: [] + # enable pod disruption budget for the control plane, which is used to + # ensure Istio control plane components are gradually upgraded or recovered. + defaultPodDisruptionBudget: + enabled: true + # The values aren't mutable due to a current PodDisruptionBudget limitation + # minAvailable: 1 + + # A minimal set of requested resources to applied to all deployments so that + # Horizontal Pod Autoscaler will be able to function (if set). + # Each component can overwrite these default values by adding its own resources + # block in the relevant section below and setting the desired resources values. + defaultResources: + requests: + cpu: 10m + # memory: 128Mi + # limits: + # cpu: 100m + # memory: 128Mi + + # Default hub for Istio images. + # Releases are published to docker hub under 'istio' project. + # Dev builds from prow are on gcr.io + hub: docker.io/istio + # Default tag for Istio images. + tag: 1.26.1 + # Variant of the image to use. + # Currently supported are: [debug, distroless] + variant: "" + + # Specify image pull policy if default behavior isn't desired. + # Default behavior: latest images will be Always else IfNotPresent. + imagePullPolicy: "" + + # ImagePullSecrets for all ServiceAccount, list of secrets in the same namespace + # to use for pulling any images in pods that reference this ServiceAccount. + # For components that don't use ServiceAccounts (i.e. grafana, servicegraph, tracing) + # ImagePullSecrets will be added to the corresponding Deployment(StatefulSet) objects. + # Must be set for any cluster configured with private docker registry. + imagePullSecrets: [] + # - private-registry-key + + # Enabled by default in master for maximising testing. + istiod: + enableAnalysis: false + + # To output all istio components logs in json format by adding --log_as_json argument to each container argument + logAsJson: false + + # Comma-separated minimum per-scope logging level of messages to output, in the form of :,: + # The control plane has different scopes depending on component, but can configure default log level across all components + # If empty, default scope and level will be used as configured in code + logging: + level: "default:info" + + omitSidecarInjectorConfigMap: false + + # Configure whether Operator manages webhook configurations. The current behavior + # of Istiod is to manage its own webhook configurations. + # When this option is set as true, Istio Operator, instead of webhooks, manages the + # webhook configurations. When this option is set as false, webhooks manage their + # own webhook configurations. + operatorManageWebhooks: false + + # Custom DNS config for the pod to resolve names of services in other + # clusters. Use this to add additional search domains, and other settings. + # see + # https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#dns-config + # This does not apply to gateway pods as they typically need a different + # set of DNS settings than the normal application pods (e.g., in + # multicluster scenarios). + # NOTE: If using templates, follow the pattern in the commented example below. + #podDNSSearchNamespaces: + #- global + #- "{{ valueOrDefault .DeploymentMeta.Namespace \"default\" }}.global" + + # Kubernetes >=v1.11.0 will create two PriorityClass, including system-cluster-critical and + # system-node-critical, it is better to configure this in order to make sure your Istio pods + # will not be killed because of low priority class. + # Refer to https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass + # for more detail. + priorityClassName: "" + + proxy: + image: proxyv2 + + # This controls the 'policy' in the sidecar injector. + autoInject: enabled + + # CAUTION: It is important to ensure that all Istio helm charts specify the same clusterDomain value + # cluster domain. Default value is "cluster.local". + clusterDomain: "cluster.local" + + # Per Component log level for proxy, applies to gateways and sidecars. If a component level is + # not set, then the global "logLevel" will be used. + componentLogLevel: "misc:error" + + # istio ingress capture allowlist + # examples: + # Redirect only selected ports: --includeInboundPorts="80,8080" + excludeInboundPorts: "" + includeInboundPorts: "*" + + # istio egress capture allowlist + # https://istio.io/docs/tasks/traffic-management/egress.html#calling-external-services-directly + # example: includeIPRanges: "172.30.0.0/16,172.20.0.0/16" + # would only capture egress traffic on those two IP Ranges, all other outbound traffic would + # be allowed by the sidecar + includeIPRanges: "*" + excludeIPRanges: "" + includeOutboundPorts: "" + excludeOutboundPorts: "" + + # Log level for proxy, applies to gateways and sidecars. + # Expected values are: trace|debug|info|warning|error|critical|off + logLevel: warning + + # Specify the path to the outlier event log. + # Example: /dev/stdout + outlierLogPath: "" + + #If set to true, istio-proxy container will have privileged securityContext + privileged: false + + # The number of successive failed probes before indicating readiness failure. + readinessFailureThreshold: 4 + + # The initial delay for readiness probes in seconds. + readinessInitialDelaySeconds: 0 + + # The period between readiness probes. + readinessPeriodSeconds: 15 + + # Enables or disables a startup probe. + # For optimal startup times, changing this should be tied to the readiness probe values. + # + # If the probe is enabled, it is recommended to have delay=0s,period=15s,failureThreshold=4. + # This ensures the pod is marked ready immediately after the startup probe passes (which has a 1s poll interval), + # and doesn't spam the readiness endpoint too much + # + # If the probe is disabled, it is recommended to have delay=1s,period=2s,failureThreshold=30. + # This ensures the startup is reasonable fast (polling every 2s). 1s delay is used since the startup is not often ready instantly. + startupProbe: + enabled: true + failureThreshold: 600 # 10 minutes + + # Resources for the sidecar. + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 2000m + memory: 1024Mi + + # Default port for Pilot agent health checks. A value of 0 will disable health checking. + statusPort: 15020 + + # Specify which tracer to use. One of: zipkin, lightstep, datadog, stackdriver, none. + # If using stackdriver tracer outside GCP, set env GOOGLE_APPLICATION_CREDENTIALS to the GCP credential file. + tracer: "none" + + proxy_init: + # Base name for the proxy_init container, used to configure iptables. + image: proxyv2 + # Bypasses iptables idempotency handling, and attempts to apply iptables rules regardless of table state, which may cause unrecoverable failures. + # Do not use unless you need to work around an issue of the idempotency handling. This flag will be removed in future releases. + forceApplyIptables: false + + # configure remote pilot and istiod service and endpoint + remotePilotAddress: "" + + ############################################################################################## + # The following values are found in other charts. To effectively modify these values, make # + # make sure they are consistent across your Istio helm charts # + ############################################################################################## + + # The customized CA address to retrieve certificates for the pods in the cluster. + # CSR clients such as the Istio Agent and ingress gateways can use this to specify the CA endpoint. + # If not set explicitly, default to the Istio discovery address. + caAddress: "" + + # Enable control of remote clusters. + externalIstiod: false + + # Configure a remote cluster as the config cluster for an external istiod. + configCluster: false + + # configValidation enables the validation webhook for Istio configuration. + configValidation: true + + # Mesh ID means Mesh Identifier. It should be unique within the scope where + # meshes will interact with each other, but it is not required to be + # globally/universally unique. For example, if any of the following are true, + # then two meshes must have different Mesh IDs: + # - Meshes will have their telemetry aggregated in one place + # - Meshes will be federated together + # - Policy will be written referencing one mesh from the other + # + # If an administrator expects that any of these conditions may become true in + # the future, they should ensure their meshes have different Mesh IDs + # assigned. + # + # Within a multicluster mesh, each cluster must be (manually or auto) + # configured to have the same Mesh ID value. If an existing cluster 'joins' a + # multicluster mesh, it will need to be migrated to the new mesh ID. Details + # of migration TBD, and it may be a disruptive operation to change the Mesh + # ID post-install. + # + # If the mesh admin does not specify a value, Istio will use the value of the + # mesh's Trust Domain. The best practice is to select a proper Trust Domain + # value. + meshID: "" + + # Configure the mesh networks to be used by the Split Horizon EDS. + # + # The following example defines two networks with different endpoints association methods. + # For `network1` all endpoints that their IP belongs to the provided CIDR range will be + # mapped to network1. The gateway for this network example is specified by its public IP + # address and port. + # The second network, `network2`, in this example is defined differently with all endpoints + # retrieved through the specified Multi-Cluster registry being mapped to network2. The + # gateway is also defined differently with the name of the gateway service on the remote + # cluster. The public IP for the gateway will be determined from that remote service (only + # LoadBalancer gateway service type is currently supported, for a NodePort type gateway service, + # it still need to be configured manually). + # + # meshNetworks: + # network1: + # endpoints: + # - fromCidr: "192.168.0.1/24" + # gateways: + # - address: 1.1.1.1 + # port: 80 + # network2: + # endpoints: + # - fromRegistry: reg1 + # gateways: + # - registryServiceName: istio-ingressgateway.istio-system.svc.cluster.local + # port: 443 + # + meshNetworks: {} + + # Use the user-specified, secret volume mounted key and certs for Pilot and workloads. + mountMtlsCerts: false + + multiCluster: + # Set to true to connect two kubernetes clusters via their respective + # ingressgateway services when pods in each cluster cannot directly + # talk to one another. All clusters should be using Istio mTLS and must + # have a shared root CA for this model to work. + enabled: false + # Should be set to the name of the cluster this installation will run in. This is required for sidecar injection + # to properly label proxies + clusterName: "" + + # Network defines the network this cluster belong to. This name + # corresponds to the networks in the map of mesh networks. + network: "" + + # Configure the certificate provider for control plane communication. + # Currently, two providers are supported: "kubernetes" and "istiod". + # As some platforms may not have kubernetes signing APIs, + # Istiod is the default + pilotCertProvider: istiod + + sds: + # The JWT token for SDS and the aud field of such JWT. See RFC 7519, section 4.1.3. + # When a CSR is sent from Istio Agent to the CA (e.g. Istiod), this aud is to make sure the + # JWT is intended for the CA. + token: + aud: istio-ca + + sts: + # The service port used by Security Token Service (STS) server to handle token exchange requests. + # Setting this port to a non-zero value enables STS server. + servicePort: 0 + + # The name of the CA for workload certificates. + # For example, when caName=GkeWorkloadCertificate, GKE workload certificates + # will be used as the certificates for workloads. + # The default value is "" and when caName="", the CA will be configured by other + # mechanisms (e.g., environmental variable CA_PROVIDER). + caName: "" + + waypoint: + # Resources for the waypoint proxy. + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: "2" + memory: 1Gi + + # If specified, affinity defines the scheduling constraints of waypoint pods. + affinity: {} + + # Topology Spread Constraints for the waypoint proxy. + topologySpreadConstraints: [] + + # Node labels for the waypoint proxy. + nodeSelector: {} + + # Tolerations for the waypoint proxy. + tolerations: [] + + base: + # For istioctl usage to disable istio config crds in base + enableIstioConfigCRDs: true + + # Gateway Settings + gateways: + # Define the security context for the pod. + # If unset, this will be automatically set to the minimum privileges required to bind to port 80 and 443. + # On Kubernetes 1.22+, this only requires the `net.ipv4.ip_unprivileged_port_start` sysctl. + securityContext: {} + + # Set to `type: RuntimeDefault` to use the default profile for templated gateways, if your container runtime supports it + seccompProfile: {} + + # gatewayClasses allows customizing the configuration of the default deployment of Gateways per GatewayClass. + # For example: + # gatewayClasses: + # istio: + # service: + # spec: + # type: ClusterIP + # Per-Gateway configuration can also be set in the `Gateway.spec.infrastructure.parametersRef` field. + gatewayClasses: {} diff --git a/backing-services/jenkins/.helmignore b/backing-services/jenkins/.helmignore new file mode 100644 index 0000000..207983f --- /dev/null +++ b/backing-services/jenkins/.helmignore @@ -0,0 +1,25 @@ +# 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 +# img folder +img/ +# Changelog +CHANGELOG.md diff --git a/backing-services/jenkins/Chart.lock b/backing-services/jenkins/Chart.lock new file mode 100644 index 0000000..c5a572f --- /dev/null +++ b/backing-services/jenkins/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + version: 2.26.0 +digest: sha256:5ff7837915aef0067bd32271ee2b10c990774c16c4b6fe0a7c5eb6e53530ce08 +generated: "2024-10-17T18:25:25.574412548Z" diff --git a/backing-services/jenkins/Chart.yaml b/backing-services/jenkins/Chart.yaml new file mode 100644 index 0000000..50427e7 --- /dev/null +++ b/backing-services/jenkins/Chart.yaml @@ -0,0 +1,37 @@ +annotations: + category: Infrastructure + images: | + - name: jenkins + image: docker.io/bitnami/jenkins:2.479.1-debian-12-r0 + - name: jenkins-agent + image: docker.io/bitnami/jenkins-agent:0.3273.0-debian-12-r1 + - name: os-shell + image: docker.io/bitnami/os-shell:12-debian-12-r32 + licenses: Apache-2.0 +apiVersion: v2 +appVersion: 2.479.1 +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + tags: + - bitnami-common + version: 2.x.x +description: Jenkins is an open source Continuous Integration and Continuous Delivery + (CI/CD) server designed to automate the building, testing, and deploying of any + software project. +home: https://bitnami.com +icon: https://bitnami.com/assets/stacks/jenkins/img/jenkins-stack-220x234.png +keywords: +- jenkins +- ci +- cd +- http +- web +- application +maintainers: +- name: Broadcom, Inc. All Rights Reserved. + url: https://github.com/bitnami/charts +name: jenkins +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/jenkins +version: 13.4.27 diff --git a/backing-services/jenkins/README.md b/backing-services/jenkins/README.md new file mode 100644 index 0000000..b3ed3a4 --- /dev/null +++ b/backing-services/jenkins/README.md @@ -0,0 +1,628 @@ + + +# Bitnami package for Jenkins + +Jenkins is an open source Continuous Integration and Continuous Delivery (CI/CD) server designed to automate the building, testing, and deploying of any software project. + +[Overview of Jenkins](http://jenkins-ci.org/) + +Trademarks: This software listing is packaged by Bitnami. The respective trademarks mentioned in the offering are owned by the respective companies, and use of them does not imply any affiliation or endorsement. + +## TL;DR + +```console +helm install my-release oci://registry-1.docker.io/bitnamicharts/jenkins +``` + +Looking to use Jenkins in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the commercial edition of the Bitnami catalog. + +## Introduction + +This chart bootstraps a [Jenkins](https://github.com/bitnami/containers/tree/main/bitnami/jenkins) deployment on a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ +- PV provisioner support in the underlying infrastructure +- ReadWriteMany volumes for deployment scaling + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```console +helm install my-release oci://REGISTRY_NAME/REPOSITORY_NAME/jenkins +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +These commands deploy Jenkins 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` + +## Configuration and installation details + +### Resource requests and limits + +Bitnami charts allow setting resource requests and limits for all containers inside the chart deployment. These are inside the `resources` value (check parameter table). Setting requests is essential for production workloads and these should be adapted to your specific use case. + +To make this process easier, the chart contains the `resourcesPreset` values, which automatically sets the `resources` section according to different presets. Check these presets in [the bitnami/common chart](https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15). However, in production workloads using `resourcePreset` is discouraged as it may not fully adapt to your specific needs. Find more information on container resource management in the [official Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). + +### [Rolling vs Immutable tags](https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-understand-rolling-tags-containers-index.html) + +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. + +### Configure Ingress + +This chart provides support for Ingress resources. If you have an ingress controller installed on your cluster, such as [nginx-ingress-controller](https://github.com/bitnami/charts/tree/main/bitnami/nginx-ingress-controller) or [contour](https://github.com/bitnami/charts/tree/main/bitnami/contour) you can utilize the ingress controller to serve your application.To enable Ingress integration, set `ingress.enabled` to `true`. + +The most common scenario is to have one host name mapped to the deployment. In this case, the `ingress.hostname` property can be used to set the host name. The `ingress.tls` parameter can be used to add the TLS configuration for this host. + +However, it is also possible to have more than one host. To facilitate this, the `ingress.extraHosts` parameter (if available) can be set with the host names specified as an array. The `ingress.extraTLS` parameter (if available) can also be used to add the TLS configuration for extra hosts. + +> NOTE: For each host specified in the `ingress.extraHosts` parameter, it is necessary to set a name, path, and any annotations that the Ingress controller should know about. Not all annotations are supported by all Ingress controllers, but [this annotation reference document](https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md) lists the annotations supported by many popular Ingress controllers. + +Adding the TLS parameter (where available) will cause the chart to generate HTTPS URLs, and the application will be available on port 443. The actual TLS secrets do not have to be generated by this chart. However, if TLS is enabled, the Ingress record will not work until the TLS secret exists. + +[Learn more about Ingress controllers](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/). + +### Configure TLS Secrets for use with Ingress + +This chart facilitates the creation of TLS secrets for use with the Ingress controller (although this is not mandatory). There are several common use cases: + +- Generate certificate secrets based on chart parameters. +- Enable externally generated certificates. +- Manage application certificates via an external service (like [cert-manager](https://github.com/jetstack/cert-manager/)). +- Create self-signed certificates within the chart (if supported). + +In the first two cases, a certificate and a key are needed. Files are expected in `.pem` format. + +Here is an example of a certificate file: + +> NOTE: There may be more than one certificate if there is a certificate chain. + +```text +-----BEGIN CERTIFICATE----- +MIID6TCCAtGgAwIBAgIJAIaCwivkeB5EMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV +... +jScrvkiBO65F46KioCL9h5tDvomdU1aqpI/CBzhvZn1c0ZTf87tGQR8NK7v7 +-----END CERTIFICATE----- +``` + +Here is an example of a certificate key: + +```text +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAvLYcyu8f3skuRyUgeeNpeDvYBCDcgq+LsWap6zbX5f8oLqp4 +... +wrj2wDbCDCFmfqnSJ+dKI3vFLlEz44sAV8jX/kd4Y6ZTQhlLbYc= +-----END RSA PRIVATE KEY----- +``` + +- If using Helm to manage the certificates based on the parameters, copy these values into the `certificate` and `key` values for a given `*.ingress.secrets` entry. +- If managing TLS secrets separately, it is necessary to create a TLS secret with name `INGRESS_HOSTNAME-tls` (where INGRESS_HOSTNAME is a placeholder to be replaced with the hostname you set using the `*.ingress.hostname` parameter). +- If your cluster has a [cert-manager](https://github.com/jetstack/cert-manager) add-on to automate the management and issuance of TLS certificates, add to `*.ingress.annotations` the [corresponding ones](https://cert-manager.io/docs/usage/ingress/#supported-annotations) for cert-manager. +- If using self-signed certificates created by Helm, set both `*.ingress.tls` and `*.ingress.selfSigned` to `true`. + +### Configure extra environment variables + +To add extra environment variables (useful for advanced operations like custom init scripts), use the `extraEnvVars` property. + +```yaml +extraEnvVars: + - name: LOG_LEVEL + value: DEBUG +``` + +Alternatively, use a ConfigMap or a Secret with the environment variables. To do so, use the `extraEnvVarsCM` or the `extraEnvVarsSecret` values. + +### Configure Sidecars and Init Containers + +If additional containers are needed in the same pod as Jenkins (such as additional metrics or logging exporters), they can be defined using the `sidecars` parameter. + +```yaml +sidecars: +- name: your-image-name + image: your-image + imagePullPolicy: Always + ports: + - name: portname + containerPort: 1234 +``` + +If these sidecars export extra ports, extra port definitions can be added using the `service.extraPorts` parameter (where available), as shown in the example below: + +```yaml +service: + extraPorts: + - name: extraPort + port: 11311 + targetPort: 11311 +``` + +> NOTE: This Helm chart already includes sidecar containers for the Prometheus exporters (where applicable). These can be activated by adding the `--enable-metrics=true` parameter at deployment time. The `sidecars` parameter should therefore only be used for any extra sidecar containers. + +If additional init containers are needed in the same pod, they can be defined using the `initContainers` parameter. Here is an example: + +```yaml +initContainers: + - name: your-image-name + image: your-image + imagePullPolicy: Always + ports: + - name: portname + containerPort: 1234 +``` + +Learn more about [sidecar containers](https://kubernetes.io/docs/concepts/workloads/pods/) and [init containers](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/). + +### Deploy extra resources + +There are cases where you may want to deploy extra objects, such a ConfigMap containing your app's configuration or some extra deployment with a micro service used by your app. For covering this case, the chart allows adding the full specification of other objects using the `extraDeploy` parameter. + +### Set Pod affinity + +This chart allows you to set custom Pod affinity using the `XXX.affinity` parameter(s). Find more information about Pod affinity in the [Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). + +As an alternative, you can use the preset configurations for pod affinity, pod anti-affinity, and node affinity available at the [bitnami/common](https://github.com/bitnami/charts/tree/main/bitnami/common#affinities) chart. To do so, set the `XXX.podAffinityPreset`, `XXX.podAntiAffinityPreset`, or `XXX.nodeAffinityPreset` parameters. + +## Persistence + +The [Bitnami Jenkins](https://github.com/bitnami/containers/tree/main/bitnami/jenkins) image stores the Jenkins data and configurations at the `/bitnami/jenkins` path of the container. Persistent Volume Claims (PVCs) are used to keep the data across deployments. + +If you encounter errors when working with persistent volumes, refer to our [troubleshooting guide for persistent volumes](https://docs.bitnami.com/kubernetes/faq/troubleshooting/troubleshooting-persistence-volumes/). +s + +## Parameters + +### Global parameters + +| Name | Description | Value | +| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | +| `global.imageRegistry` | Global Docker image registry | `""` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | +| `global.defaultStorageClass` | Global default StorageClass for Persistent Volume(s) | `""` | +| `global.storageClass` | DEPRECATED: use global.defaultStorageClass instead | `""` | +| `global.compatibility.openshift.adaptSecurityContext` | Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) | `auto` | + +### Common parameters + +| Name | Description | Value | +| ------------------------ | --------------------------------------------------------------------------------------- | --------------- | +| `kubeVersion` | Override Kubernetes version | `""` | +| `nameOverride` | String to partially override common.names.fullname | `""` | +| `fullnameOverride` | String to fully override common.names.fullname | `""` | +| `replicaCount` | Number of container replicas | `1` | +| `commonLabels` | Labels to add to all deployed objects | `{}` | +| `commonAnnotations` | Annotations to add to all deployed objects | `{}` | +| `clusterDomain` | Kubernetes cluster domain name | `cluster.local` | +| `extraDeploy` | Array of extra objects to deploy with the release | `[]` | +| `diagnosticMode.enabled` | Enable diagnostic mode (all probes will be disabled and the command will be overridden) | `false` | +| `diagnosticMode.command` | Command to override all containers in the deployment | `["sleep"]` | +| `diagnosticMode.args` | Args to override all containers in the deployment | `["infinity"]` | + +### Jenkins Image parameters + +| Name | Description | Value | +| ------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------- | +| `image.registry` | Jenkins image registry | `REGISTRY_NAME` | +| `image.repository` | Jenkins image repository | `REPOSITORY_NAME/jenkins` | +| `image.digest` | Jenkins image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `image.pullPolicy` | Jenkins image pull policy | `IfNotPresent` | +| `image.pullSecrets` | Jenkins image pull secrets | `[]` | +| `image.debug` | Enable image debug mode | `false` | + +### Jenkins Configuration parameters + +| Name | Description | Value | +| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | +| `jenkinsUser` | Jenkins username | `user` | +| `jenkinsPassword` | Jenkins user password | `""` | +| `jenkinsHost` | Jenkins host to create application URLs | `""` | +| `jenkinsHome` | Jenkins home directory | `/bitnami/jenkins/home` | +| `javaOpts` | Custom JVM parameters | `[]` | +| `disableInitialization` | Skip performing the initial bootstrapping for Jenkins | `no` | +| `command` | Override default container command (useful when using custom images) | `[]` | +| `args` | Override default container args (useful when using custom images) | `[]` | +| `extraEnvVars` | Array with extra environment variables to add to the Jenkins container | `[]` | +| `extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars | `""` | +| `extraEnvVarsSecret` | Name of existing Secret containing extra env vars | `""` | +| `plugins` | List of plugins to be installed during Jenkins first boot. | `[]` | +| `extraPlugins` | List of plugins to install in addition to those listed in `plugins` | `[]` | +| `latestPlugins` | Set to true to download the latest version of all dependencies, even if the version(s) of the requested plugin(s) are not the latest. | `true` | +| `latestSpecifiedPlugins` | Set to true download the latest dependencies of any plugin that is requested to have the latest version. | `false` | +| `skipImagePlugins` | Set this value to true to skip installing plugins stored under /opt/bitnami/jenkins/plugins | `false` | +| `overridePlugins` | Setting this value to true will remove all plugins from the jenkinsHome directory and install new plugins from scratch. | `false` | +| `overridePaths` | Comma-separated list of relative paths to be removed from Jenkins home volume and/or mounted if present in the mounted content dir | `""` | +| `initScripts` | Dictionary of scripts to be mounted at `/docker-entrypoint-initdb.d`. Evaluated as a template. Allows .sh and .groovy formats. | `{}` | +| `initScriptsCM` | ConfigMap containing the `/docker-entrypoint-initdb.d` scripts. Evaluated as a template. | `""` | +| `initScriptsSecret` | Secret containing `/docker-entrypoint-initdb.d` scripts to be executed at initialization time that contain sensitive data. Evaluated as a template. | `""` | +| `initHookScripts` | Dictionary of scripts to be mounted at `$JENKINS_HOME/init.groovy.d`. Evaluated as a template. Allows .sh and .groovy formats. | `{}` | +| `initHookScriptsCM` | ConfigMap containing the `$JENKINS_HOME/init.groovy.d` scripts. Evaluated as a template. | `""` | +| `initHookScriptsSecret` | Secret containing `$JENKINS_HOME/init.groovy.d` scripts to be executed at initialization time that contain sensitive data. Evaluated as a template. | `""` | + +### Jenkins TLS configuration + +| Name | Description | Value | +| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `tls.autoGenerated` | Create self-signed TLS certificates. Currently only supports PEM certificates. | `false` | +| `tls.usePemCerts` | Use this variable if your secrets contain PEM certificates instead of PKCS12 | `false` | +| `tls.existingSecret` | Name of the existing secret containing the 'jenkins.jks' keystore, if usePemCerts is enabled, use keys 'tls.crt' and 'tls.key'. | `""` | +| `tls.password` | Password to access the JKS keystore when it is password-protected. | `""` | +| `tls.passwordsSecret` | Name of the existing secret containing the JKS keystore password. | `""` | +| `tls.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if tls.resources is set (tls.resources is recommended for production). | `nano` | +| `tls.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | + +### Jenkins Configuration as Code plugin settings (EXPERIMENTAL) + +| Name | Description | Value | +| --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | +| `configAsCode.enabled` | Enable configuration as code. | `false` | +| `configAsCode.extraConfigFiles` | List of additional configuration-as-code files to be mounted | `{}` | +| `configAsCode.securityRealm` | Content of the 'securityRealm' block | `{}` | +| `configAsCode.authorizationStrategy` | Content of the 'authorizationStrategy' block | `{}` | +| `configAsCode.security` | Content of the 'security' block | `{}` | +| `configAsCode.extraJenkins` | Append additional settings under the 'jenkins' block | `{}` | +| `configAsCode.extraConfig` | Append additional settings at the root of the configuration-as-code file | `{}` | +| `configAsCode.extraKubernetes` | Append additional settings under the Kubernetes cloud block | `{}` | +| `configAsCode.extraClouds` | Additional clouds | `[]` | +| `configAsCode.existingConfigmap` | Name of an existing configmap containing the config-as-code files. | `""` | +| `configAsCode.autoReload.enabled` | Enable the creation of the autoReload sidecar container. | `true` | +| `configAsCode.autoReload.initialDelay` | In seconds, time | `360` | +| `configAsCode.autoReload.reqRetries` | | `12` | +| `configAsCode.autoReload.interval` | | `10` | +| `configAsCode.autoReload.command` | | `[]` | +| `configAsCode.autoReload.args` | | `[]` | +| `configAsCode.autoReload.extraEnvVars` | | `[]` | +| `configAsCode.autoReload.extraEnvVarsSecret` | | `""` | +| `configAsCode.autoReload.extraEnvVarsCM` | | `""` | +| `configAsCode.autoReload.extraVolumeMounts` | | `[]` | +| `configAsCode.autoReload.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `configAsCode.autoReload.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `configAsCode.autoReload.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `configAsCode.autoReload.containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `configAsCode.autoReload.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `configAsCode.autoReload.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `configAsCode.autoReload.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `configAsCode.autoReload.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `configAsCode.autoReload.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `configAsCode.autoReload.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `configAsCode.autoReload.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, small, medium, large, xlarge, 2xlarge). This is ignored if configAsCode.autoReload.resources is set (configAsCode.autoReload.resources is recommended for production). | `none` | +| `configAsCode.autoReload.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `agent.enabled` | Set to true to enable the configuration of Jenkins kubernetes agents | `false` | +| `agent.image.registry` | Jenkins image registry | `REGISTRY_NAME` | +| `agent.image.repository` | Jenkins image repository | `REPOSITORY_NAME/jenkins-agent` | +| `agent.image.digest` | Jenkins image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `agent.image.pullPolicy` | Jenkins image pull policy | `IfNotPresent` | +| `agent.image.pullSecrets` | Jenkins image pull secrets | `[]` | +| `agent.image.debug` | Enable image debug mode | `false` | +| `agent.templateLabel` | Label for the Kubernetes agent template | `kubernetes-agent` | +| `agent.podLabels` | Additional pod labels for the Jenkins agent pods | `{}` | +| `agent.annotations` | Additional pod annotations for the Jenkins agent pods | `{}` | +| `agent.sidecars` | Additional sidecar containers for the Jenkins agent pods | `[]` | +| `agent.command` | Override default container command (useful when using custom images) | `""` | +| `agent.args` | Override default container args (useful when using custom images) | `""` | +| `agent.containerExtraEnvVars` | Additional env vars for the Jenkins agent pods | `[]` | +| `agent.podExtraEnvVars` | Additional env vars for the Jenkins agent pods | `[]` | +| `agent.extraAgentTemplate` | Extend the default agent template | `{}` | +| `agent.extraTemplates` | Provide your own custom agent templates | `[]` | +| `agent.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if agent.resources is set (agent.resources is recommended for production). | `small` | +| `agent.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `agent.containerSecurityContext.enabled` | Enable container security context | `false` | +| `agent.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `agent.containerSecurityContext.runAsUser` | User ID for the agent container | `""` | +| `agent.containerSecurityContext.runAsGroup` | User ID for the agent container | `""` | +| `agent.containerSecurityContext.privileged` | Decide if the container runs privileged. | `false` | + +### Jenkins deployment parameters + +| Name | Description | Value | +| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | +| `updateStrategy.type` | Jenkins deployment strategy type | `RollingUpdate` | +| `priorityClassName` | Jenkins pod priority class name | `""` | +| `schedulerName` | Name of the k8s scheduler (other than default) | `""` | +| `topologySpreadConstraints` | Topology Spread Constraints for pod assignment | `[]` | +| `automountServiceAccountToken` | Mount Service Account token in pod | `true` | +| `hostAliases` | Jenkins pod host aliases | `[]` | +| `extraVolumes` | Optionally specify extra list of additional volumes for Jenkins pods | `[]` | +| `extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for Jenkins container(s) | `[]` | +| `sidecars` | Add additional sidecar containers to the Jenkins pod | `[]` | +| `initContainers` | Add additional init containers to the Jenkins pods | `[]` | +| `pdb.create` | Enable/disable a Pod Disruption Budget creation | `true` | +| `pdb.minAvailable` | Minimum number/percentage of pods that should remain scheduled | `""` | +| `pdb.maxUnavailable` | Maximum number/percentage of pods that may be made unavailable. Defaults to `1` if both `pdb.minAvailable` and `pdb.maxUnavailable` are empty. | `""` | +| `lifecycleHooks` | Add lifecycle hooks to the Jenkins deployment | `{}` | +| `podLabels` | Extra labels for Jenkins pods | `{}` | +| `podAnnotations` | Annotations for Jenkins pods | `{}` | +| `podAffinityPreset` | Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `nodeAffinityPreset.type` | Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `nodeAffinityPreset.key` | Node label key to match. Ignored if `affinity` is set | `""` | +| `nodeAffinityPreset.values` | Node label values to match. Ignored if `affinity` is set | `[]` | +| `affinity` | Affinity for pod assignment | `{}` | +| `nodeSelector` | Node labels for pod assignment | `{}` | +| `tolerations` | Tolerations for pod assignment | `[]` | +| `resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `medium` | +| `resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `containerPorts.http` | Jenkins HTTP container port | `8080` | +| `containerPorts.https` | Jenkins HTTPS container port | `8443` | +| `containerPorts.agentListener` | Jenkins agent listener port, ignored if agent.enabled=false | `50000` | +| `podSecurityContext.enabled` | Enabled Jenkins pods' Security Context | `true` | +| `podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `podSecurityContext.sysctls` | Set kernel settings using the sysctl interface | `[]` | +| `podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `podSecurityContext.fsGroup` | Set Jenkins pod's Security Context fsGroup | `1001` | +| `containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `startupProbe.enabled` | Enable startupProbe | `false` | +| `startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `180` | +| `startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `startupProbe.failureThreshold` | Failure threshold for startupProbe | `6` | +| `startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `livenessProbe.enabled` | Enable livenessProbe | `true` | +| `livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `180` | +| `livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `readinessProbe.enabled` | Enable readinessProbe | `true` | +| `readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `30` | +| `readinessProbe.periodSeconds` | Period seconds for readinessProbe | `5` | +| `readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `3` | +| `readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `3` | +| `readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | + +### Traffic Exposure Parameters + +| Name | Description | Value | +| ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | +| `service.type` | Jenkins service type | `LoadBalancer` | +| `service.ports.http` | Jenkins service HTTP port | `80` | +| `service.ports.https` | Jenkins service HTTPS port | `443` | +| `service.nodePorts.http` | Node port for HTTP | `""` | +| `service.nodePorts.https` | Node port for HTTPS | `""` | +| `service.clusterIP` | Jenkins service Cluster IP | `""` | +| `service.loadBalancerIP` | Jenkins service Load Balancer IP | `""` | +| `service.loadBalancerSourceRanges` | Jenkins service Load Balancer sources | `[]` | +| `service.externalTrafficPolicy` | Jenkins service external traffic policy | `Cluster` | +| `service.annotations` | Additional custom annotations for Jenkins service | `{}` | +| `service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` | +| `service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `networkPolicy.enabled` | Specifies whether a NetworkPolicy should be created | `true` | +| `networkPolicy.allowExternal` | Don't require server label for connections | `true` | +| `networkPolicy.allowExternalEgress` | Allow the pod to access any range of port and all destinations. | `true` | +| `networkPolicy.kubeAPIServerPorts` | List of possible endpoints to kube-apiserver (limit to your cluster settings to increase security) | `[]` | +| `networkPolicy.extraIngress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `networkPolicy.extraEgress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `networkPolicy.ingressNSMatchLabels` | Labels to match to allow traffic from other namespaces | `{}` | +| `networkPolicy.ingressNSPodMatchLabels` | Pod labels to match to allow traffic from other namespaces | `{}` | +| `agentListenerService.enabled` | | `true` | +| `agentListenerService.type` | Jenkins service type | `ClusterIP` | +| `agentListenerService.ports.agentListener` | Jenkins service agent listener port | `50000` | +| `agentListenerService.nodePorts.agentListener` | Node port for agent listener | `""` | +| `agentListenerService.clusterIP` | Jenkins service Cluster IP | `""` | +| `agentListenerService.loadBalancerIP` | Jenkins service Load Balancer IP | `""` | +| `agentListenerService.loadBalancerSourceRanges` | Jenkins service Load Balancer sources | `[]` | +| `agentListenerService.externalTrafficPolicy` | Jenkins service external traffic policy | `Cluster` | +| `agentListenerService.annotations` | Additional custom annotations for Jenkins service | `{}` | +| `agentListenerService.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `agentListenerService.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` | +| `agentListenerService.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `ingress.enabled` | Enable ingress record generation for Jenkins | `false` | +| `ingress.pathType` | Ingress path type | `ImplementationSpecific` | +| `ingress.apiVersion` | Force Ingress API version (automatically detected if not set) | `""` | +| `ingress.hostname` | Default host for the ingress record | `jenkins.local` | +| `ingress.path` | Default path for the ingress record | `/` | +| `ingress.annotations` | Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. | `{}` | +| `ingress.tls` | Enable TLS configuration for the host defined at `ingress.hostname` parameter | `false` | +| `ingress.selfSigned` | Create a TLS secret for this ingress record using self-signed certificates generated by Helm | `false` | +| `ingress.extraHosts` | An array with additional hostname(s) to be covered with the ingress record | `[]` | +| `ingress.extraPaths` | An array with additional arbitrary paths that may need to be added to the ingress under the main host | `[]` | +| `ingress.extraTls` | TLS configuration for additional hostname(s) to be covered with this ingress record | `[]` | +| `ingress.secrets` | Custom TLS certificates as secrets | `[]` | +| `ingress.ingressClassName` | IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+) | `""` | +| `ingress.extraRules` | Additional rules to be covered with this ingress record | `[]` | + +### Persistence Parameters + +| Name | Description | Value | +| -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | +| `persistence.enabled` | Enable persistence using Persistent Volume Claims | `true` | +| `persistence.storageClass` | Persistent Volume storage class | `""` | +| `persistence.existingClaim` | Use a existing PVC which must be created manually before bound | `""` | +| `persistence.annotations` | Additional custom annotations for the PVC | `{}` | +| `persistence.accessModes` | Persistent Volume access modes | `[]` | +| `persistence.size` | Persistent Volume size | `8Gi` | +| `persistence.selector` | Selector to match an existing Persistent Volume for Ingester's data PVC | `{}` | +| `volumePermissions.enabled` | Enable init container that changes the owner/group of the PV mount point to `runAsUser:fsGroup` | `false` | +| `volumePermissions.image.registry` | OS Shell + Utility image registry | `REGISTRY_NAME` | +| `volumePermissions.image.repository` | OS Shell + Utility image repository | `REPOSITORY_NAME/os-shell` | +| `volumePermissions.image.digest` | OS Shell + Utility image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `volumePermissions.image.pullPolicy` | OS Shell + Utility image pull policy | `IfNotPresent` | +| `volumePermissions.image.pullSecrets` | OS Shell + Utility image pull secrets | `[]` | +| `volumePermissions.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if volumePermissions.resources is set (volumePermissions.resources is recommended for production). | `nano` | +| `volumePermissions.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `volumePermissions.securityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `volumePermissions.securityContext.runAsUser` | Set init container's Security Context runAsUser | `0` | + +### Other Parameters + +| Name | Description | Value | +| --------------------------------------------- | ---------------------------------------------------------------- | ------- | +| `rbac.create` | Specifies whether RBAC resources should be created | `true` | +| `rbac.rules` | Custom RBAC rules to set | `[]` | +| `serviceAccount.create` | Specifies whether a ServiceAccount should be created | `true` | +| `serviceAccount.name` | The name of the ServiceAccount to use. | `""` | +| `serviceAccount.annotations` | Additional Service Account annotations (evaluated as a template) | `{}` | +| `serviceAccount.automountServiceAccountToken` | Automount service account token for the server service account | `false` | + +The above parameters map to the env variables defined in [bitnami/jenkins](https://github.com/bitnami/containers/tree/main/bitnami/jenkins). For more information please refer to the [bitnami/jenkins](https://github.com/bitnami/containers/tree/main/bitnami/jenkins) image documentation. + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +helm install my-release \ + --set jenkinsUser=admin \ + --set jenkinsPassword=password \ + oci://REGISTRY_NAME/REPOSITORY_NAME/jenkins +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The above command sets the Jenkins administrator account username and password to `admin` and `password` respectively. + +> NOTE: Once this chart is deployed, it is not possible to change the application's access credentials, such as usernames or passwords, using Helm. To change these application credentials after deployment, delete any persistent volumes (PVs) used by the chart and re-deploy it, or use the application's built-in administrative tools if available. + +Alternatively, a YAML file that specifies the values for the above parameters can be provided while installing the chart. For example, + +```console +helm install my-release -f values.yaml oci://REGISTRY_NAME/REPOSITORY_NAME/jenkins +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> **Tip**: You can use the default [values.yaml](https://github.com/bitnami/charts/tree/main/bitnami/jenkins/values.yaml) + +## Troubleshooting + +Find more information about how to deal with common errors related to Bitnami's Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues). + +## Upgrading + +### To 13.0.0 + +This major bump changes the following security defaults: + +- `runAsGroup` is changed from `0` to `1001` +- `readOnlyRootFilesystem` is set to `true` +- `resourcesPreset` is changed from `none` to the minimum size working in our test suites (NOTE: `resourcesPreset` is not meant for production usage, but `resources` adapted to your use case). +- `global.compatibility.openshift.adaptSecurityContext` is changed from `disabled` to `auto`. + +This could potentially break any customization or init scripts used in your deployment. If this is the case, change the default values to the previous ones. + +### To 11.0.0 + +This major release no longer contains preinstalled plugins. In case you want to install a plugin you can follow the [official documentation](https://www.jenkins.io/doc/book/managing/plugins/) + +### To 10.0.0 + +This major release is no longer contains the metrics section because the container `bitnami/enkins-exporter` has been deprecated due to the upstream project is not maintained. + +### To 9.0.0 + +This major release renames several values in this chart and adds missing features, in order to be inline with the rest of assets in the Bitnami charts repository. + +Affected values: + +- `service.port` renamed as `service.ports.http`. +- `service.httpsPort` renamed as `service.ports.https`. +- `serviceMonitor.additionalLabels` renamed as `serviceMonitor.labels`. + +### To 8.0.0 + +Due to recent changes in the container image (see [Notable changes](https://github.com/bitnami/containers/tree/main/bitnami/jenkins#notable-changes)), the major version of the chart has been bumped preemptively. + +Upgrading from version `7.x.x` should be possible following the workaround below (the following example assumes that the release name is `jenkins`): + +- Create a backup of your Jenkins data (e.g. using Velero to backup your PV) +- Remove Jenkins deployment: + +```console +export JENKINS_PASSWORD=$(kubectl get secret --namespace default jenkins -o jsonpath="{.data.jenkins-password}" | base64 -d) +kubectl delete deployments.apps jenkins +``` + +- Upgrade your release and delete data that should not be persisted anymore: + +```console +helm upgrade jenkins oci://REGISTRY_NAME/REPOSITORY_NAME/jenkins --set jenkinsPassword=$JENKINS_PASSWORD --set jenkinsHome=/bitnami/jenkins/jenkins_home +kubectl exec -it $(kubectl get pod -l app.kubernetes.io/instance=jenkins,app.kubernetes.io/name=jenkins -o jsonpath="{.items[0].metadata.name}") -- find /bitnami/jenkins -mindepth 1 -maxdepth 1 -not -name jenkins_home -exec rm -rf {} \; +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +### To 7.0.0 + +Chart labels were adapted to follow the [Helm charts standard labels](https://helm.sh/docs/chart_best_practices/labels/#standard-labels). + +Consequences: + +- Backwards compatibility is not guaranteed. However, you can easily workaround this issue by removing Jenkins deployment before upgrading (the following example assumes that the release name is `jenkins`): + +```console +export JENKINS_PASSWORD=$(kubectl get secret --namespace default jenkins -o jsonpath="{.data.jenkins-password}" | base64 -d) +kubectl delete deployments.apps jenkins +helm upgrade jenkins oci://REGISTRY_NAME/REPOSITORY_NAME/jenkins --set jenkinsPassword=$JENKINS_PASSWORD +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +### To 6.1.0 + +This version also introduces `bitnami/common`, a [library chart](https://helm.sh/docs/topics/library_charts/#helm) as a dependency. More documentation about this new utility could be found [here](https://github.com/bitnami/charts/tree/main/bitnami/common#bitnami-common-library-chart). Please, make sure that you have updated the chart dependencies before executing any upgrade. + +### To 6.0.0 + +[On November 13, 2020, Helm v2 support formally ended](https://github.com/helm/charts#status-of-the-project). This major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +### To 5.0.0 + +The [Bitnami Jenkins](https://github.com/bitnami/containers/tree/main/bitnami/jenkins) image was migrated to a "non-root" user approach. Previously the container ran as the `root` user and the Jenkins service was started as the `jenkins` user. From now on, both the container and the Jenkins service run as user `jenkins` (`uid=1001`). You can revert this behavior by setting the parameters `securityContext.runAsUser`, and `securityContext.fsGroup` to `root`. +Ingress configuration was also adapted to follow the Helm charts best practices. + +Consequences: + +- No "privileged" actions are allowed anymore. +- Backwards compatibility is not guaranteed when persistence is enabled. + +To upgrade to `5.0.0`, install a new Jenkins chart, and migrate your Jenkins data ensuring the `jenkins` user has the appropriate permissions. + +### To 4.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 4dfac075aacf74405e31ae5b27df4369e84eb0b0 the `apiVersion` of the deployment resources was updated to `apps/v1` in tune with the api's deprecated, resulting in compatibility breakage. + +This major version signifies this change. + +### To 1.0.0 + +Backwards compatibility is not guaranteed unless you modify the labels used on the chart's deployments. +Use the workaround below to upgrade from versions previous to 1.0.0. The following example assumes that the release name is jenkins: + +```console +kubectl patch deployment jenkins --type=json -p='[{"op": "remove", "path": "/spec/selector/matchLabels/chart"}]' +``` + +## License + +Copyright © 2024 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/backing-services/jenkins/charts/common/.helmignore b/backing-services/jenkins/charts/common/.helmignore new file mode 100644 index 0000000..d0e1084 --- /dev/null +++ b/backing-services/jenkins/charts/common/.helmignore @@ -0,0 +1,26 @@ +# 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 +.vscode/ +# img folder +img/ +# Changelog +CHANGELOG.md diff --git a/backing-services/jenkins/charts/common/Chart.yaml b/backing-services/jenkins/charts/common/Chart.yaml new file mode 100644 index 0000000..0d437c4 --- /dev/null +++ b/backing-services/jenkins/charts/common/Chart.yaml @@ -0,0 +1,23 @@ +annotations: + category: Infrastructure + licenses: Apache-2.0 +apiVersion: v2 +appVersion: 2.26.0 +description: A Library Helm Chart for grouping common logic between bitnami charts. + This chart is not deployable by itself. +home: https://bitnami.com +icon: https://bitnami.com/downloads/logos/bitnami-mark.png +keywords: +- common +- helper +- template +- function +- bitnami +maintainers: +- name: Broadcom, Inc. All Rights Reserved. + url: https://github.com/bitnami/charts +name: common +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/common +type: library +version: 2.26.0 diff --git a/backing-services/jenkins/charts/common/README.md b/backing-services/jenkins/charts/common/README.md new file mode 100644 index 0000000..fee26c9 --- /dev/null +++ b/backing-services/jenkins/charts/common/README.md @@ -0,0 +1,235 @@ +# Bitnami Common Library Chart + +A [Helm Library Chart](https://helm.sh/docs/topics/library_charts/#helm) for grouping common logic between Bitnami charts. + +## TL;DR + +```yaml +dependencies: + - name: common + version: 2.x.x + repository: oci://registry-1.docker.io/bitnamicharts +``` + +```console +helm dependency update +``` + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "common.names.fullname" . }} +data: + myvalue: "Hello World" +``` + +Looking to use our applications in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the commercial edition of the Bitnami catalog. + +## Introduction + +This chart provides a common template helpers which can be used to develop new charts using [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ + +## Parameters + +## Special input schemas + +### ImageRoot + +```yaml +registry: + type: string + description: Docker registry where the image is located + example: docker.io + +repository: + type: string + description: Repository and image name + example: bitnami/nginx + +tag: + type: string + description: image tag + example: 1.16.1-debian-10-r63 + +pullPolicy: + type: string + description: Specify a imagePullPolicy. Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + +pullSecrets: + type: array + items: + type: string + description: Optionally specify an array of imagePullSecrets (evaluated as templates). + +debug: + type: boolean + description: Set to true if you would like to see extra information on logs + example: false + +## An instance would be: +# registry: docker.io +# repository: bitnami/nginx +# tag: 1.16.1-debian-10-r63 +# pullPolicy: IfNotPresent +# debug: false +``` + +### Persistence + +```yaml +enabled: + type: boolean + description: Whether enable persistence. + example: true + +storageClass: + type: string + description: Ghost data Persistent Volume Storage Class, If set to "-", storageClassName: "" which disables dynamic provisioning. + example: "-" + +accessMode: + type: string + description: Access mode for the Persistent Volume Storage. + example: ReadWriteOnce + +size: + type: string + description: Size the Persistent Volume Storage. + example: 8Gi + +path: + type: string + description: Path to be persisted. + example: /bitnami + +## An instance would be: +# enabled: true +# storageClass: "-" +# accessMode: ReadWriteOnce +# size: 8Gi +# path: /bitnami +``` + +### ExistingSecret + +```yaml +name: + type: string + description: Name of the existing secret. + example: mySecret +keyMapping: + description: Mapping between the expected key name and the name of the key in the existing secret. + type: object + +## An instance would be: +# name: mySecret +# keyMapping: +# password: myPasswordKey +``` + +#### Example of use + +When we store sensitive data for a deployment in a secret, some times we want to give to users the possibility of using theirs existing secrets. + +```yaml +# templates/secret.yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }} + labels: + app: {{ include "common.names.fullname" . }} +type: Opaque +data: + password: {{ .Values.password | b64enc | quote }} + +# templates/dpl.yaml +--- +... + env: + - name: PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "common.secrets.name" (dict "existingSecret" .Values.existingSecret "context" $) }} + key: {{ include "common.secrets.key" (dict "existingSecret" .Values.existingSecret "key" "password") }} +... + +# values.yaml +--- +name: mySecret +keyMapping: + password: myPasswordKey +``` + +### ValidateValue + +#### NOTES.txt + +```console +{{- $validateValueConf00 := (dict "valueKey" "path.to.value00" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value01" "secret" "secretName" "field" "password-01") -}} + +{{ include "common.validations.values.multiple.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} +``` + +If we force those values to be empty we will see some alerts + +```console +helm install test mychart --set path.to.value00="",path.to.value01="" + 'path.to.value00' must not be empty, please add '--set path.to.value00=$PASSWORD_00' to the command. To get the current value: + + export PASSWORD_00=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-00}" | base64 -d) + + 'path.to.value01' must not be empty, please add '--set path.to.value01=$PASSWORD_01' to the command. To get the current value: + + export PASSWORD_01=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-01}" | base64 -d) +``` + +## Upgrading + +### To 1.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +#### What changes were introduced in this major version? + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- Use `type: library`. [Here](https://v3.helm.sh/docs/faq/#library-chart-support) you can find more information. +- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts + +#### Considerations when upgrading to this version + +- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues +- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore +- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 + +#### Useful links + +- +- +- + +## License + +Copyright © 2024 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/backing-services/jenkins/charts/common/templates/_affinities.tpl b/backing-services/jenkins/charts/common/templates/_affinities.tpl new file mode 100644 index 0000000..d387dbe --- /dev/null +++ b/backing-services/jenkins/charts/common/templates/_affinities.tpl @@ -0,0 +1,155 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a soft nodeAffinity definition +{{ include "common.affinities.nodes.soft" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.soft" -}} +preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} + weight: 1 +{{- end -}} + +{{/* +Return a hard nodeAffinity definition +{{ include "common.affinities.nodes.hard" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.hard" -}} +requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} +{{- end -}} + +{{/* +Return a nodeAffinity definition +{{ include "common.affinities.nodes" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.nodes.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.nodes.hard" . -}} + {{- end -}} +{{- end -}} + +{{/* +Return a topologyKey definition +{{ include "common.affinities.topologyKey" (dict "topologyKey" "BAR") -}} +*/}} +{{- define "common.affinities.topologyKey" -}} +{{ .topologyKey | default "kubernetes.io/hostname" -}} +{{- end -}} + +{{/* +Return a soft podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.soft" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "extraNamespaces" (list "namespace1" "namespace2") "context" $) -}} +*/}} +{{- define "common.affinities.pods.soft" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +{{- $extraNamespaces := default (list) .extraNamespaces -}} +preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if $extraNamespaces }} + namespaces: + - {{ .context.Release.Namespace }} + {{- with $extraNamespaces }} + {{ include "common.tplvalues.render" (dict "value" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: 1 + {{- range $extraPodAffinityTerms }} + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: {{ .weight | default 1 -}} + {{- end -}} +{{- end -}} + +{{/* +Return a hard podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.hard" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "extraNamespaces" (list "namespace1" "namespace2") "context" $) -}} +*/}} +{{- define "common.affinities.pods.hard" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +{{- $extraNamespaces := default (list) .extraNamespaces -}} +requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if $extraNamespaces }} + namespaces: + - {{ .context.Release.Namespace }} + {{- with $extraNamespaces }} + {{ include "common.tplvalues.render" (dict "value" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- range $extraPodAffinityTerms }} + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- end -}} +{{- end -}} + +{{/* +Return a podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.pods" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.pods.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.pods.hard" . -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/jenkins/charts/common/templates/_capabilities.tpl b/backing-services/jenkins/charts/common/templates/_capabilities.tpl new file mode 100644 index 0000000..2fe81d3 --- /dev/null +++ b/backing-services/jenkins/charts/common/templates/_capabilities.tpl @@ -0,0 +1,229 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the target Kubernetes version +*/}} +{{- define "common.capabilities.kubeVersion" -}} +{{- default (default .Capabilities.KubeVersion.Version .Values.kubeVersion) ((.Values.global).kubeVersion) -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for poddisruptionbudget. +*/}} +{{- define "common.capabilities.policy.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.21-0" $kubeVersion) -}} +{{- print "policy/v1beta1" -}} +{{- else -}} +{{- print "policy/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "common.capabilities.networkPolicy.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.7-0" $kubeVersion) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for cronjob. +*/}} +{{- define "common.capabilities.cronjob.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.21-0" $kubeVersion) -}} +{{- print "batch/v1beta1" -}} +{{- else -}} +{{- print "batch/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for daemonset. +*/}} +{{- define "common.capabilities.daemonset.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.14-0" $kubeVersion) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for deployment. +*/}} +{{- define "common.capabilities.deployment.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.14-0" $kubeVersion) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for statefulset. +*/}} +{{- define "common.capabilities.statefulset.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.14-0" $kubeVersion) -}} +{{- print "apps/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "common.capabilities.ingress.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if (.Values.ingress).apiVersion -}} +{{- .Values.ingress.apiVersion -}} +{{- else if and (not (empty $kubeVersion)) (semverCompare "<1.14-0" $kubeVersion) -}} +{{- print "extensions/v1beta1" -}} +{{- else if and (not (empty $kubeVersion)) (semverCompare "<1.19-0" $kubeVersion) -}} +{{- print "networking.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end }} +{{- end -}} + +{{/* +Return the appropriate apiVersion for RBAC resources. +*/}} +{{- define "common.capabilities.rbac.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.17-0" $kubeVersion) -}} +{{- print "rbac.authorization.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "rbac.authorization.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for CRDs. +*/}} +{{- define "common.capabilities.crd.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.19-0" $kubeVersion) -}} +{{- print "apiextensions.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiextensions.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for APIService. +*/}} +{{- define "common.capabilities.apiService.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.10-0" $kubeVersion) -}} +{{- print "apiregistration.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiregistration.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Horizontal Pod Autoscaler. +*/}} +{{- define "common.capabilities.hpa.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" .context -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.23-0" $kubeVersion) -}} +{{- if .beta2 -}} +{{- print "autoscaling/v2beta2" -}} +{{- else -}} +{{- print "autoscaling/v2beta1" -}} +{{- end -}} +{{- else -}} +{{- print "autoscaling/v2" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Vertical Pod Autoscaler. +*/}} +{{- define "common.capabilities.vpa.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" .context -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.23-0" $kubeVersion) -}} +{{- if .beta2 -}} +{{- print "autoscaling/v2beta2" -}} +{{- else -}} +{{- print "autoscaling/v2beta1" -}} +{{- end -}} +{{- else -}} +{{- print "autoscaling/v2" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if PodSecurityPolicy is supported +*/}} +{{- define "common.capabilities.psp.supported" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if or (empty $kubeVersion) (semverCompare "<1.25-0" $kubeVersion) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if AdmissionConfiguration is supported +*/}} +{{- define "common.capabilities.admissionConfiguration.supported" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if or (empty $kubeVersion) (not (semverCompare "<1.23-0" $kubeVersion)) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for AdmissionConfiguration. +*/}} +{{- define "common.capabilities.admissionConfiguration.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.23-0" $kubeVersion) -}} +{{- print "apiserver.config.k8s.io/v1alpha1" -}} +{{- else if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "apiserver.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiserver.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for PodSecurityConfiguration. +*/}} +{{- define "common.capabilities.podSecurityConfiguration.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.23-0" $kubeVersion) -}} +{{- print "pod-security.admission.config.k8s.io/v1alpha1" -}} +{{- else if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "pod-security.admission.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "pod-security.admission.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the used Helm version is 3.3+. +A way to check the used Helm version was not introduced until version 3.3.0 with .Capabilities.HelmVersion, which contains an additional "{}}" structure. +This check is introduced as a regexMatch instead of {{ if .Capabilities.HelmVersion }} because checking for the key HelmVersion in <3.3 results in a "interface not found" error. +**To be removed when the catalog's minimun Helm version is 3.3** +*/}} +{{- define "common.capabilities.supportsHelmVersion" -}} +{{- if regexMatch "{(v[0-9])*[^}]*}}$" (.Capabilities | toString ) }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/jenkins/charts/common/templates/_compatibility.tpl b/backing-services/jenkins/charts/common/templates/_compatibility.tpl new file mode 100644 index 0000000..a61588d --- /dev/null +++ b/backing-services/jenkins/charts/common/templates/_compatibility.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return true if the detected platform is Openshift +Usage: +{{- include "common.compatibility.isOpenshift" . -}} +*/}} +{{- define "common.compatibility.isOpenshift" -}} +{{- if .Capabilities.APIVersions.Has "security.openshift.io/v1" -}} +{{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Render a compatible securityContext depending on the platform. By default it is maintained as it is. In other platforms like Openshift we remove default user/group values that do not work out of the box with the restricted-v1 SCC +Usage: +{{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) -}} +*/}} +{{- define "common.compatibility.renderSecurityContext" -}} +{{- $adaptedContext := .secContext -}} + +{{- if (((.context.Values.global).compatibility).openshift) -}} + {{- if or (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "force") (and (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "auto") (include "common.compatibility.isOpenshift" .context)) -}} + {{/* Remove incompatible user/group values that do not work in Openshift out of the box */}} + {{- $adaptedContext = omit $adaptedContext "fsGroup" "runAsUser" "runAsGroup" -}} + {{- if not .secContext.seLinuxOptions -}} + {{/* If it is an empty object, we remove it from the resulting context because it causes validation issues */}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{/* Remove empty seLinuxOptions object if global.compatibility.omitEmptySeLinuxOptions is set to true */}} +{{- if and (((.context.Values.global).compatibility).omitEmptySeLinuxOptions) (not .secContext.seLinuxOptions) -}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} +{{- end -}} +{{/* Remove fields that are disregarded when running the container in privileged mode */}} +{{- if $adaptedContext.privileged -}} + {{- $adaptedContext = omit $adaptedContext "capabilities" "seLinuxOptions" -}} +{{- end -}} +{{- omit $adaptedContext "enabled" | toYaml -}} +{{- end -}} diff --git a/backing-services/jenkins/charts/common/templates/_errors.tpl b/backing-services/jenkins/charts/common/templates/_errors.tpl new file mode 100644 index 0000000..e965365 --- /dev/null +++ b/backing-services/jenkins/charts/common/templates/_errors.tpl @@ -0,0 +1,28 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Through error when upgrading using empty passwords values that must not be empty. + +Usage: +{{- $validationError00 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password00" "secret" "secretName" "field" "password-00") -}} +{{- $validationError01 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password01" "secret" "secretName" "field" "password-01") -}} +{{ include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $validationError00 $validationError01) "context" $) }} + +Required password params: + - validationErrors - String - Required. List of validation strings to be return, if it is empty it won't throw error. + - context - Context - Required. Parent context. +*/}} +{{- define "common.errors.upgrade.passwords.empty" -}} + {{- $validationErrors := join "" .validationErrors -}} + {{- if and $validationErrors .context.Release.IsUpgrade -}} + {{- $errorString := "\nPASSWORDS ERROR: You must provide your current passwords when upgrading the release." -}} + {{- $errorString = print $errorString "\n Note that even after reinstallation, old credentials may be needed as they may be kept in persistent volume claims." -}} + {{- $errorString = print $errorString "\n Further information can be obtained at https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues/#credential-errors-while-upgrading-chart-releases" -}} + {{- $errorString = print $errorString "\n%s" -}} + {{- printf $errorString $validationErrors | fail -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/jenkins/charts/common/templates/_images.tpl b/backing-services/jenkins/charts/common/templates/_images.tpl new file mode 100644 index 0000000..76bb7ce --- /dev/null +++ b/backing-services/jenkins/charts/common/templates/_images.tpl @@ -0,0 +1,115 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Return the proper image name. +If image tag and digest are not defined, termination fallbacks to chart appVersion. +{{ include "common.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" .Values.global "chart" .Chart ) }} +*/}} +{{- define "common.images.image" -}} +{{- $registryName := default .imageRoot.registry ((.global).imageRegistry) -}} +{{- $repositoryName := .imageRoot.repository -}} +{{- $separator := ":" -}} +{{- $termination := .imageRoot.tag | toString -}} + +{{- if not .imageRoot.tag }} + {{- if .chart }} + {{- $termination = .chart.AppVersion | toString -}} + {{- end -}} +{{- end -}} +{{- if .imageRoot.digest }} + {{- $separator = "@" -}} + {{- $termination = .imageRoot.digest | toString -}} +{{- end -}} +{{- if $registryName }} + {{- printf "%s/%s%s%s" $registryName $repositoryName $separator $termination -}} +{{- else -}} + {{- printf "%s%s%s" $repositoryName $separator $termination -}} +{{- end -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead) +{{ include "common.images.pullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global) }} +*/}} +{{- define "common.images.pullSecrets" -}} + {{- $pullSecrets := list }} + + {{- range ((.global).imagePullSecrets) -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end }} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) -}} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names evaluating values as templates +{{ include "common.images.renderPullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $) }} +*/}} +{{- define "common.images.renderPullSecrets" -}} + {{- $pullSecrets := list }} + {{- $context := .context }} + + {{- range (($context.Values.global).imagePullSecrets) -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) -}} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper image version (ingores image revision/prerelease info & fallbacks to chart appVersion) +{{ include "common.images.version" ( dict "imageRoot" .Values.path.to.the.image "chart" .Chart ) }} +*/}} +{{- define "common.images.version" -}} +{{- $imageTag := .imageRoot.tag | toString -}} +{{/* regexp from https://github.com/Masterminds/semver/blob/23f51de38a0866c5ef0bfc42b3f735c73107b700/version.go#L41-L44 */}} +{{- if regexMatch `^([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?$` $imageTag -}} + {{- $version := semver $imageTag -}} + {{- printf "%d.%d.%d" $version.Major $version.Minor $version.Patch -}} +{{- else -}} + {{- print .chart.AppVersion -}} +{{- end -}} +{{- end -}} + diff --git a/backing-services/jenkins/charts/common/templates/_ingress.tpl b/backing-services/jenkins/charts/common/templates/_ingress.tpl new file mode 100644 index 0000000..7d2b879 --- /dev/null +++ b/backing-services/jenkins/charts/common/templates/_ingress.tpl @@ -0,0 +1,73 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Generate backend entry that is compatible with all Kubernetes API versions. + +Usage: +{{ include "common.ingress.backend" (dict "serviceName" "backendName" "servicePort" "backendPort" "context" $) }} + +Params: + - serviceName - String. Name of an existing service backend + - servicePort - String/Int. Port name (or number) of the service. It will be translated to different yaml depending if it is a string or an integer. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.ingress.backend" -}} +{{- $apiVersion := (include "common.capabilities.ingress.apiVersion" .context) -}} +{{- if or (eq $apiVersion "extensions/v1beta1") (eq $apiVersion "networking.k8s.io/v1beta1") -}} +serviceName: {{ .serviceName }} +servicePort: {{ .servicePort }} +{{- else -}} +service: + name: {{ .serviceName }} + port: + {{- if typeIs "string" .servicePort }} + name: {{ .servicePort }} + {{- else if or (typeIs "int" .servicePort) (typeIs "float64" .servicePort) }} + number: {{ .servicePort | int }} + {{- end }} +{{- end -}} +{{- end -}} + +{{/* +Print "true" if the API pathType field is supported +Usage: +{{ include "common.ingress.supportsPathType" . }} +*/}} +{{- define "common.ingress.supportsPathType" -}} +{{- if (semverCompare "<1.18-0" (include "common.capabilities.kubeVersion" .)) -}} +{{- print "false" -}} +{{- else -}} +{{- print "true" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the ingressClassname field is supported +Usage: +{{ include "common.ingress.supportsIngressClassname" . }} +*/}} +{{- define "common.ingress.supportsIngressClassname" -}} +{{- if semverCompare "<1.18-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "false" -}} +{{- else -}} +{{- print "true" -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if cert-manager required annotations for TLS signed +certificates are set in the Ingress annotations +Ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations +Usage: +{{ include "common.ingress.certManagerRequest" ( dict "annotations" .Values.path.to.the.ingress.annotations ) }} +*/}} +{{- define "common.ingress.certManagerRequest" -}} +{{ if or (hasKey .annotations "cert-manager.io/cluster-issuer") (hasKey .annotations "cert-manager.io/issuer") (hasKey .annotations "kubernetes.io/tls-acme") }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/jenkins/charts/common/templates/_labels.tpl b/backing-services/jenkins/charts/common/templates/_labels.tpl new file mode 100644 index 0000000..0a0cc54 --- /dev/null +++ b/backing-services/jenkins/charts/common/templates/_labels.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Kubernetes standard labels +{{ include "common.labels.standard" (dict "customLabels" .Values.commonLabels "context" $) -}} +*/}} +{{- define "common.labels.standard" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{- $default := dict "app.kubernetes.io/name" (include "common.names.name" .context) "helm.sh/chart" (include "common.names.chart" .context) "app.kubernetes.io/instance" .context.Release.Name "app.kubernetes.io/managed-by" .context.Release.Service -}} +{{- with .context.Chart.AppVersion -}} +{{- $_ := set $default "app.kubernetes.io/version" . -}} +{{- end -}} +{{ template "common.tplvalues.merge" (dict "values" (list .customLabels $default) "context" .context) }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +helm.sh/chart: {{ include "common.names.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Chart.AppVersion }} +app.kubernetes.io/version: {{ . | quote }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Labels used on immutable fields such as deploy.spec.selector.matchLabels or svc.spec.selector +{{ include "common.labels.matchLabels" (dict "customLabels" .Values.podLabels "context" $) -}} + +We don't want to loop over custom labels appending them to the selector +since it's very likely that it will break deployments, services, etc. +However, it's important to overwrite the standard labels if the user +overwrote them on metadata.labels fields. +*/}} +{{- define "common.labels.matchLabels" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{ merge (pick (include "common.tplvalues.render" (dict "value" .customLabels "context" .context) | fromYaml) "app.kubernetes.io/name" "app.kubernetes.io/instance") (dict "app.kubernetes.io/name" (include "common.names.name" .context) "app.kubernetes.io/instance" .context.Release.Name ) | toYaml }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} +{{- end -}} diff --git a/backing-services/jenkins/charts/common/templates/_names.tpl b/backing-services/jenkins/charts/common/templates/_names.tpl new file mode 100644 index 0000000..ba83956 --- /dev/null +++ b/backing-services/jenkins/charts/common/templates/_names.tpl @@ -0,0 +1,71 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "common.names.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "common.names.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "common.names.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 dependency name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +Usage: +{{ include "common.names.dependency.fullname" (dict "chartName" "dependency-chart-name" "chartValues" .Values.dependency-chart "context" $) }} +*/}} +{{- define "common.names.dependency.fullname" -}} +{{- if .chartValues.fullnameOverride -}} +{{- .chartValues.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .chartName .chartValues.nameOverride -}} +{{- if contains $name .context.Release.Name -}} +{{- .context.Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .context.Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts. +*/}} +{{- define "common.names.namespace" -}} +{{- default .Release.Namespace .Values.namespaceOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a fully qualified app name adding the installation's namespace. +*/}} +{{- define "common.names.fullname.namespace" -}} +{{- printf "%s-%s" (include "common.names.fullname" .) (include "common.names.namespace" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/backing-services/jenkins/charts/common/templates/_resources.tpl b/backing-services/jenkins/charts/common/templates/_resources.tpl new file mode 100644 index 0000000..d8a43e1 --- /dev/null +++ b/backing-services/jenkins/charts/common/templates/_resources.tpl @@ -0,0 +1,50 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a resource request/limit object based on a given preset. +These presets are for basic testing and not meant to be used in production +{{ include "common.resources.preset" (dict "type" "nano") -}} +*/}} +{{- define "common.resources.preset" -}} +{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} +{{- $presets := dict + "nano" (dict + "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "2Gi") + ) + "micro" (dict + "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "2Gi") + ) + "small" (dict + "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "2Gi") + ) + "medium" (dict + "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "2Gi") + ) + "large" (dict + "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "2Gi") + ) + "xlarge" (dict + "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "2Gi") + ) + "2xlarge" (dict + "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "2Gi") + ) + }} +{{- if hasKey $presets .type -}} +{{- index $presets .type | toYaml -}} +{{- else -}} +{{- printf "ERROR: Preset key '%s' invalid. Allowed values are %s" .type (join "," (keys $presets)) | fail -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/jenkins/charts/common/templates/_secrets.tpl b/backing-services/jenkins/charts/common/templates/_secrets.tpl new file mode 100644 index 0000000..801918c --- /dev/null +++ b/backing-services/jenkins/charts/common/templates/_secrets.tpl @@ -0,0 +1,185 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Generate secret name. + +Usage: +{{ include "common.secrets.name" (dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $) }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - defaultNameSuffix - String - Optional. It is used only if we have several secrets in the same deployment. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.secrets.name" -}} +{{- $name := (include "common.names.fullname" .context) -}} + +{{- if .defaultNameSuffix -}} +{{- $name = printf "%s-%s" $name .defaultNameSuffix | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- with .existingSecret -}} +{{- if not (typeIs "string" .) -}} +{{- with .name -}} +{{- $name = . -}} +{{- end -}} +{{- else -}} +{{- $name = . -}} +{{- end -}} +{{- end -}} + +{{- printf "%s" $name -}} +{{- end -}} + +{{/* +Generate secret key. + +Usage: +{{ include "common.secrets.key" (dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName") }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - key - String - Required. Name of the key in the secret. +*/}} +{{- define "common.secrets.key" -}} +{{- $key := .key -}} + +{{- if .existingSecret -}} + {{- if not (typeIs "string" .existingSecret) -}} + {{- if .existingSecret.keyMapping -}} + {{- $key = index .existingSecret.keyMapping $.key -}} + {{- end -}} + {{- end }} +{{- end -}} + +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Generate secret password or retrieve one if already created. + +Usage: +{{ include "common.secrets.passwords.manage" (dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - providedValues - List - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - length - int - Optional - Length of the generated random password. + - strong - Boolean - Optional - Whether to add symbols to the generated random password. + - chartName - String - Optional - Name of the chart used when said chart is deployed as a subchart. + - context - Context - Required - Parent context. + - failOnNew - Boolean - Optional - Default to true. If set to false, skip errors adding new keys to existing secrets. + - skipB64enc - Boolean - Optional - Default to false. If set to true, no the secret will not be base64 encrypted. + - skipQuote - Boolean - Optional - Default to false. If set to true, no quotes will be added around the secret. +The order in which this function returns a secret password: + 1. Already existing 'Secret' resource + (If a 'Secret' resource is found under the name provided to the 'secret' parameter to this function and that 'Secret' resource contains a key with the name passed as the 'key' parameter to this function then the value of this existing secret password will be returned) + 2. Password provided via the values.yaml + (If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned) + 3. Randomly generated secret password + (A new random secret password with the length specified in the 'length' parameter will be generated and returned) + +*/}} +{{- define "common.secrets.passwords.manage" -}} + +{{- $password := "" }} +{{- $subchart := "" }} +{{- $chartName := default "" .chartName }} +{{- $passwordLength := default 10 .length }} +{{- $providedPasswordKey := include "common.utils.getKeyFromList" (dict "keys" .providedValues "context" $.context) }} +{{- $providedPasswordValue := include "common.utils.getValueFromKey" (dict "key" $providedPasswordKey "context" $.context) }} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data }} +{{- if $secretData }} + {{- if hasKey $secretData .key }} + {{- $password = index $secretData .key | b64dec }} + {{- else if not (eq .failOnNew false) }} + {{- printf "\nPASSWORDS ERROR: The secret \"%s\" does not contain the key \"%s\"\n" .secret .key | fail -}} + {{- end -}} +{{- end }} + +{{- if not $password }} + {{- if $providedPasswordValue }} + {{- $password = $providedPasswordValue | toString }} + {{- else }} + {{- if .context.Values.enabled }} + {{- $subchart = $chartName }} + {{- end -}} + + {{- if not (eq .failOnNew false) }} + {{- $requiredPassword := dict "valueKey" $providedPasswordKey "secret" .secret "field" .key "subchart" $subchart "context" $.context -}} + {{- $requiredPasswordError := include "common.validations.values.single.empty" $requiredPassword -}} + {{- $passwordValidationErrors := list $requiredPasswordError -}} + {{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" $passwordValidationErrors "context" $.context) -}} + {{- end }} + + {{- if .strong }} + {{- $subStr := list (lower (randAlpha 1)) (randNumeric 1) (upper (randAlpha 1)) | join "_" }} + {{- $password = randAscii $passwordLength }} + {{- $password = regexReplaceAllLiteral "\\W" $password "@" | substr 5 $passwordLength }} + {{- $password = printf "%s%s" $subStr $password | toString | shuffle }} + {{- else }} + {{- $password = randAlphaNum $passwordLength }} + {{- end }} + {{- end -}} +{{- end -}} +{{- if not .skipB64enc }} +{{- $password = $password | b64enc }} +{{- end -}} +{{- if .skipQuote -}} +{{- printf "%s" $password -}} +{{- else -}} +{{- printf "%s" $password | quote -}} +{{- end -}} +{{- end -}} + +{{/* +Reuses the value from an existing secret, otherwise sets its value to a default value. + +Usage: +{{ include "common.secrets.lookup" (dict "secret" "secret-name" "key" "keyName" "defaultValue" .Values.myValue "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - defaultValue - String - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - context - Context - Required - Parent context. + +*/}} +{{- define "common.secrets.lookup" -}} +{{- $value := "" -}} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data -}} +{{- if and $secretData (hasKey $secretData .key) -}} + {{- $value = index $secretData .key -}} +{{- else if .defaultValue -}} + {{- $value = .defaultValue | toString | b64enc -}} +{{- end -}} +{{- if $value -}} +{{- printf "%s" $value -}} +{{- end -}} +{{- end -}} + +{{/* +Returns whether a previous generated secret already exists + +Usage: +{{ include "common.secrets.exists" (dict "secret" "secret-name" "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - context - Context - Required - Parent context. +*/}} +{{- define "common.secrets.exists" -}} +{{- $secret := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret) }} +{{- if $secret }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/jenkins/charts/common/templates/_storage.tpl b/backing-services/jenkins/charts/common/templates/_storage.tpl new file mode 100644 index 0000000..aa75856 --- /dev/null +++ b/backing-services/jenkins/charts/common/templates/_storage.tpl @@ -0,0 +1,21 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the proper Storage Class +{{ include "common.storage.class" ( dict "persistence" .Values.path.to.the.persistence "global" $) }} +*/}} +{{- define "common.storage.class" -}} +{{- $storageClass := (.global).storageClass | default .persistence.storageClass | default (.global).defaultStorageClass | default "" -}} +{{- if $storageClass -}} + {{- if (eq "-" $storageClass) -}} + {{- printf "storageClassName: \"\"" -}} + {{- else -}} + {{- printf "storageClassName: %s" $storageClass -}} + {{- end -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/jenkins/charts/common/templates/_tplvalues.tpl b/backing-services/jenkins/charts/common/templates/_tplvalues.tpl new file mode 100644 index 0000000..a04f4c1 --- /dev/null +++ b/backing-services/jenkins/charts/common/templates/_tplvalues.tpl @@ -0,0 +1,52 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Renders a value that contains template perhaps with scope if the scope is present. +Usage: +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ ) }} +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ "scope" $app ) }} +*/}} +{{- define "common.tplvalues.render" -}} +{{- $value := typeIs "string" .value | ternary .value (.value | toYaml) }} +{{- if contains "{{" (toJson .value) }} + {{- if .scope }} + {{- tpl (cat "{{- with $.RelativeScope -}}" $value "{{- end }}") (merge (dict "RelativeScope" .scope) .context) }} + {{- else }} + {{- tpl $value .context }} + {{- end }} +{{- else }} + {{- $value }} +{{- end }} +{{- end -}} + +{{/* +Merge a list of values that contains template after rendering them. +Merge precedence is consistent with http://masterminds.github.io/sprig/dicts.html#merge-mustmerge +Usage: +{{ include "common.tplvalues.merge" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }} +*/}} +{{- define "common.tplvalues.merge" -}} +{{- $dst := dict -}} +{{- range .values -}} +{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | merge $dst -}} +{{- end -}} +{{ $dst | toYaml }} +{{- end -}} + +{{/* +Merge a list of values that contains template after rendering them. +Merge precedence is consistent with https://masterminds.github.io/sprig/dicts.html#mergeoverwrite-mustmergeoverwrite +Usage: +{{ include "common.tplvalues.merge-overwrite" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }} +*/}} +{{- define "common.tplvalues.merge-overwrite" -}} +{{- $dst := dict -}} +{{- range .values -}} +{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | mergeOverwrite $dst -}} +{{- end -}} +{{ $dst | toYaml }} +{{- end -}} diff --git a/backing-services/jenkins/charts/common/templates/_utils.tpl b/backing-services/jenkins/charts/common/templates/_utils.tpl new file mode 100644 index 0000000..d53c74a --- /dev/null +++ b/backing-services/jenkins/charts/common/templates/_utils.tpl @@ -0,0 +1,77 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Print instructions to get a secret value. +Usage: +{{ include "common.utils.secret.getvalue" (dict "secret" "secret-name" "field" "secret-value-field" "context" $) }} +*/}} +{{- define "common.utils.secret.getvalue" -}} +{{- $varname := include "common.utils.fieldToEnvVar" . -}} +export {{ $varname }}=$(kubectl get secret --namespace {{ include "common.names.namespace" .context | quote }} {{ .secret }} -o jsonpath="{.data.{{ .field }}}" | base64 -d) +{{- end -}} + +{{/* +Build env var name given a field +Usage: +{{ include "common.utils.fieldToEnvVar" dict "field" "my-password" }} +*/}} +{{- define "common.utils.fieldToEnvVar" -}} + {{- $fieldNameSplit := splitList "-" .field -}} + {{- $upperCaseFieldNameSplit := list -}} + + {{- range $fieldNameSplit -}} + {{- $upperCaseFieldNameSplit = append $upperCaseFieldNameSplit ( upper . ) -}} + {{- end -}} + + {{ join "_" $upperCaseFieldNameSplit }} +{{- end -}} + +{{/* +Gets a value from .Values given +Usage: +{{ include "common.utils.getValueFromKey" (dict "key" "path.to.key" "context" $) }} +*/}} +{{- define "common.utils.getValueFromKey" -}} +{{- $splitKey := splitList "." .key -}} +{{- $value := "" -}} +{{- $latestObj := $.context.Values -}} +{{- range $splitKey -}} + {{- if not $latestObj -}} + {{- printf "please review the entire path of '%s' exists in values" $.key | fail -}} + {{- end -}} + {{- $value = ( index $latestObj . ) -}} + {{- $latestObj = $value -}} +{{- end -}} +{{- printf "%v" (default "" $value) -}} +{{- end -}} + +{{/* +Returns first .Values key with a defined value or first of the list if all non-defined +Usage: +{{ include "common.utils.getKeyFromList" (dict "keys" (list "path.to.key1" "path.to.key2") "context" $) }} +*/}} +{{- define "common.utils.getKeyFromList" -}} +{{- $key := first .keys -}} +{{- $reverseKeys := reverse .keys }} +{{- range $reverseKeys }} + {{- $value := include "common.utils.getValueFromKey" (dict "key" . "context" $.context ) }} + {{- if $value -}} + {{- $key = . }} + {{- end -}} +{{- end -}} +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Checksum a template at "path" containing a *single* resource (ConfigMap,Secret) for use in pod annotations, excluding the metadata (see #18376). +Usage: +{{ include "common.utils.checksumTemplate" (dict "path" "/configmap.yaml" "context" $) }} +*/}} +{{- define "common.utils.checksumTemplate" -}} +{{- $obj := include (print .context.Template.BasePath .path) .context | fromYaml -}} +{{ omit $obj "apiVersion" "kind" "metadata" | toYaml | sha256sum }} +{{- end -}} diff --git a/backing-services/jenkins/charts/common/templates/_warnings.tpl b/backing-services/jenkins/charts/common/templates/_warnings.tpl new file mode 100644 index 0000000..e4dbecd --- /dev/null +++ b/backing-services/jenkins/charts/common/templates/_warnings.tpl @@ -0,0 +1,109 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Warning about using rolling tag. +Usage: +{{ include "common.warnings.rollingTag" .Values.path.to.the.imageRoot }} +*/}} +{{- define "common.warnings.rollingTag" -}} + +{{- if and (contains "bitnami/" .repository) (not (.tag | toString | regexFind "-r\\d+$|sha256:")) }} +WARNING: Rolling tag detected ({{ .repository }}:{{ .tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. ++info https://docs.vmware.com/en/VMware-Tanzu-Application-Catalog/services/tutorials/GUID-understand-rolling-tags-containers-index.html +{{- end }} +{{- end -}} + +{{/* +Warning about replaced images from the original. +Usage: +{{ include "common.warnings.modifiedImages" (dict "images" (list .Values.path.to.the.imageRoot) "context" $) }} +*/}} +{{- define "common.warnings.modifiedImages" -}} +{{- $affectedImages := list -}} +{{- $printMessage := false -}} +{{- $originalImages := .context.Chart.Annotations.images -}} +{{- range .images -}} + {{- $fullImageName := printf (printf "%s/%s:%s" .registry .repository .tag) -}} + {{- if not (contains $fullImageName $originalImages) }} + {{- $affectedImages = append $affectedImages (printf "%s/%s:%s" .registry .repository .tag) -}} + {{- $printMessage = true -}} + {{- end -}} +{{- end -}} +{{- if $printMessage }} + +⚠ SECURITY WARNING: Original containers have been substituted. This Helm chart was designed, tested, and validated on multiple platforms using a specific set of Bitnami and Tanzu Application Catalog containers. Substituting other containers is likely to cause degraded security and performance, broken chart features, and missing environment variables. + +Substituted images detected: +{{- range $affectedImages }} + - {{ . }} +{{- end }} +{{- end -}} +{{- end -}} + +{{/* +Warning about not setting the resource object in all deployments. +Usage: +{{ include "common.warnings.resources" (dict "sections" (list "path1" "path2") context $) }} +Example: +{{- include "common.warnings.resources" (dict "sections" (list "csiProvider.provider" "server" "volumePermissions" "") "context" $) }} +The list in the example assumes that the following values exist: + - csiProvider.provider.resources + - server.resources + - volumePermissions.resources + - resources +*/}} +{{- define "common.warnings.resources" -}} +{{- $values := .context.Values -}} +{{- $printMessage := false -}} +{{ $affectedSections := list -}} +{{- range .sections -}} + {{- if eq . "" -}} + {{/* Case where the resources section is at the root (one main deployment in the chart) */}} + {{- if not (index $values "resources") -}} + {{- $affectedSections = append $affectedSections "resources" -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Case where the are multiple resources sections (more than one main deployment in the chart) */}} + {{- $keys := split "." . -}} + {{/* We iterate through the different levels until arriving to the resource section. Example: a.b.c.resources */}} + {{- $section := $values -}} + {{- range $keys -}} + {{- $section = index $section . -}} + {{- end -}} + {{- if not (index $section "resources") -}} + {{/* If the section has enabled=false or replicaCount=0, do not include it */}} + {{- if and (hasKey $section "enabled") -}} + {{- if index $section "enabled" -}} + {{/* enabled=true */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else if and (hasKey $section "replicaCount") -}} + {{/* We need a casting to int because number 0 is not treated as an int by default */}} + {{- if (gt (index $section "replicaCount" | int) 0) -}} + {{/* replicaCount > 0 */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Default case, add it to the affected sections */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- if $printMessage }} + +WARNING: There are "resources" sections in the chart not set. Using "resourcesPreset" is not recommended for production. For production installations, please set the following values according to your workload needs: +{{- range $affectedSections }} + - {{ . }} +{{- end }} ++info https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +{{- end -}} +{{- end -}} diff --git a/backing-services/jenkins/charts/common/templates/validations/_cassandra.tpl b/backing-services/jenkins/charts/common/templates/validations/_cassandra.tpl new file mode 100644 index 0000000..f8fd213 --- /dev/null +++ b/backing-services/jenkins/charts/common/templates/validations/_cassandra.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.cassandra.values.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.cassandra.dbUser.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.dbUser.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled cassandra. + +Usage: +{{ include "common.cassandra.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.cassandra.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.cassandra.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key dbUser + +Usage: +{{ include "common.cassandra.values.key.dbUser" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.key.dbUser" -}} + {{- if .subchart -}} + cassandra.dbUser + {{- else -}} + dbUser + {{- end -}} +{{- end -}} diff --git a/backing-services/jenkins/charts/common/templates/validations/_mariadb.tpl b/backing-services/jenkins/charts/common/templates/validations/_mariadb.tpl new file mode 100644 index 0000000..6ea8c0f --- /dev/null +++ b/backing-services/jenkins/charts/common/templates/validations/_mariadb.tpl @@ -0,0 +1,108 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MariaDB required passwords are not empty. + +Usage: +{{ include "common.validations.values.mariadb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MariaDB values are stored, e.g: "mysql-passwords-secret" + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mariadb.passwords" -}} + {{- $existingSecret := include "common.mariadb.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mariadb.values.enabled" . -}} + {{- $architecture := include "common.mariadb.values.architecture" . -}} + {{- $authPrefix := include "common.mariadb.values.key.auth" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mariadb-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- if not (empty $valueUsername) -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mariadb-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replication") -}} + {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mariadb-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mariadb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mariadb. + +Usage: +{{ include "common.mariadb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mariadb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mariadb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mariadb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mariadb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.key.auth" -}} + {{- if .subchart -}} + mariadb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/backing-services/jenkins/charts/common/templates/validations/_mongodb.tpl b/backing-services/jenkins/charts/common/templates/validations/_mongodb.tpl new file mode 100644 index 0000000..e678a6d --- /dev/null +++ b/backing-services/jenkins/charts/common/templates/validations/_mongodb.tpl @@ -0,0 +1,67 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mongodb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDb is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mongodb. + +Usage: +{{ include "common.mongodb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mongodb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mongodb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mongodb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.key.auth" -}} + {{- if .subchart -}} + mongodb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mongodb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/jenkins/charts/common/templates/validations/_mysql.tpl b/backing-services/jenkins/charts/common/templates/validations/_mysql.tpl new file mode 100644 index 0000000..fbb65c3 --- /dev/null +++ b/backing-services/jenkins/charts/common/templates/validations/_mysql.tpl @@ -0,0 +1,67 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mysql.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mysql. + +Usage: +{{ include "common.mysql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mysql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mysql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mysql.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mysql.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.key.auth" -}} + {{- if .subchart -}} + mysql.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/backing-services/jenkins/charts/common/templates/validations/_postgresql.tpl b/backing-services/jenkins/charts/common/templates/validations/_postgresql.tpl new file mode 100644 index 0000000..51d4716 --- /dev/null +++ b/backing-services/jenkins/charts/common/templates/validations/_postgresql.tpl @@ -0,0 +1,105 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to decide whether evaluate global values. + +Usage: +{{ include "common.postgresql.values.use.global" (dict "key" "key-of-global" "context" $) }} +Params: + - key - String - Required. Field to be evaluated within global, e.g: "existingSecret" +*/}} +{{- define "common.postgresql.values.use.global" -}} + {{- if .context.Values.global -}} + {{- if .context.Values.global.postgresql -}} + {{- index .context.Values.global.postgresql .key | quote -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.postgresql.values.existingSecret" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.existingSecret" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "existingSecret" "context" .context) -}} + + {{- if .subchart -}} + {{- default (.context.Values.postgresql.existingSecret | quote) $globalValue -}} + {{- else -}} + {{- default (.context.Values.existingSecret | quote) $globalValue -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled postgresql. + +Usage: +{{ include "common.postgresql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key postgressPassword. + +Usage: +{{ include "common.postgresql.values.key.postgressPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.postgressPassword" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "postgresqlUsername" "context" .context) -}} + + {{- if not $globalValue -}} + {{- if .subchart -}} + postgresql.postgresqlPassword + {{- else -}} + postgresqlPassword + {{- end -}} + {{- else -}} + global.postgresql.postgresqlPassword + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled.replication. + +Usage: +{{ include "common.postgresql.values.enabled.replication" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.enabled.replication" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.replication.enabled -}} + {{- else -}} + {{- printf "%v" .context.Values.replication.enabled -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key replication.password. + +Usage: +{{ include "common.postgresql.values.key.replicationPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.replicationPassword" -}} + {{- if .subchart -}} + postgresql.replication.password + {{- else -}} + replication.password + {{- end -}} +{{- end -}} diff --git a/backing-services/jenkins/charts/common/templates/validations/_redis.tpl b/backing-services/jenkins/charts/common/templates/validations/_redis.tpl new file mode 100644 index 0000000..9fedfef --- /dev/null +++ b/backing-services/jenkins/charts/common/templates/validations/_redis.tpl @@ -0,0 +1,48 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for enabled redis. + +Usage: +{{ include "common.redis.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.redis.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.redis.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right prefix path for the values + +Usage: +{{ include "common.redis.values.key.prefix" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false +*/}} +{{- define "common.redis.values.keys.prefix" -}} + {{- if .subchart -}}redis.{{- else -}}{{- end -}} +{{- end -}} + +{{/* +Checks whether the redis chart's includes the standarizations (version >= 14) + +Usage: +{{ include "common.redis.values.standarized.version" (dict "context" $) }} +*/}} +{{- define "common.redis.values.standarized.version" -}} + + {{- $standarizedAuth := printf "%s%s" (include "common.redis.values.keys.prefix" .) "auth" -}} + {{- $standarizedAuthValues := include "common.utils.getValueFromKey" (dict "key" $standarizedAuth "context" .context) }} + + {{- if $standarizedAuthValues -}} + {{- true -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/jenkins/charts/common/templates/validations/_validations.tpl b/backing-services/jenkins/charts/common/templates/validations/_validations.tpl new file mode 100644 index 0000000..7cdee61 --- /dev/null +++ b/backing-services/jenkins/charts/common/templates/validations/_validations.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate values must not be empty. + +Usage: +{{- $validateValueConf00 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-01") -}} +{{ include "common.validations.values.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" +*/}} +{{- define "common.validations.values.multiple.empty" -}} + {{- range .required -}} + {{- include "common.validations.values.single.empty" (dict "valueKey" .valueKey "secret" .secret "field" .field "context" $.context) -}} + {{- end -}} +{{- end -}} + +{{/* +Validate a value must not be empty. + +Usage: +{{ include "common.validations.value.empty" (dict "valueKey" "mariadb.password" "secret" "secretName" "field" "my-password" "subchart" "subchart" "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" + - subchart - String - Optional - Name of the subchart that the validated password is part of. +*/}} +{{- define "common.validations.values.single.empty" -}} + {{- $value := include "common.utils.getValueFromKey" (dict "key" .valueKey "context" .context) }} + {{- $subchart := ternary "" (printf "%s." .subchart) (empty .subchart) }} + + {{- if not $value -}} + {{- $varname := "my-value" -}} + {{- $getCurrentValue := "" -}} + {{- if and .secret .field -}} + {{- $varname = include "common.utils.fieldToEnvVar" . -}} + {{- $getCurrentValue = printf " To get the current value:\n\n %s\n" (include "common.utils.secret.getvalue" .) -}} + {{- end -}} + {{- printf "\n '%s' must not be empty, please add '--set %s%s=$%s' to the command.%s" .valueKey $subchart .valueKey $varname $getCurrentValue -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/jenkins/charts/common/values.yaml b/backing-services/jenkins/charts/common/values.yaml new file mode 100644 index 0000000..de2cac5 --- /dev/null +++ b/backing-services/jenkins/charts/common/values.yaml @@ -0,0 +1,8 @@ +# Copyright Broadcom, Inc. All Rights Reserved. +# SPDX-License-Identifier: APACHE-2.0 + +## bitnami/common +## It is required by CI/CD tools and processes. +## @skip exampleValue +## +exampleValue: common-chart diff --git a/backing-services/jenkins/school-stage-eks.values.yaml b/backing-services/jenkins/school-stage-eks.values.yaml new file mode 100644 index 0000000..76160cb --- /dev/null +++ b/backing-services/jenkins/school-stage-eks.values.yaml @@ -0,0 +1,22 @@ +service: + type: LoadBalancer + annotations: + service.beta.kubernetes.io/aws-load-balancer-type: "nlb" + service.beta.kubernetes.io/aws-load-balancer-type: external + service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing + service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: instance + +jenkinsPassword: "Tavana123$" + +persistence: + enabled: true + storageClass: "efs-sc" + +serviceAccount: + create: true + name: "jenkinsservcieaccount" + annotations: + eks.amazonaws.com/role-arn: "arn:aws:iam::889565812003:role/schoolbuses-cluster-20241110104436981500000002" + +agent: + enabled: true \ No newline at end of file diff --git a/backing-services/jenkins/templates/NOTES.txt b/backing-services/jenkins/templates/NOTES.txt new file mode 100644 index 0000000..1004503 --- /dev/null +++ b/backing-services/jenkins/templates/NOTES.txt @@ -0,0 +1,49 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +** Please be patient while the chart is being deployed ** + +{{- if .Values.ingress.enabled }} + +1. Get the Jenkins URL and associate its hostname to your cluster external IP: + + export CLUSTER_IP=$(minikube ip) # On Minikube. Use: `kubectl cluster-info` on others K8s clusters + echo "Jenkins URL: http{{ if .Values.ingress.tls }}s{{ end }}://{{ .Values.ingress.hostname }}" + echo "$CLUSTER_IP {{ .Values.ingress.hostname }}" | sudo tee -a /etc/hosts + +{{- else }} + +1. Get the Jenkins URL by running: + +{{- if contains "NodePort" .Values.service.type }} + + export NODE_PORT=$(kubectl get --namespace {{ include "common.names.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "common.names.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ include "common.names.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo "Jenkins URL: http://$NODE_IP:$NODE_PORT/" + +{{- else if contains "LoadBalancer" .Values.service.type }} + +** Please ensure an external IP is associated to the {{ template "common.names.fullname" . }} service before proceeding ** +** Watch the status using: kubectl get svc --namespace {{ include "common.names.namespace" . }} -w {{ template "common.names.fullname" . }} ** + + export SERVICE_IP=$(kubectl get svc --namespace {{ include "common.names.namespace" . }} {{ template "common.names.fullname" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") +{{- $port:=.Values.service.ports.http | toString }} + echo "Jenkins URL: http://$SERVICE_IP{{- if ne $port "80" }}:{{ .Values.service.ports.http }}{{ end }}/" + +{{- else if contains "ClusterIP" .Values.service.type }} + + echo "Jenkins URL: http://127.0.0.1:8080/" + kubectl port-forward --namespace {{ include "common.names.namespace" . }} svc/{{ template "common.names.fullname" . }} 8080:{{ .Values.service.ports.http }} + +{{- end }} +{{- end }} + +2. Login with the following credentials + + echo Username: {{ .Values.jenkinsUser }} + echo Password: $(kubectl get secret --namespace {{ include "common.names.namespace" . }} {{ template "common.names.fullname" . }} -o jsonpath="{.data.jenkins-password}" | base64 -d) + +{{- include "jenkins.checkRollingTags" . }} +{{- include "common.warnings.resources" (dict "sections" (list "agent" "" "tls" "volumePermissions") "context" $) }} +{{- include "common.warnings.modifiedImages" (dict "images" (list .Values.image .Values.agent.image .Values.volumePermissions.image) "context" $) }} \ No newline at end of file diff --git a/backing-services/jenkins/templates/_helpers.tpl b/backing-services/jenkins/templates/_helpers.tpl new file mode 100644 index 0000000..ac13913 --- /dev/null +++ b/backing-services/jenkins/templates/_helpers.tpl @@ -0,0 +1,150 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the proper Jenkins image name +*/}} +{{- define "jenkins.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper Jenkins agent image name +*/}} +{{- define "jenkins.agent.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.agent.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper image name (for the init container volume-permissions image) +*/}} +{{- define "jenkins.volumePermissions.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.volumePermissions.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "jenkins.imagePullSecrets" -}} +{{- include "common.images.renderPullSecrets" (dict "images" (list .Values.image .Values.volumePermissions.image) "context" $) -}} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "jenkins.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "common.names.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Gets the host to be used for this application. +When using Ingress, it will be set to the Ingress hostname. +*/}} +{{- define "jenkins.host" -}} +{{- if .Values.ingress.enabled }} +{{- .Values.ingress.hostname | default "" -}} +{{- else -}} +{{- .Values.jenkinsHost | default "" -}} +{{- end -}} +{{- end -}} + +{{/* +Gets the host to be used for this application. +When using Ingress, it will be set to the Ingress hostname. +*/}} +{{- define "jenkins.configAsCodeCM" -}} +{{- if .Values.configAsCode.existingConfigmap -}} +{{- .Values.configAsCode.existingConfigmap -}} +{{- else -}} +{{- printf "%s-casc" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return the Jenkins TLS secret name +*/}} +{{- define "jenkins.tlsSecretName" -}} +{{- $secretName := .Values.tls.existingSecret -}} +{{- if $secretName -}} + {{- printf "%s" (tpl $secretName $) -}} +{{- else -}} + {{- printf "%s-crt" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return the Jenkins JKS password secret name +*/}} +{{- define "jenkins.tlsPasswordsSecret" -}} +{{- $secretName := .Values.tls.passwordsSecret -}} +{{- if $secretName -}} + {{- printf "%s" (tpl $secretName $) -}} +{{- else -}} + {{- printf "%s-tls-pass" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* + We need to adapt the basic Kubernetes resource object to Jenkins agent configuration +*/}} +{{- define "jenkins.agent.resources" -}} +{{ $resources := (dict "limits" (dict) "requests" (dict)) }} +{{- if .Values.agent.resources -}} + {{ $resources = .Values.agent.resources -}} +{{- else if ne .Values.agent.resourcesPreset "none" -}} + {{ $resources = include "common.resources.preset" (dict "type" .Values.agent.resourcesPreset) | fromYaml -}} +{{- end -}} +{{- if $resources.limits }} +{{- if $resources.limits.cpu }} +resourceLimitCpu: {{ $resources.limits.cpu }} +{{- end }} +{{- if $resources.limits.memory }} +resourceLimitMemory: {{ $resources.limits.memory }} +{{- end }} +{{- end }} +{{- if $resources.requests }} +{{- if $resources.requests.cpu }} +resourceRequestCpu: {{ $resources.requests.cpu }} +{{- end }} +{{- if $resources.requests.memory }} +resourceRequestMemory: {{ $resources.requests.memory }} +{{- end }} +{{- end -}} +{{- end -}} + +{{/* +Check if there are rolling tags in the images +*/}} +{{- define "jenkins.checkRollingTags" -}} +{{- include "common.warnings.rollingTag" .Values.image }} +{{- end -}} + +{{/* +Get the initialization scripts ConfigMap name. +*/}} +{{- define "jenkins.initScriptsName" -}} +{{- if .Values.initScriptsCM -}} + {{- printf "%s" (tpl .Values.initScriptsCM $) -}} +{{- else -}} + {{- printf "%s-init-scripts" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} + +{{/* +Get the initialization hook scripts ConfigMap name. +*/}} +{{- define "jenkins.initHookScriptsName" -}} +{{- if .Values.initHookScriptsCM -}} + {{- printf "%s" (tpl .Values.initHookScriptsCM $) -}} +{{- else -}} + {{- printf "%s-init-hook-scripts" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/jenkins/templates/agent-listener-svc.yaml b/backing-services/jenkins/templates/agent-listener-svc.yaml new file mode 100644 index 0000000..ef3d42f --- /dev/null +++ b/backing-services/jenkins/templates/agent-listener-svc.yaml @@ -0,0 +1,53 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.agent.enabled .Values.agentListenerService.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-agent-listener" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.agentListenerService.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.agentListenerService.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.agentListenerService.type }} + {{- if and .Values.agentListenerService.clusterIP (eq .Values.agentListenerService.type "ClusterIP") }} + clusterIP: {{ .Values.agentListenerService.clusterIP }} + {{- end }} + {{- if or (eq .Values.agentListenerService.type "LoadBalancer") (eq .Values.agentListenerService.type "NodePort") }} + externalTrafficPolicy: {{ .Values.agentListenerService.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.agentListenerService.type "LoadBalancer") .Values.agentListenerService.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{- toYaml .Values.agentListenerService.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + {{- if (and (eq .Values.agentListenerService.type "LoadBalancer") (not (empty .Values.agentListenerService.loadBalancerIP))) }} + loadBalancerIP: {{ .Values.agentListenerService.loadBalancerIP }} + {{- end }} + {{- if .Values.agentListenerService.sessionAffinity }} + sessionAffinity: {{ .Values.agentListenerService.sessionAffinity }} + {{- end }} + {{- if .Values.agentListenerService.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.agentListenerService.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + ports: + - name: agent-listener + port: {{ .Values.agentListenerService.ports.agentListener }} + protocol: TCP + targetPort: agent-listener + {{- if (and (or (eq .Values.agentListenerService.type "NodePort") (eq .Values.agentListenerService.type "LoadBalancer")) (not (empty .Values.agentListenerService.nodePorts.agentListener))) }} + nodePort: {{ .Values.agentListenerService.nodePorts.agentListener }} + {{- else if eq .Values.agentListenerService.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.agentListenerService.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.agentListenerService.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: jenkins-controller +{{- end }} diff --git a/backing-services/jenkins/templates/casc-cm.yaml b/backing-services/jenkins/templates/casc-cm.yaml new file mode 100644 index 0000000..7fde940 --- /dev/null +++ b/backing-services/jenkins/templates/casc-cm.yaml @@ -0,0 +1,113 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.configAsCode.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-casc" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + config-as-code-default.yaml: |- + jenkins: + {{- if .Values.configAsCode.authorizationStrategy }} + authorizationStrategy: {{ include "common.tplvalues.render" ( dict "value" .Values.configAsCode.authorizationStrategy "context" $ ) | nindent 8 }} + {{- end }} + {{- if .Values.configAsCode.securityRealm }} + securityRealm: {{ include "common.tplvalues.render" ( dict "value" .Values.configAsCode.securityRealm "context" $ ) | nindent 8 }} + {{- end }} + {{- if .Values.agent.enabled }} + slaveAgentPort: {{ .Values.agentListenerService.ports.agentListener | int }} + clouds: + - kubernetes: + name: "kubernetes" + namespace: "{{ template "common.names.namespace" . }}" + serverUrl: "https://kubernetes.default" + jenkinsUrl: {{ printf "http://%s.%s.svc.%s:%d" (include "common.names.fullname" .) (include "common.names.namespace" .) .Values.clusterDomain (.Values.service.ports.http | int) }} + jenkinsTunnel: {{ printf "%s-agent-listener.%s.svc.%s:%d" (include "common.names.fullname" .) (include "common.names.namespace" .) .Values.clusterDomain (.Values.agentListenerService.ports.agentListener | int) }} + podLabels: + - key: "app.kubernetes.io/component" + value: "jenkins-agent" + {{- $podLabels := (include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | fromYaml) }} + {{- if .Values.agent.podLabels }} + {{- $podLabels = merge $podLabels .Values.agent.podLabels }} + {{- end }} + {{- range $key, $val := $podLabels }} + - key: {{ $key | quote }} + value: {{ $val | quote }} + {{- end }} + templates: + - name: {{ printf "%s-agent" (include "common.names.fullname" .) }} + label: {{ .Values.agent.templateLabel | quote }} + namespace: {{ template "common.names.namespace" . }} + id: "agent-template" + {{- if or .Values.agent.annotations }} + annotations: + {{- range $key, $value := .Values.commonAnnotations }} + - key: {{ $key }} + value: {{ $value | quote }} + {{- end }} + {{- range $key, $value := .Values.agent.annotations }} + - key: {{ $key }} + value: {{ $value | quote }} + {{- end }} + {{- end }} + containers: + - name: jnlp + alwaysPullImage: {{ ternary "true" "false" (eq .Values.image.pullPolicy "Always") }} + {{- if .Values.agent.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.agent.command "context" $) | nindent 20 }} + {{- end }} + {{- if .Values.agent.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.agent.args "context" $) | nindent 20 }} + {{- end }} + {{- if .Values.agent.containerExtraEnvVars }} + envVars: {{- include "common.tplvalues.render" (dict "value" .Values.agent.containerExtraEnvVars "context" $) | nindent 22 }} + {{- end }} + image: {{ include "jenkins.agent.image" . }} + {{- if or .Values.agent.resources (ne .Values.agent.resourcesPreset "none") }} + {{- include "jenkins.agent.resources" . | nindent 16 }} + {{- end }} + {{- if .Values.agent.containerSecurityContext.enabled }} + privileged: {{ .Values.agent.containerSecurityContext.privileged }} + {{- if not (or (eq .Values.global.compatibility.openshift.adaptSecurityContext "force") (and (eq .Values.global.compatibility.openshift.adaptSecurityContext "auto") (include "common.compatibility.isOpenshift" .))) }} + runAsUser: {{ .Values.agent.containerSecurityContext.runAsUser }} + runAsGroup: {{ .Values.agent.containerSecurityContext.runAsGroup }} + {{- end }} + {{- end }} + {{- if .Values.agent.sidecars }} + {{- include "common.tplvalues.render" ( dict "value" .Values.agent.sidecars "context" $) | nindent 18 }} + {{- end }} + {{- if .Values.agent.podExtraEnvVars }} + envVars: {{- include "common.tplvalues.render" (dict "value" .Values.agent.podExtraEnvVars "context" $) | nindent 18 }} + {{- end }} + {{- include "jenkins.imagePullSecrets" . | nindent 16 }} + {{- if .Values.agent.extraAgentTemplate }} + {{- include "common.tplvalues.render" ( dict "value" .Values.agent.extraAgentTemplate "context" $) | nindent 16 }} + {{- end }} + {{- if .Values.agent.extraTemplates }} + {{- include "common.tplvalues.render" ( dict "value" .Values.agent.extraTemplates "context" $ ) | nindent 14 }} + {{- end }} + {{- if .Values.configAsCode.extraKubernetes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.configAsCode.extraKubernetes "context" $ ) | nindent 12 }} + {{- end }} + {{- if .Values.configAsCode.extraClouds }} + {{- include "common.tplvalues.render" ( dict "value" .Values.configAsCode.extraClouds "context" $ ) | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.configAsCode.extraJenkins }} + {{- include "common.tplvalues.render" ( dict "value" .Values.configAsCode.extraJenkins "context" $ ) | nindent 6 }} + {{- end }} + {{- if .Values.configAsCode.security }} + security: {{ include "common.tplvalues.render" ( dict "value" .Values.configAsCode.security "context" $ ) | nindent 6 }} + {{- end }} + {{- if .Values.configAsCode.extraConfig }} + {{- include "common.tplvalues.render" ( dict "value" .Values.configAsCode.extraConfig "context" $ ) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/jenkins/templates/controller-svc.yaml b/backing-services/jenkins/templates/controller-svc.yaml new file mode 100644 index 0000000..b30b5ae --- /dev/null +++ b/backing-services/jenkins/templates/controller-svc.yaml @@ -0,0 +1,60 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + {{- if and .Values.service.clusterIP (eq .Values.service.type "ClusterIP") }} + clusterIP: {{ .Values.service.clusterIP }} + {{- end }} + {{- if or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{- toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + {{- if (and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerIP))) }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + {{- if .Values.service.sessionAffinity }} + sessionAffinity: {{ .Values.service.sessionAffinity }} + {{- end }} + {{- if .Values.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + ports: + - name: http + port: {{ .Values.service.ports.http }} + protocol: TCP + targetPort: http + {{- if (and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.http))) }} + nodePort: {{ .Values.service.nodePorts.http }} + {{- else if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- end }} + - name: https + port: {{ .Values.service.ports.https }} + protocol: TCP + targetPort: https + {{- if (and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.https))) }} + nodePort: {{ .Values.service.nodePorts.https }} + {{- else if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: jenkins-controller diff --git a/backing-services/jenkins/templates/deployment.yaml b/backing-services/jenkins/templates/deployment.yaml new file mode 100644 index 0000000..f1b76e3 --- /dev/null +++ b/backing-services/jenkins/templates/deployment.yaml @@ -0,0 +1,563 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} +kind: Deployment +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + replicas: {{ .Values.replicaCount }} + strategy: {{- include "common.tplvalues.render" (dict "value" .Values.updateStrategy "context" $ ) | nindent 4 }} + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: jenkins-controller + annotations: + checksum/secrets: {{ include (print $.Template.BasePath "/secrets.yaml") . | sha256sum }} + {{- if .Values.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.podAnnotations "context" $) | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "jenkins.serviceAccountName" . }} + {{- include "jenkins.imagePullSecrets" . | nindent 6 }} + automountServiceAccountToken: {{ .Values.automountServiceAccountToken }} + {{- if .Values.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAffinityPreset "component" "jenkins-controller" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAntiAffinityPreset "component" "jenkins-controller" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.nodeAffinityPreset.type "key" .Values.nodeAffinityPreset.key "values" .Values.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.schedulerName }} + schedulerName: {{ .Values.schedulerName }} + {{- end }} + {{- if .Values.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName | quote }} + {{- end }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + {{- if or (and .Values.volumePermissions.enabled .Values.persistence.enabled) (or .Values.tls.autoGenerated .Values.tls.existingSecret) .Values.initContainers }} + initContainers: + - name: copy-plugins + image: {{ include "jenkins.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + command: + - /bin/bash + - -ec + - |- + #!/bin/bash + + . /opt/bitnami/scripts/libfs.sh + + if ! is_dir_empty /opt/bitnami/jenkins/plugins; then + cp -r /opt/bitnami/jenkins/plugins/* /plugins + fi + {{- if .Values.resources }} + resources: {{- toYaml .Values.resources | nindent 12 }} + {{- else if ne .Values.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.resourcesPreset) | nindent 12 }} + {{- end }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /opt/bitnami/jenkins/certs + subPath: app-certs-dir + - name: empty-dir + mountPath: /plugins + subPath: app-plugins-dir + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if or .Values.tls.autoGenerated .Values.tls.existingSecret }} + - name: init-certs + image: {{ include "jenkins.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + command: + - /bin/bash + - -ec + - |- + if [[ -f /opt/bitnami/jenkins/certs/jenkins.jks ]]; then + rm /opt/bitnami/jenkins/certs/jenkins.jks + fi + {{- if or .Values.tls.autoGenerated .Values.tls.usePemCerts }} + if [[ -f "/certs/tls.key" ]] && [[ -f "/certs/tls.crt" ]]; then + openssl pkcs12 -export -in "/certs/tls.crt" \ + -passout pass:"${JENKINS_KEYSTORE_PASSWORD}" \ + -inkey "/certs/tls.key" \ + -out "/tmp/keystore.p12" + keytool -importkeystore -srckeystore "/tmp/keystore.p12" \ + -srcstoretype PKCS12 \ + -srcstorepass "${JENKINS_KEYSTORE_PASSWORD}" \ + -deststorepass "${JENKINS_KEYSTORE_PASSWORD}" \ + -destkeystore "/opt/bitnami/jenkins/certs/jenkins.jks" + rm "/tmp/keystore.p12" + else + echo "Couldn't find the expected PEM certificates! They are mandatory when encryption via TLS is enabled." + exit 1 + fi + {{- else }} + if [[ -f "/certs/jenkins.jks" ]]; then + cp "/certs/jenkins.jks" "/opt/bitnami/jenkins/certs/jenkins.jks" + else + echo "Couldn't find the expected Java Key Stores (JKS) files! They are mandatory when encryption via TLS is enabled." + exit 1 + fi + {{- end }} + env: + {{- if or .Values.tls.passwordsSecret .Values.tls.password .Values.tls.autoGenerated .Values.tls.usePemCerts }} + - name: JENKINS_KEYSTORE_PASSWORD + valueFrom: + secretKeyRef: + name: {{ (include "jenkins.tlsPasswordsSecret" .) }} + key: keystore-password + {{- end }} + {{- if .Values.tls.resources }} + resources: {{- toYaml .Values.tls.resources | nindent 12 }} + {{- else if ne .Values.tls.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.tls.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: certs + mountPath: /certs + - name: empty-dir + mountPath: /opt/bitnami/jenkins/certs + subPath: app-certs-dir + {{- end }} + {{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }} + - name: volume-permissions + image: {{ include "jenkins.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + args: + - -ec + - | + mkdir -p /bitnami/jenkins + chown -R "{{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }}" /bitnami/jenkins + {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.securityContext "runAsUser" | toYaml | nindent 12 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.securityContext | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- else if ne .Values.volumePermissions.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.volumePermissions.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: jenkins-data + mountPath: /bitnami/jenkins + {{- end }} + {{- if .Values.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- end }} + containers: + - name: jenkins + image: {{ include "jenkins.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.args "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" .Values.image.debug | quote }} + - name: JENKINS_USERNAME + value: {{ .Values.jenkinsUser | quote }} + - name: JENKINS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "common.names.fullname" . }} + key: jenkins-password + - name: JENKINS_HOME + value: {{ .Values.jenkinsHome | quote }} + - name: JENKINS_SKIP_BOOTSTRAP + value: {{ .Values.disableInitialization | quote }} + - name: JENKINS_HOST + value: {{ include "jenkins.host" . | quote }} + - name: JENKINS_EXTERNAL_HTTP_PORT_NUMBER + value: {{ .Values.service.ports.http | quote }} + - name: JENKINS_EXTERNAL_HTTPS_PORT_NUMBER + value: {{ .Values.service.ports.https | quote }} + {{- if or .Values.tls.autoGenerated .Values.tls.existingSecret }} + - name: JENKINS_CERTS_DIR + value: "/opt/bitnami/jenkins/certs" + {{- end }} + {{- if or .Values.tls.passwordsSecret .Values.tls.password .Values.tls.autoGenerated .Values.tls.usePemCerts }} + - name: JENKINS_KEYSTORE_PASSWORD + valueFrom: + secretKeyRef: + name: {{ (include "jenkins.tlsPasswordsSecret" .) }} + key: keystore-password + {{- end }} + {{- $plugins := .Values.plugins }} + {{- if .Values.extraPlugins }} + {{- $plugins = append $plugins .Values.extraPlugins }} + {{- end }} + {{- if $plugins }} + - name: JENKINS_PLUGINS + value: {{ join ";" $plugins | quote }} + {{- end }} + {{- $paths := .Values.overridePaths | default "" }} + {{- if or .Values.initHookScripts .Values.initHookScriptsCM .Values.initHookScriptsSecret }} + {{- if $paths }} + {{- $paths = printf "%s,init.groovy.d" $paths }} + {{- else }} + {{- $paths = "init.groovy.d" }} + {{- end }} + {{- end }} + {{- if $paths }} + - name: JENKINS_OVERRIDE_PATHS + value: {{ join ";" $paths | quote }} + {{- end }} + - name: JENKINS_PLUGINS_LATEST + value: {{ ternary "true" "false" .Values.latestPlugins | quote }} + - name: JENKINS_PLUGINS_LATEST_SPECIFIED + value: {{ ternary "true" "false" .Values.latestSpecifiedPlugins | quote }} + - name: JENKINS_SKIP_IMAGE_PLUGINS + value: {{ ternary "true" "false" .Values.skipImagePlugins | quote }} + - name: JENKINS_OVERRIDE_PLUGINS + value: {{ ternary "true" "false" .Values.overridePlugins | quote }} + {{- if .Values.configAsCode.enabled }} + - name: CASC_JENKINS_CONFIG + value: "$(JENKINS_HOME)/casc_configs" + {{- if and .Values.configAsCode.enabled .Values.configAsCode.autoReload.enabled }} + - name: CASC_RELOAD_TOKEN + value: "$(POD_NAME)" + {{- end }} + {{- end }} + {{- if .Values.javaOpts }} + - name: JAVA_OPTS + value: {{ .Values.javaOpts | join " " | quote }} + {{- end }} + {{- if .Values.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.extraEnvVarsCM .Values.extraEnvVarsSecret }} + envFrom: + {{- if .Values.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.extraEnvVarsSecret "context" $) }} + {{- end }} + {{- end }} + ports: + - name: http + containerPort: {{ .Values.containerPorts.http }} + protocol: TCP + - name: https + containerPort: {{ .Values.containerPorts.https }} + protocol: TCP + {{- if .Values.agent.enabled }} + - name: agent-listener + containerPort: {{ .Values.containerPorts.agentListener }} + protocol: TCP + {{- end }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: http + {{- end }} + {{- if .Values.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.livenessProbe.enabled }} + livenessProbe: + tcpSocket: + port: http + initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.livenessProbe.failureThreshold }} + successThreshold: {{ .Values.livenessProbe.successThreshold }} + {{- end }} + {{- if .Values.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: /login + port: http + initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + successThreshold: {{ .Values.readinessProbe.successThreshold }} + {{- end }} + {{- end }} + {{- if .Values.resources }} + resources: {{- toYaml .Values.resources | nindent 12 }} + {{- else if ne .Values.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/jenkins/plugins + subPath: app-plugins-dir + - name: empty-dir + mountPath: /opt/bitnami/jenkins/tmp + subPath: app-tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/jenkins/logs + subPath: app-logs-dir + - name: jenkins-data + mountPath: /bitnami/jenkins + {{- if or .Values.tls.autoGenerated .Values.tls.existingSecret }} + - name: empty-dir + mountPath: /opt/bitnami/jenkins/certs + subPath: app-certs-dir + {{- end }} + {{- if .Values.configAsCode.enabled }} + - name: config-as-code-mountpoint + mountPath: /usr/share/jenkins/ref/casc_configs + {{- end }} + {{- if or .Values.initScripts .Values.initScriptsCM .Values.initScriptsSecret }} + - name: custom-init-scripts + mountPath: /docker-entrypoint-initdb.d/ + {{- end }} + {{- if or .Values.initHookScripts .Values.initHookScriptsCM .Values.initHookScriptsSecret }} + - name: jenkins-init-hook-scripts + mountPath: /usr/share/jenkins/ref/init.groovy.d/ + {{- end }} + {{- if .Values.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if and .Values.configAsCode.enabled .Values.configAsCode.autoReload.enabled }} + - name: reload-configuration-as-code + image: {{ include "jenkins.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.configAsCode.autoReload.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.configAsCode.autoReload.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.configAsCode.autoReload.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + {{- end }} + {{- if .Values.configAsCode.autoReload.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.configAsCode.autoReload.args "context" $) | nindent 12 }} + {{- else }} + args: + - -ec + - | + set -o errexit + set -o nounset + set -o pipefail + + . /opt/bitnami/scripts/libjenkins.sh + + get_configmap() { + local -r print_output=${1:-false} + + local -r apiserver="https://kubernetes.default.svc" + local -r sa_dir="/var/run/secrets/kubernetes.io/serviceaccount" + local -r token=$(cat "${sa_dir}/token") + local -r ca_cert="${sa_dir}/ca.crt" + local -r url="${apiserver}/api/v1/namespaces/${NAMESPACE}/configmaps/${CONFIGMAP_NAME}" + + local command=("curl" "-s" --cacert "${ca_cert}" "-H" "Authorization: Bearer ${token}" "-H" "Accept: application/json" "${url}") + + if ! is_boolean_yes "$print_output"; then + command+=("--fail" "-o" "/old_copy/cm.json") + fi + "${command[@]}" + } + + trigger_config_reload() { + local -r jenkins_host="http://localhost:{{ .Values.containerPorts.http }}" + local -r url="${jenkins_host}/reload-configuration-as-code/?casc-reload-token=$(POD_NAME)" + local command=("curl" "-s" "--fail" "-X" "POST" "${url}") + + "${command[@]}" + } + + # Variables + k8s_api_retries=12 + k8s_api_sleep=5 + jenkins_casc_reload_retries={{ .Values.configAsCode.autoReload.reqRetries | int }} + jenkins_casc_reload_sleep={{ .Values.configAsCode.autoReload.interval | int }} + + sleep {{ .Values.configAsCode.autoReload.initialDelay | int | quote }} + + while true; do + # Download configmap content + if ! retry_while 'get_configmap' "$k8s_api_retries" "$k8s_api_sleep"; then + error "Failed to obtain the ConfigMap. Please check the following error message:\n $(get_configmap "true")" + exit 1 + else + if [[ -d "/bitnami/jenkins/home/casc_configs" ]]; then + # Remove existing config-as-code files + rm -rf /bitnami/jenkins/home/casc_configs + fi + # Create target directories + mkdir -p /bitnami/jenkins/home/casc_configs /old_copy/casc_configs + # Copy files defined in the ConfigMap + for file in $(jq -rc '.data | keys[]' "/old_copy/cm.json"); do + jq -r ".data.\"${file}\"" "/old_copy/cm.json" > "/bitnami/jenkins/home/casc_configs/${file}" + done + # Remove configmap json file + rm /old_copy/cm.json + # Compare running configuration and new configuration + if [[ -d /old_copy/casc_configs && -d /bitnami/jenkins/home/casc_configs ]] && ! diff -q /old_copy/casc_configs /bitnami/jenkins/home/casc_configs; then + if ! retry_while "trigger_config_reload" "$jenkins_casc_reload_retries" "$jenkins_casc_reload_sleep"; then + error "Failed to trigger config reload." + else + info "Configuration successfully applied" + # Copy running configuration to compare in the next iteration + cp -rf /bitnami/jenkins/home/casc_configs /old_copy/ + fi + fi + fi + sleep {{ default "60" .Values.configAsCode.autoReload.interval }} + done + {{- end }} + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: CONFIGMAP_NAME + value: {{ template "jenkins.configAsCodeCM" . }} + - name: NAMESPACE + value: {{ include "common.names.namespace" . | quote }} + {{- if .Values.configAsCode.autoReload.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.configAsCode.autoReload.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.configAsCode.autoReload.resources }} + resources: {{- toYaml .Values.configAsCode.autoReload.resources | nindent 12 }} + {{- else if ne .Values.configAsCode.autoReload.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.configAsCode.autoReload.resourcesPreset) | nindent 12 }} + {{- end }} + {{- if or .Values.configAsCode.autoReload.extraEnvVarsCM .Values.configAsCode.autoReload.extraEnvVarsSecret }} + envFrom: + {{- if .Values.configAsCode.autoReload.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.configAsCode.autoReload.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.configAsCode.autoReload.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.configAsCode.autoReload.extraEnvVarsSecret "context" $) }} + {{- end }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: jenkins-data + mountPath: /bitnami/jenkins + - name: empty-dir + mountPath: /old_copy + subPath: app-casc-tmp-dir + {{- if .Values.configAsCode.autoReload.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.configAsCode.autoReload.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- end}} + {{- if .Values.sidecars }} + {{- include "common.tplvalues.render" ( dict "value" .Values.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: empty-dir + emptyDir: {} + - name: jenkins-data + {{- if .Values.persistence.enabled }} + persistentVolumeClaim: + claimName: {{ default (include "common.names.fullname" .) (tpl .Values.persistence.existingClaim $) }} + {{- else }} + emptyDir: {} + {{- end }} + {{- if or .Values.tls.autoGenerated .Values.tls.existingSecret }} + - name: certs + secret: + secretName: {{ include "jenkins.tlsSecretName" . }} + {{- end }} + {{- if .Values.configAsCode.enabled }} + - name: config-as-code-mountpoint + configMap: + name: {{ template "jenkins.configAsCodeCM" . }} + {{- end }} + {{- if or .Values.initScripts .Values.initScriptsCM .Values.initScriptsSecret }} + - name: custom-init-scripts + projected: + sources: + {{- if or .Values.initScripts .Values.initScriptsCM }} + - configMap: + name: {{ template "jenkins.initScriptsName" . }} + {{- end }} + {{- if .Values.initScriptsSecret }} + - secret: + secretName: {{ print (tpl .Values.initScriptsSecret .) }} + defaultMode: 0755 + {{- end }} + {{- end }} + {{- if or .Values.initHookScripts .Values.initHookScriptsCM .Values.initHookScriptsSecret }} + - name: jenkins-init-hook-scripts + projected: + sources: + {{- if or .Values.initHookScripts .Values.initHookScriptsCM }} + - configMap: + name: {{ template "jenkins.initHookScriptsName" . }} + {{- end }} + {{- if .Values.initHookScriptsSecret }} + - secret: + secretName: {{ print (tpl .Values.initHookScriptsSecret .) }} + defaultMode: 0755 + {{- end }} + {{- end }} + {{- if .Values.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraVolumes "context" $) | nindent 8 }} + {{- end }} diff --git a/backing-services/jenkins/templates/extra-list.yaml b/backing-services/jenkins/templates/extra-list.yaml new file mode 100644 index 0000000..329f5c6 --- /dev/null +++ b/backing-services/jenkins/templates/extra-list.yaml @@ -0,0 +1,9 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/backing-services/jenkins/templates/ingress.yaml b/backing-services/jenkins/templates/ingress.yaml new file mode 100644 index 0000000..063a722 --- /dev/null +++ b/backing-services/jenkins/templates/ingress.yaml @@ -0,0 +1,59 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.ingress.enabled }} +apiVersion: {{ include "common.capabilities.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.ingress.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.ingress.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.ingressClassName (eq "true" (include "common.ingress.supportsIngressClassname" .)) }} + ingressClassName: {{ .Values.ingress.ingressClassName | quote }} + {{- end }} + rules: + {{- if .Values.ingress.hostname }} + - host: {{ .Values.ingress.hostname }} + http: + paths: + {{- if .Values.ingress.extraPaths }} + {{- toYaml .Values.ingress.extraPaths | nindent 10 }} + {{- end }} + - path: {{ .Values.ingress.path }} + {{- if eq "true" (include "common.ingress.supportsPathType" .) }} + pathType: {{ .Values.ingress.pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" .) "servicePort" "http" "context" $) | nindent 14 }} + {{- end }} + {{- range .Values.ingress.extraHosts }} + - host: {{ .name | quote }} + http: + paths: + - path: {{ default "/" .path }} + {{- if eq "true" (include "common.ingress.supportsPathType" $) }} + pathType: {{ default "ImplementationSpecific" .pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" $) "servicePort" "http" "context" $) | nindent 14 }} + {{- end }} + {{- if .Values.ingress.extraRules }} + {{- include "common.tplvalues.render" (dict "value" .Values.ingress.extraRules "context" $) | nindent 4 }} + {{- end }} + {{- if or .Values.ingress.tls .Values.ingress.extraTls }} + tls: + {{- if .Values.ingress.tls }} + - hosts: + - {{ .Values.ingress.hostname | quote }} + secretName: {{ printf "%s-tls" .Values.ingress.hostname }} + {{- end }} + {{- if .Values.ingress.extraTls }} + {{- include "common.tplvalues.render" (dict "value" .Values.ingress.extraTls "context" $) | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/jenkins/templates/init-hook-scripts-configmap.yaml b/backing-services/jenkins/templates/init-hook-scripts-configmap.yaml new file mode 100644 index 0000000..ecbe4f2 --- /dev/null +++ b/backing-services/jenkins/templates/init-hook-scripts-configmap.yaml @@ -0,0 +1,21 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.initHookScripts }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-init-hook-scripts" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + {{- range $filename, $content := .Values.initHookScripts }} + {{ $filename }}: | + {{- include "common.tplvalues.render" (dict "value" $content "context" $) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/jenkins/templates/init-script-configmap.yaml b/backing-services/jenkins/templates/init-script-configmap.yaml new file mode 100644 index 0000000..aae96a7 --- /dev/null +++ b/backing-services/jenkins/templates/init-script-configmap.yaml @@ -0,0 +1,21 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.initScripts }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-init-scripts" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + {{- range $filename, $content := .Values.initScripts }} + {{ $filename }}: | + {{- include "common.tplvalues.render" (dict "value" $content "context" $) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/jenkins/templates/networkpolicy.yaml b/backing-services/jenkins/templates/networkpolicy.yaml new file mode 100644 index 0000000..e132908 --- /dev/null +++ b/backing-services/jenkins/templates/networkpolicy.yaml @@ -0,0 +1,85 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ include "common.capabilities.networkPolicy.apiVersion" . }} +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: jenkins-controller + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: jenkins-controller + policyTypes: + - Ingress + - Egress + {{- if .Values.networkPolicy.allowExternalEgress }} + egress: + - {} + {{- else }} + egress: + - ports: + # Allow dns resolution + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + # Allow http and https for plugin download + - port: 80 + - port: 443 + {{- range $port := .Values.networkPolicy.kubeAPIServerPorts }} + - port: {{ $port }} + {{- end }} + - ports: + # Allow traffic to Kubernetes agents + - port: {{ .Values.agentListenerService.ports.agentListener }} + to: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }} + app.kubernetes.io/component: jenkins-agent + {{- if .Values.networkPolicy.extraEgress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.networkPolicy.extraEgress "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} + ingress: + - ports: + - port: {{ .Values.containerPorts.http }} + - port: {{ .Values.containerPorts.https }} + {{- if .Values.agent.enabled }} + - port: {{ .Values.containerPorts.agentListener }} + {{- end }} + {{- if not .Values.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }} + - podSelector: + matchLabels: + {{ template "common.names.fullname" . }}-client: "true" + {{- if .Values.networkPolicy.ingressNSMatchLabels }} + - namespaceSelector: + matchLabels: + {{- range $key, $value := .Values.networkPolicy.ingressNSMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{- if .Values.networkPolicy.ingressNSPodMatchLabels }} + podSelector: + matchLabels: + {{- range $key, $value := .Values.networkPolicy.ingressNSPodMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.networkPolicy.extraIngress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.networkPolicy.extraIngress "context" $ ) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/jenkins/templates/pdb.yaml b/backing-services/jenkins/templates/pdb.yaml new file mode 100644 index 0000000..b17ff44 --- /dev/null +++ b/backing-services/jenkins/templates/pdb.yaml @@ -0,0 +1,26 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.pdb.minAvailable }} + minAvailable: {{ .Values.pdb.minAvailable }} + {{- end }} + {{- if or .Values.pdb.maxUnavailable ( not .Values.pdb.minAvailable ) }} + maxUnavailable: {{ .Values.pdb.maxUnavailable | default 1 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} +{{- end }} diff --git a/backing-services/jenkins/templates/pvc.yaml b/backing-services/jenkins/templates/pvc.yaml new file mode 100644 index 0000000..578f7c0 --- /dev/null +++ b/backing-services/jenkins/templates/pvc.yaml @@ -0,0 +1,31 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + annotations: + volume.alpha.kubernetes.io/storage-class: {{ ternary "default" (trimPrefix "storageClassName: " (include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global))) (empty (include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global))) }} + {{- if or .Values.persistence.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.persistence.annotations .Values.commonAnnotations ) "context" . ) }} + {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- if .Values.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.selector "context" $) | nindent 4 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) | nindent 2 }} +{{- end }} diff --git a/backing-services/jenkins/templates/role.yaml b/backing-services/jenkins/templates/role.yaml new file mode 100644 index 0000000..8af2fb9 --- /dev/null +++ b/backing-services/jenkins/templates/role.yaml @@ -0,0 +1,56 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.rbac.create (or .Values.agent.enabled .Values.configAsCode.enabled .Values.rbac.rules) }} +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: Role +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }} + {{- end }} +rules: + {{- if .Values.agent.enabled }} + - apiGroups: + - "" + resources: + - "pods" + - "pods/exec" + - "pods/log" + - "persistentvolumeclaims" + - "events" + verbs: + - "get" + - "list" + - "watch" + - apiGroups: + - "" + resources: + - "pods" + - "pods/exec" + - "persistentvolumeclaims" + verbs: + - "create" + - "delete" + - "deletecollection" + - "patch" + - "update" + {{- end }} + {{- if .Values.configAsCode.enabled }} + - apiGroups: + - "" + resources: + - "configmaps" + verbs: + - "get" + - "watch" + - "list" + {{- end }} + {{- if .Values.rbac.rules }} + {{- include "common.tplvalues.render" ( dict "value" .Values.rbac.rules "context" $ ) | nindent 2 }} + {{- end }} +{{- end }} diff --git a/backing-services/jenkins/templates/rolebinding.yaml b/backing-services/jenkins/templates/rolebinding.yaml new file mode 100644 index 0000000..a851fab --- /dev/null +++ b/backing-services/jenkins/templates/rolebinding.yaml @@ -0,0 +1,24 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.rbac.create }} +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: RoleBinding +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "common.names.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ include "jenkins.serviceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} +{{- end }} diff --git a/backing-services/jenkins/templates/secrets.yaml b/backing-services/jenkins/templates/secrets.yaml new file mode 100644 index 0000000..7e9d1e0 --- /dev/null +++ b/backing-services/jenkins/templates/secrets.yaml @@ -0,0 +1,35 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + jenkins-password: {{ include "common.secrets.passwords.manage" (dict "secret" ( include "common.names.fullname" .) "key" "jenkins-password" "providedValues" (list "jenkinsPassword") "context" $) }} +{{- if and (or .Values.tls.autoGenerated .Values.tls.existingSecret) (not .Values.tls.passwordsSecret) }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ printf "%s-tls-pass" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + {{- if .Values.tls.existingSecret }} + {{- $pass := required "Is 'tls.existingSecret' is provided, providing a JKS password is mandatory" .Values.tls.password }} + {{- end }} + keystore-password: {{ include "common.secrets.passwords.manage" (dict "secret" ( printf "%s-tls-pass" (include "common.names.fullname" .)) "key" "keystore-password" "providedValues" (list "tls.password") "context" $) }} +{{- end }} diff --git a/backing-services/jenkins/templates/serviceaccount.yaml b/backing-services/jenkins/templates/serviceaccount.yaml new file mode 100644 index 0000000..93c6744 --- /dev/null +++ b/backing-services/jenkins/templates/serviceaccount.yaml @@ -0,0 +1,18 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "jenkins.serviceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/backing-services/jenkins/templates/tls-secret.yaml b/backing-services/jenkins/templates/tls-secret.yaml new file mode 100644 index 0000000..fa32449 --- /dev/null +++ b/backing-services/jenkins/templates/tls-secret.yaml @@ -0,0 +1,69 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.ingress.enabled }} +{{- if .Values.ingress.secrets }} +{{- range .Values.ingress.secrets }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .name }} + namespace: {{ include "common.names.namespace" $ | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $.Values.commonLabels "context" $ ) | nindent 4 }} + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ .certificate | b64enc }} + tls.key: {{ .key | b64enc }} +--- +{{- end }} +{{- end }} +{{- if and .Values.ingress.tls .Values.ingress.selfSigned }} +{{- $secretName := printf "%s-tls" .Values.ingress.hostname }} +{{- $ca := genCA "jenkins-ca" 365 }} +{{- $cert := genSignedCert .Values.ingress.hostname nil (list .Values.ingress.hostname) 365 $ca }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.crt" "defaultValue" $cert.Cert "context" $) }} + tls.key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.key" "defaultValue" $cert.Key "context" $) }} + ca.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }} +--- +{{- end }} +{{- end }} +{{- if and .Values.tls.autoGenerated (not .Values.tls.existingSecret) }} +{{- $secretName := printf "%s-crt" (include "common.names.fullname" .) }} +{{- $fullname := include "common.names.fullname" . }} +{{- $releaseNamespace := include "common.names.namespace" . }} +{{- $clusterDomain := .Values.clusterDomain }} +{{- $serviceName := include "common.names.fullname" . }} +{{- $altNames := list (printf "%s.%s.svc.%s" $serviceName $releaseNamespace $clusterDomain) $serviceName $fullname "localhost" "127.0.0.1" }} +{{- $ca := genCA "jenkins-https-ca" 365 }} +{{- $cert := genSignedCert $fullname nil $altNames 365 $ca }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.crt" "defaultValue" $cert.Cert "context" $) }} + tls.key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.key" "defaultValue" $cert.Key "context" $) }} + ca.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }} +{{- end }} diff --git a/backing-services/jenkins/values.schema.json b/backing-services/jenkins/values.schema.json new file mode 100644 index 0000000..ba50426 --- /dev/null +++ b/backing-services/jenkins/values.schema.json @@ -0,0 +1,114 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "serviceAccountName": { + "type": "string", + "title": "ServiceAccount name", + "form": true, + "description": "Defaults to use default if not set" + }, + "jenkinsUser": { + "type": "string", + "title": "Username", + "form": true + }, + "jenkinsPassword": { + "type": "string", + "title": "Password", + "form": true, + "description": "Defaults to a random 10-character alphanumeric string if not set" + }, + "persistence": { + "type": "object", + "title": "Persistence", + "form": true, + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable persistence", + "description": "Enable persistence using Persistent Volume Claims" + }, + "size": { + "type": "string", + "title": "Persistent Volume Size", + "form": true, + "render": "slider", + "sliderMin": 1, + "sliderMax": 100, + "sliderUnit": "Gi", + "hidden": { + "value": false, + "path": "persistence/enabled" + } + } + } + }, + "resources": { + "type": "object", + "title": "Required Resources", + "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" + } + } + } + } + }, + "ingress": { + "type": "object", + "form": true, + "title": "Ingress Configuration", + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Use a custom hostname", + "description": "Enable the ingress resource that allows you to access the Jenkins installation." + }, + "hostname": { + "type": "string", + "form": true, + "title": "Hostname", + "hidden": { + "value": false, + "path": "ingress/enabled" + } + } + } + }, + "service": { + "type": "object", + "form": true, + "title": "Service Configuration", + "properties": { + "type": { + "type": "string", + "form": true, + "title": "Service Type", + "description": "Allowed values: \"ClusterIP\", \"NodePort\" and \"LoadBalancer\"" + } + } + } + } +} diff --git a/backing-services/jenkins/values.yaml b/backing-services/jenkins/values.yaml new file mode 100644 index 0000000..4790b9d --- /dev/null +++ b/backing-services/jenkins/values.yaml @@ -0,0 +1,1113 @@ +# Copyright Broadcom, Inc. All Rights Reserved. +# SPDX-License-Identifier: APACHE-2.0 + +## @section Global parameters +## 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, imagePullSecrets and storageClass + +## @param global.imageRegistry Global Docker image registry +## @param global.imagePullSecrets Global Docker registry secret names as an array +## @param global.defaultStorageClass Global default StorageClass for Persistent Volume(s) +## @param global.storageClass DEPRECATED: use global.defaultStorageClass instead +## +global: + imageRegistry: "" + ## E.g. + ## imagePullSecrets: + ## - myRegistryKeySecretName + ## + imagePullSecrets: [] + defaultStorageClass: "" + storageClass: "" + ## Compatibility adaptations for Kubernetes platforms + ## + compatibility: + ## Compatibility adaptations for Openshift + ## + openshift: + ## @param global.compatibility.openshift.adaptSecurityContext Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) + ## + adaptSecurityContext: auto +## @section Common parameters + +## @param kubeVersion Override Kubernetes version +## +kubeVersion: "" +## @param nameOverride String to partially override common.names.fullname +## +nameOverride: "" +## @param fullnameOverride String to fully override common.names.fullname +## +fullnameOverride: "" +## @param replicaCount Number of container replicas +## +replicaCount: 1 +## @param commonLabels Labels to add to all deployed objects +## +commonLabels: {} +## @param commonAnnotations Annotations to add to all deployed objects +## +commonAnnotations: {} +## @param clusterDomain Kubernetes cluster domain name +## +clusterDomain: cluster.local +## @param extraDeploy Array of extra objects to deploy with the release +## +extraDeploy: [] +## Enable diagnostic mode in the deployment +## +diagnosticMode: + ## @param diagnosticMode.enabled Enable diagnostic mode (all probes will be disabled and the command will be overridden) + ## + enabled: false + ## @param diagnosticMode.command Command to override all containers in the deployment + ## + command: + - sleep + ## @param diagnosticMode.args Args to override all containers in the deployment + ## + args: + - infinity +## @section Jenkins Image parameters + +## Bitnami Jenkins image +## ref: https://hub.docker.com/r/bitnami/jenkins/tags/ +## @param image.registry [default: REGISTRY_NAME] Jenkins image registry +## @param image.repository [default: REPOSITORY_NAME/jenkins] Jenkins image repository +## @skip image.tag Jenkins image tag (immutable tags are recommended) +## @param image.digest Jenkins image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag +## @param image.pullPolicy Jenkins image pull policy +## @param image.pullSecrets Jenkins image pull secrets +## @param image.debug Enable image debug mode +## +image: + registry: docker.io + repository: bitnami/jenkins + tag: 2.479.1-debian-12-r0 + digest: "" + ## Specify a imagePullPolicy + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Enable debug mode + ## + debug: false +## @section Jenkins Configuration parameters +## Jenkins settings based on environment variables +## ref: https://github.com/bitnami/containers/tree/main/bitnami/jenkins#configuration + +## @param jenkinsUser Jenkins username +## +jenkinsUser: user +## @param jenkinsPassword Jenkins user password +## Defaults to a random 10-character alphanumeric string if not set +## +jenkinsPassword: "" +## @param jenkinsHost Jenkins host to create application URLs +## +jenkinsHost: "" +## @param jenkinsHome Jenkins home directory +## +jenkinsHome: /bitnami/jenkins/home +## @param javaOpts Custom JVM parameters +## +javaOpts: [] +## @param disableInitialization Skip performing the initial bootstrapping for Jenkins +## +disableInitialization: "no" +## @param command Override default container command (useful when using custom images) +## +command: [] +## @param args Override default container args (useful when using custom images) +## +args: [] +## @param extraEnvVars Array with extra environment variables to add to the Jenkins container +## e.g: +## extraEnvVars: +## - name: FOO +## value: "bar" +## +extraEnvVars: [] +## @param extraEnvVarsCM Name of existing ConfigMap containing extra env vars +## +extraEnvVarsCM: "" +## @param extraEnvVarsSecret Name of existing Secret containing extra env vars +## +extraEnvVarsSecret: "" +## @param plugins List of plugins to be installed during Jenkins first boot. +## Note: For this value to take effect on already initialized pods, set overridePlugins=true. +## plugins: +## - kubernetes:3852.v41ea_166a_ed1b_ +## - workflow-aggregator:590.v6a_d052e5a_a_b_5 +## - git:4.13.0 +## - configuration-as-code:1569.vb_72405b_80249 +## +plugins: [] +## @param extraPlugins List of plugins to install in addition to those listed in `plugins` +## +extraPlugins: [] +## @param latestPlugins Set to true to download the latest version of all dependencies, even if the version(s) of the requested plugin(s) are not the latest. +## +latestPlugins: true +## @param latestSpecifiedPlugins Set to true download the latest dependencies of any plugin that is requested to have the latest version. +## +latestSpecifiedPlugins: false +## @param skipImagePlugins Set this value to true to skip installing plugins stored under /opt/bitnami/jenkins/plugins +## +skipImagePlugins: false +## @param overridePlugins Setting this value to true will remove all plugins from the jenkinsHome directory and install new plugins from scratch. +## +overridePlugins: false +## @param overridePaths Comma-separated list of relative paths to be removed from Jenkins home volume and/or mounted if present in the mounted content dir +## +overridePaths: "" +## @param initScripts Dictionary of scripts to be mounted at `/docker-entrypoint-initdb.d`. Evaluated as a template. Allows .sh and .groovy formats. +## These scripts will only be executed during the container first startup. +## For example: +## initScripts: +## my_init_script.sh: | +## #!/bin/sh +## echo "Do something." +## +initScripts: {} +## @param initScriptsCM ConfigMap containing the `/docker-entrypoint-initdb.d` scripts. Evaluated as a template. +## +initScriptsCM: "" +## @param initScriptsSecret Secret containing `/docker-entrypoint-initdb.d` scripts to be executed at initialization time that contain sensitive data. Evaluated as a template. +## +initScriptsSecret: "" +## @param initHookScripts Dictionary of scripts to be mounted at `$JENKINS_HOME/init.groovy.d`. Evaluated as a template. Allows .sh and .groovy formats. +## These init scripts will executed each time Jenkins is . +## +## For example: +## initHookScripts: +## my_script.groovy: | +## println "Hello World" +## +initHookScripts: {} +## @param initHookScriptsCM ConfigMap containing the `$JENKINS_HOME/init.groovy.d` scripts. Evaluated as a template. +## +initHookScriptsCM: "" +## @param initHookScriptsSecret Secret containing `$JENKINS_HOME/init.groovy.d` scripts to be executed at initialization time that contain sensitive data. Evaluated as a template. +## +initHookScriptsSecret: "" +## @section Jenkins TLS configuration +## +tls: + ## @param tls.autoGenerated Create self-signed TLS certificates. Currently only supports PEM certificates. + ## + autoGenerated: false + ## @param tls.usePemCerts Use this variable if your secrets contain PEM certificates instead of PKCS12 + ## Note: Ignored when using autoGenerated certs. + ## + usePemCerts: false + ## @param tls.existingSecret Name of the existing secret containing the 'jenkins.jks' keystore, if usePemCerts is enabled, use keys 'tls.crt' and 'tls.key'. + ## + existingSecret: "" + ## @param tls.password Password to access the JKS keystore when it is password-protected. + ## + password: "" + ## @param tls.passwordsSecret Name of the existing secret containing the JKS keystore password. + ## + passwordsSecret: "" + ## Init Container resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## 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:'. + ## @param tls.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if tls.resources is set (tls.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param tls.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} +## @section Jenkins Configuration as Code plugin settings (EXPERIMENTAL) +## The values under this section require that the plugin 'configuration-as-code' is installed. +## All the configuration-as-code values are rendered as a template. +## +configAsCode: + ## @param configAsCode.enabled Enable configuration as code. + ## + enabled: false + ## @param configAsCode.extraConfigFiles List of additional configuration-as-code files to be mounted + ## E.g.: + ## welcome-message.yaml: |- + ## jenkins: + ## systemMessage: Welcome to our CI\CD server. This Jenkins is configured and managed 'as code'. + ## + extraConfigFiles: {} + ## @param configAsCode.securityRealm Content of the 'securityRealm' block + ## + securityRealm: {} + ## @param configAsCode.authorizationStrategy Content of the 'authorizationStrategy' block + ## + authorizationStrategy: {} + ## @param configAsCode.security Content of the 'security' block + ## + security: {} + ## @param configAsCode.extraJenkins Append additional settings under the 'jenkins' block + ## + extraJenkins: {} + ## @param configAsCode.extraConfig Append additional settings at the root of the configuration-as-code file + ## + extraConfig: {} + ## @param configAsCode.extraKubernetes Append additional settings under the Kubernetes cloud block + ## NOTE: This value will only take effect if agent.enabled=true + ## + extraKubernetes: {} + ## @param configAsCode.extraClouds Additional clouds + ## NOTE: This value will only take effect if agent.enabled=true + ## + extraClouds: [] + ## @param configAsCode.existingConfigmap Name of an existing configmap containing the config-as-code files. + ## + existingConfigmap: "" + ## Configuration auto-reload sidecar container + ## + autoReload: + ## @param configAsCode.autoReload.enabled Enable the creation of the autoReload sidecar container. + ## Note: This container will trigger the configuration reload each time the Configmap is updated. Changes applied via Jenkins UI will be overwritten. + ## If disabled, config as code files will only take effect during the container first boot. + ## + enabled: true + ## @param configAsCode.autoReload.initialDelay In seconds, time + ## + initialDelay: 360 + ## @param configAsCode.autoReload.reqRetries + ## + reqRetries: 12 + ## @param configAsCode.autoReload.interval + ## + interval: 10 + ## @param configAsCode.autoReload.command + ## + command: [] + ## @param configAsCode.autoReload.args + ## + args: [] + ## @param configAsCode.autoReload.extraEnvVars + ## + extraEnvVars: [] + ## @param configAsCode.autoReload.extraEnvVarsSecret + ## + extraEnvVarsSecret: "" + ## @param configAsCode.autoReload.extraEnvVarsCM + ## + extraEnvVarsCM: "" + ## @param configAsCode.autoReload.extraVolumeMounts + ## + extraVolumeMounts: [] + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param configAsCode.autoReload.containerSecurityContext.enabled Enabled containers' Security Context + ## @param configAsCode.autoReload.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param configAsCode.autoReload.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param configAsCode.autoReload.containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup + ## @param configAsCode.autoReload.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param configAsCode.autoReload.containerSecurityContext.privileged Set container's Security Context privileged + ## @param configAsCode.autoReload.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param configAsCode.autoReload.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param configAsCode.autoReload.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param configAsCode.autoReload.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## Jenkins containers' resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param configAsCode.autoReload.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, small, medium, large, xlarge, 2xlarge). This is ignored if configAsCode.autoReload.resources is set (configAsCode.autoReload.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "none" + ## @param configAsCode.autoReload.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} +## Jenkins agents (EXPERIMENTAL) +## This feature won't take effect if ConfigAsCode is not enabled. +## NOTE: Values under this field may use Jenkins syntax instead of Kubernetes syntax +## Ref: https://www.jenkins.io/doc/pipeline/steps/kubernetes/ +agent: + ## @param agent.enabled Set to true to enable the configuration of Jenkins kubernetes agents + ## + enabled: false + ## Bitnami Jenkins agent image + ## ref: https://hub.docker.com/r/bitnami/jenkins/tags/ + ## @param agent.image.registry [default: REGISTRY_NAME] Jenkins image registry + ## @param agent.image.repository [default: REPOSITORY_NAME/jenkins-agent] Jenkins image repository + ## @skip agent.image.tag Jenkins image tag (immutable tags are recommended) + ## @param agent.image.digest Jenkins image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param agent.image.pullPolicy Jenkins image pull policy + ## @param agent.image.pullSecrets Jenkins image pull secrets + ## @param agent.image.debug Enable image debug mode + ## + image: + registry: docker.io + repository: bitnami/jenkins-agent + tag: 0.3273.0-debian-12-r1 + digest: "" + ## Specify a imagePullPolicy + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Enable debug mode + ## + debug: false + ## @param agent.templateLabel Label for the Kubernetes agent template + ## + templateLabel: "kubernetes-agent" + ## @param agent.podLabels Additional pod labels for the Jenkins agent pods + ## + podLabels: {} + ## @param agent.annotations Additional pod annotations for the Jenkins agent pods + ## + annotations: {} + ## @param agent.sidecars Additional sidecar containers for the Jenkins agent pods + ## + sidecars: [] + ## @param agent.command Override default container command (useful when using custom images) + ## + command: "" + ## @param agent.args Override default container args (useful when using custom images) + ## + args: "" + ## @param agent.containerExtraEnvVars Additional env vars for the Jenkins agent pods + ## + containerExtraEnvVars: [] + ## @param agent.podExtraEnvVars Additional env vars for the Jenkins agent pods + ## + podExtraEnvVars: [] + ## @param agent.extraAgentTemplate Extend the default agent template + ## + extraAgentTemplate: {} + ## @param agent.extraTemplates Provide your own custom agent templates + ## + extraTemplates: [] + ## Jenkins containers' resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param agent.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if agent.resources is set (agent.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "small" + ## @param agent.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Container securityContext + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param agent.containerSecurityContext.enabled Enable container security context + ## @param agent.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param agent.containerSecurityContext.runAsUser User ID for the agent container + ## @param agent.containerSecurityContext.runAsGroup User ID for the agent container + ## @param agent.containerSecurityContext.privileged Decide if the container runs privileged. + ## + containerSecurityContext: + enabled: false + seLinuxOptions: {} + runAsUser: "" + runAsGroup: "" + privileged: false +## @section Jenkins deployment parameters + +## @param updateStrategy.type Jenkins deployment strategy type +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy +## NOTE: Set it to `Recreate` if you use a PV that cannot be mounted on multiple pods +## e.g: +## updateStrategy: +## type: RollingUpdate +## rollingUpdate: +## maxSurge: 25% +## maxUnavailable: 25% +## +updateStrategy: + type: RollingUpdate +## @param priorityClassName Jenkins pod priority class name +## +priorityClassName: "" +## @param schedulerName Name of the k8s scheduler (other than default) +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +schedulerName: "" +## @param topologySpreadConstraints Topology Spread Constraints for pod assignment +## https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ +## The value is evaluated as a template +## +topologySpreadConstraints: [] +## @param automountServiceAccountToken Mount Service Account token in pod +## +automountServiceAccountToken: true +## @param hostAliases Jenkins pod host aliases +## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ +## +hostAliases: [] +## @param extraVolumes Optionally specify extra list of additional volumes for Jenkins pods +## +extraVolumes: [] +## @param extraVolumeMounts Optionally specify extra list of additional volumeMounts for Jenkins container(s) +## +extraVolumeMounts: [] +## @param sidecars Add additional sidecar containers to the Jenkins pod +## e.g: +## sidecars: +## - name: your-image-name +## image: your-image +## imagePullPolicy: Always +## ports: +## - name: portname +## containerPort: 1234 +## +sidecars: [] +## @param initContainers Add additional init containers to the Jenkins pods +## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ +## e.g: +## initContainers: +## - name: your-image-name +## image: your-image +## imagePullPolicy: Always +## ports: +## - name: portname +## containerPort: 1234 +## +initContainers: [] +## Pod Disruption Budget configuration +## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb +## @param pdb.create Enable/disable a Pod Disruption Budget creation +## @param pdb.minAvailable Minimum number/percentage of pods that should remain scheduled +## @param pdb.maxUnavailable Maximum number/percentage of pods that may be made unavailable. Defaults to `1` if both `pdb.minAvailable` and `pdb.maxUnavailable` are empty. +## +pdb: + create: true + minAvailable: "" + maxUnavailable: "" +## @param lifecycleHooks Add lifecycle hooks to the Jenkins deployment +## +lifecycleHooks: {} +## @param podLabels Extra labels for Jenkins pods +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +## +podLabels: {} +## @param podAnnotations Annotations for Jenkins pods +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +## +podAnnotations: {} +## @param podAffinityPreset Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## +podAffinityPreset: "" +## @param podAntiAffinityPreset Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` +## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## +podAntiAffinityPreset: soft +## Node affinity preset +## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity +## +nodeAffinityPreset: + ## @param nodeAffinityPreset.type Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param nodeAffinityPreset.key Node label key to match. Ignored if `affinity` is set + ## + key: "" + ## @param nodeAffinityPreset.values Node label values to match. Ignored if `affinity` is set + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] +## @param affinity Affinity for pod assignment +## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +## NOTE: podAffinityPreset, podAntiAffinityPreset, and nodeAffinityPreset will be ignored when it's set +## +affinity: {} +## @param nodeSelector Node labels for pod assignment +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ +## +nodeSelector: {} +## @param tolerations Tolerations for pod assignment +## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +## +tolerations: [] +## Jenkins containers' resource requests and limits +## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ +## @param resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). +## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 +## +resourcesPreset: "medium" +## @param resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) +## Example: +## resources: +## requests: +## cpu: 2 +## memory: 512Mi +## limits: +## cpu: 3 +## memory: 1024Mi +## +resources: {} +## Container ports +## @param containerPorts.http Jenkins HTTP container port +## @param containerPorts.https Jenkins HTTPS container port +## @param containerPorts.agentListener Jenkins agent listener port, ignored if agent.enabled=false +## +containerPorts: + http: 8080 + https: 8443 + agentListener: 50000 +## Configure Pods Security Context +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod +## @param podSecurityContext.enabled Enabled Jenkins pods' Security Context +## @param podSecurityContext.fsGroupChangePolicy Set filesystem group change policy +## @param podSecurityContext.sysctls Set kernel settings using the sysctl interface +## @param podSecurityContext.supplementalGroups Set filesystem extra groups +## @param podSecurityContext.fsGroup Set Jenkins pod's Security Context fsGroup +## +podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + sysctls: [] + supplementalGroups: [] + fsGroup: 1001 +## Configure Container Security Context (only main container) +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container +## @param containerSecurityContext.enabled Enabled containers' Security Context +## @param containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container +## @param containerSecurityContext.runAsUser Set containers' Security Context runAsUser +## @param containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup +## @param containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot +## @param containerSecurityContext.privileged Set container's Security Context privileged +## @param containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem +## @param containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation +## @param containerSecurityContext.capabilities.drop List of capabilities to be dropped +## @param containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile +## +containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" +## Configure extra options for Jenkins containers' startup, liveness and readiness probes +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes +## @param startupProbe.enabled Enable startupProbe +## @param startupProbe.initialDelaySeconds Initial delay seconds for startupProbe +## @param startupProbe.periodSeconds Period seconds for startupProbe +## @param startupProbe.timeoutSeconds Timeout seconds for startupProbe +## @param startupProbe.failureThreshold Failure threshold for startupProbe +## @param startupProbe.successThreshold Success threshold for startupProbe +## +startupProbe: + enabled: false + initialDelaySeconds: 180 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 6 +## @param livenessProbe.enabled Enable livenessProbe +## @param livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe +## @param livenessProbe.periodSeconds Period seconds for livenessProbe +## @param livenessProbe.timeoutSeconds Timeout seconds for livenessProbe +## @param livenessProbe.failureThreshold Failure threshold for livenessProbe +## @param livenessProbe.successThreshold Success threshold for livenessProbe +## +livenessProbe: + enabled: true + initialDelaySeconds: 180 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 6 +## @param readinessProbe.enabled Enable readinessProbe +## @param readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe +## @param readinessProbe.periodSeconds Period seconds for readinessProbe +## @param readinessProbe.timeoutSeconds Timeout seconds for readinessProbe +## @param readinessProbe.failureThreshold Failure threshold for readinessProbe +## @param readinessProbe.successThreshold Success threshold for readinessProbe +## +readinessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 5 + timeoutSeconds: 3 + successThreshold: 1 + failureThreshold: 3 +## @param customStartupProbe Custom startupProbe that overrides the default one +## +customStartupProbe: {} +## @param customLivenessProbe Custom livenessProbe that overrides the default one +## +customLivenessProbe: {} +## @param customReadinessProbe Custom readinessProbe that overrides the default one +# +customReadinessProbe: {} +## @section Traffic Exposure Parameters + +## Jenkins service parameters +## +service: + ## @param service.type Jenkins service type + ## + type: LoadBalancer + ## @param service.ports.http Jenkins service HTTP port + ## @param service.ports.https Jenkins service HTTPS port + ## + ports: + http: 80 + https: 443 + ## Node ports to expose + ## @param service.nodePorts.http Node port for HTTP + ## @param service.nodePorts.https Node port for HTTPS + ## NOTE: choose port between <30000-32767> + ## + nodePorts: + http: "" + https: "" + ## @param service.clusterIP Jenkins service Cluster IP + ## e.g.: + ## clusterIP: None + ## + clusterIP: "" + ## @param service.loadBalancerIP Jenkins service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerIP: "" + ## @param service.loadBalancerSourceRanges Jenkins service Load Balancer sources + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param service.externalTrafficPolicy Jenkins service external traffic policy + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param service.annotations Additional custom annotations for Jenkins service + ## + annotations: {} + ## @param service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} +## Network Policies +## Ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ +## +networkPolicy: + ## @param networkPolicy.enabled Specifies whether a NetworkPolicy should be created + ## + enabled: true + ## @param networkPolicy.allowExternal Don't require server label for connections + ## The Policy model to apply. When set to false, only pods with the correct + ## server label will have network access to the ports server is listening + ## on. When true, server will accept connections from any source + ## (with the correct destination port). + ## + allowExternal: true + ## @param networkPolicy.allowExternalEgress Allow the pod to access any range of port and all destinations. + ## + allowExternalEgress: true + ## @param networkPolicy.kubeAPIServerPorts [array] List of possible endpoints to kube-apiserver (limit to your cluster settings to increase security) + ## + kubeAPIServerPorts: [443, 6443, 8443] + ## @param networkPolicy.extraIngress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraIngress: + ## - ports: + ## - port: 1234 + ## from: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + extraIngress: [] + ## @param networkPolicy.extraEgress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraEgress: + ## - ports: + ## - port: 1234 + ## to: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraEgress: [] + ## @param networkPolicy.ingressNSMatchLabels [object] Labels to match to allow traffic from other namespaces + ## @param networkPolicy.ingressNSPodMatchLabels [object] Pod labels to match to allow traffic from other namespaces + ## + ingressNSMatchLabels: {} + ingressNSPodMatchLabels: {} +## Jenkins agent listener service parameters +## NOTE: ignored if agent.enabled=false +## +agentListenerService: + ## @param agentListenerService.enabled + ## + enabled: true + ## @param agentListenerService.type Jenkins service type + ## + type: ClusterIP + ## @param agentListenerService.ports.agentListener Jenkins service agent listener port + ## + ports: + agentListener: 50000 + ## Node ports to expose + ## @param agentListenerService.nodePorts.agentListener Node port for agent listener + ## NOTE: choose port between <30000-32767> + ## + nodePorts: + agentListener: "" + ## @param agentListenerService.clusterIP Jenkins service Cluster IP + ## e.g.: + ## clusterIP: None + ## + clusterIP: "" + ## @param agentListenerService.loadBalancerIP Jenkins service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerIP: "" + ## @param agentListenerService.loadBalancerSourceRanges Jenkins service Load Balancer sources + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param agentListenerService.externalTrafficPolicy Jenkins service external traffic policy + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param agentListenerService.annotations Additional custom annotations for Jenkins service + ## + annotations: {} + ## @param agentListenerService.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param agentListenerService.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param agentListenerService.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} +## Configure the ingress resource that allows you to access the Jenkins installation +## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/ +## +ingress: + ## @param ingress.enabled Enable ingress record generation for Jenkins + ## + enabled: false + ## @param ingress.pathType Ingress path type + ## + pathType: ImplementationSpecific + ## @param ingress.apiVersion Force Ingress API version (automatically detected if not set) + ## + apiVersion: "" + ## @param ingress.hostname Default host for the ingress record + ## + hostname: jenkins.local + ## @param ingress.path Default path for the ingress record + ## NOTE: You may need to set this to '/*' in order to use this with ALB ingress controllers + ## + path: / + ## @param ingress.annotations Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. + ## For a full list of possible ingress annotations, please see + ## ref: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md + ## Use this parameter to set the required annotations for cert-manager, see + ## ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations + ## + ## e.g: + ## annotations: + ## kubernetes.io/ingress.class: nginx + ## cert-manager.io/cluster-issuer: cluster-issuer-name + ## + annotations: {} + ## @param ingress.tls Enable TLS configuration for the host defined at `ingress.hostname` parameter + ## TLS certificates will be retrieved from a TLS secret with name: `{{- printf "%s-tls" .Values.ingress.hostname }}` + ## You can: + ## - Use the `ingress.secrets` parameter to create this TLS secret + ## - Rely on cert-manager to create it by setting the corresponding annotations + ## - Rely on Helm to create self-signed certificates by setting `ingress.selfSigned=true` + ## + tls: false + ## @param ingress.selfSigned Create a TLS secret for this ingress record using self-signed certificates generated by Helm + ## + selfSigned: false + ## @param ingress.extraHosts An array with additional hostname(s) to be covered with the ingress record + ## e.g: + ## extraHosts: + ## - name: jenkins.local + ## path: / + ## + extraHosts: [] + ## @param ingress.extraPaths An array with additional arbitrary paths that may need to be added to the ingress under the main host + ## e.g: + ## extraPaths: + ## - path: /* + ## backend: + ## serviceName: ssl-redirect + ## servicePort: use-annotation + ## + extraPaths: [] + ## @param ingress.extraTls TLS configuration for additional hostname(s) to be covered with this ingress record + ## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#tls + ## e.g: + ## extraTls: + ## - hosts: + ## - jenkins.local + ## secretName: jenkins.local-tls + ## + extraTls: [] + ## @param ingress.secrets Custom TLS certificates as secrets + ## NOTE: 'key' and 'certificate' are expected in PEM format + ## NOTE: 'name' should line up with a 'secretName' set further up + ## If it is not set and you're using cert-manager, this is unneeded, as it will create a secret for you with valid certificates + ## If it is not set and you're NOT using cert-manager either, self-signed certificates will be created valid for 365 days + ## It is also possible to create and manage the certificates outside of this helm chart + ## Please see README.md for more information + ## e.g: + ## secrets: + ## - name: jenkins.local-tls + ## key: |- + ## -----BEGIN RSA PRIVATE KEY----- + ## ... + ## -----END RSA PRIVATE KEY----- + ## certificate: |- + ## -----BEGIN CERTIFICATE----- + ## ... + ## -----END CERTIFICATE----- + ## + secrets: [] + ## @param ingress.ingressClassName IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+) + ## This is supported in Kubernetes 1.18+ and required if you have more than one IngressClass marked as the default for your cluster . + ## ref: https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/ + ## + ingressClassName: "" + ## @param ingress.extraRules Additional rules to be covered with this ingress record + ## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-rules + ## e.g: + ## extraRules: + ## - host: example.local + ## http: + ## path: / + ## backend: + ## service: + ## name: example-svc + ## port: + ## name: http + ## + extraRules: [] +## @section Persistence Parameters + +## Persistence Parameters +## ref: https://kubernetes.io/docs/concepts/storage/persistent-volumes/ +## +persistence: + ## @param persistence.enabled Enable persistence using Persistent Volume Claims + ## + enabled: true + ## @param persistence.storageClass 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 + ## + storageClass: "" + ## @param persistence.existingClaim Use a existing PVC which must be created manually before bound + ## + existingClaim: "" + ## @param persistence.annotations Additional custom annotations for the PVC + ## + annotations: {} + ## @param persistence.accessModes [array] Persistent Volume access modes + ## + accessModes: + - ReadWriteOnce + ## @param persistence.size Persistent Volume size + ## + size: 8Gi + ## @param persistence.selector Selector to match an existing Persistent Volume for Ingester's data PVC + ## If set, the PVC can't have a PV dynamically provisioned for it + ## E.g. + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} +## 'volumePermissions' init container parameters +## Changes the owner and group of the persistent volume mount point to runAsUser:fsGroup values +## based on the podSecurityContext/containerSecurityContext parameters +## +volumePermissions: + ## @param volumePermissions.enabled Enable init container that changes the owner/group of the PV mount point to `runAsUser:fsGroup` + ## + enabled: false + ## OS Shell + Utility image + ## ref: https://hub.docker.com/r/bitnami/os-shell/tags/ + ## @param volumePermissions.image.registry [default: REGISTRY_NAME] OS Shell + Utility image registry + ## @param volumePermissions.image.repository [default: REPOSITORY_NAME/os-shell] OS Shell + Utility image repository + ## @skip volumePermissions.image.tag OS Shell + Utility image tag (immutable tags are recommended) + ## @param volumePermissions.image.digest OS Shell + Utility image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param volumePermissions.image.pullPolicy OS Shell + Utility image pull policy + ## @param volumePermissions.image.pullSecrets OS Shell + Utility image pull secrets + ## + image: + registry: docker.io + repository: bitnami/os-shell + tag: 12-debian-12-r32 + digest: "" + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Init container's resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param volumePermissions.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if volumePermissions.resources is set (volumePermissions.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param volumePermissions.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Init container Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param volumePermissions.securityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param volumePermissions.securityContext.runAsUser Set init container's Security Context runAsUser + ## NOTE: when runAsUser is set to special value "auto", init container will try to chown the + ## data folder to auto-determined user&group, using commands: `id -u`:`id -G | cut -d" " -f2` + ## "auto" is especially useful for OpenShift which has scc with dynamic user ids (and 0 is not allowed) + ## + securityContext: + seLinuxOptions: {} + runAsUser: 0 +## @section Other Parameters +## + +## RBAC configuration +## +rbac: + ## @param rbac.create Specifies whether RBAC resources should be created + ## + create: true + ## @param rbac.rules Custom RBAC rules to set + ## e.g: + ## rules: + ## - apiGroups: + ## - "" + ## resources: + ## - pods + ## verbs: + ## - get + ## - list + ## + rules: [] +## ServiceAccount configuration +## +serviceAccount: + ## @param serviceAccount.create Specifies whether a ServiceAccount should be created + ## + create: true + ## @param serviceAccount.name The name of the ServiceAccount to use. + ## If not set and create is true, a name is generated using the common.names.fullname template + ## + name: "" + ## @param serviceAccount.annotations Additional Service Account annotations (evaluated as a template) + ## + annotations: {} + ## @param serviceAccount.automountServiceAccountToken Automount service account token for the server service account + ## + automountServiceAccountToken: false diff --git a/backing-services/minio/.helmignore b/backing-services/minio/.helmignore new file mode 100644 index 0000000..207983f --- /dev/null +++ b/backing-services/minio/.helmignore @@ -0,0 +1,25 @@ +# 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 +# img folder +img/ +# Changelog +CHANGELOG.md diff --git a/backing-services/minio/Chart.lock b/backing-services/minio/Chart.lock new file mode 100644 index 0000000..8699880 --- /dev/null +++ b/backing-services/minio/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + version: 2.30.0 +digest: sha256:46afdf79eae69065904d430f03f7e5b79a148afed20aa45ee83ba88adc036169 +generated: "2025-02-19T23:09:00.050521217Z" diff --git a/backing-services/minio/Chart.yaml b/backing-services/minio/Chart.yaml new file mode 100644 index 0000000..cda66bd --- /dev/null +++ b/backing-services/minio/Chart.yaml @@ -0,0 +1,36 @@ +annotations: + category: Infrastructure + images: | + - name: minio + image: docker.io/bitnami/minio:2025.2.18-debian-12-r0 + - name: minio-client + image: docker.io/bitnami/minio-client:2025.2.15-debian-12-r0 + - name: os-shell + image: docker.io/bitnami/os-shell:12-debian-12-r38 + licenses: Apache-2.0 +apiVersion: v2 +appVersion: 2025.2.18 +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + tags: + - bitnami-common + version: 2.x.x +description: MinIO(R) is an object storage server, compatible with Amazon S3 cloud + storage service, mainly used for storing unstructured data (such as photos, videos, + log files, etc.). +home: https://bitnami.com +icon: https://dyltqmyl993wv.cloudfront.net/assets/stacks/minio/img/minio-stack-220x234.png +keywords: +- minio +- storage +- object-storage +- s3 +- cluster +maintainers: +- name: Broadcom, Inc. All Rights Reserved. + url: https://github.com/bitnami/charts +name: minio +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/minio +version: 15.0.4 diff --git a/backing-services/minio/README.md b/backing-services/minio/README.md new file mode 100644 index 0000000..698d382 --- /dev/null +++ b/backing-services/minio/README.md @@ -0,0 +1,665 @@ + + +# Bitnami Object Storage based on MinIO(R) + +MinIO(R) is an object storage server, compatible with Amazon S3 cloud storage service, mainly used for storing unstructured data (such as photos, videos, log files, etc.). + +[Overview of Bitnami Object Storage based on MinIO®](https://min.io/) + +Disclaimer: All software products, projects and company names are trademark(TM) or registered(R) trademarks of their respective holders, and use of them does not imply any affiliation or endorsement. This software is licensed to you subject to one or more open source licenses and VMware provides the software on an AS-IS basis. MinIO(R) is a registered trademark of the MinIO Inc. in the US and other countries. Bitnami is not affiliated, associated, authorized, endorsed by, or in any way officially connected with MinIO Inc. MinIO(R) is licensed under GNU AGPL v3.0. + +## TL;DR + +```console +helm install my-release oci://registry-1.docker.io/bitnamicharts/minio +``` + +Looking to use Bitnami Object Storage based on MinIOreg; in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the commercial edition of the Bitnami catalog. + +## Introduction + +This chart bootstraps a [MinIO®](https://github.com/bitnami/containers/tree/main/bitnami/minio) deployment on a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ +- 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 oci://REGISTRY_NAME/REPOSITORY_NAME/minio +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +These commands deploy MinIO® 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` + +## Configuration and installation details + +### Resource requests and limits + +Bitnami charts allow setting resource requests and limits for all containers inside the chart deployment. These are inside the `resources` value (check parameter table). Setting requests is essential for production workloads and these should be adapted to your specific use case. + +To make this process easier, the chart contains the `resourcesPreset` values, which automatically sets the `resources` section according to different presets. Check these presets in [the bitnami/common chart](https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15). However, in production workloads using `resourcesPreset` is discouraged as it may not fully adapt to your specific needs. Find more information on container resource management in the [official Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). + +### Update credentials + +Bitnami charts configure credentials at first boot. Any further change in the secrets or credentials require manual intervention. Follow these instructions: + +- Update the user password following [the upstream documentation](https://min.io/docs/minio/linux/administration/identity-access-management/minio-user-management.html) +- Update the password secret with the new values (replace the SECRET_NAME, USER and PASSWORD placeholders) + +```shell +kubectl create secret generic SECRET_NAME --from-literal=root-user=USER --from-literal=root-password=PASSWORD --dry-run -o yaml | kubectl apply -f - +``` + +### Prometheus metrics + +This chart can be integrated with Prometheus by setting `metrics.enabled` to `true`. This will expose MinIO(TM) native Prometheus endpoint in the service. It will have the necessary annotations to be automatically scraped by Prometheus. + +#### Prometheus requirements + +It is necessary to have a working installation of Prometheus or Prometheus Operator for the integration to work. Install the [Bitnami Prometheus helm chart](https://github.com/bitnami/charts/tree/main/bitnami/prometheus) or the [Bitnami Kube Prometheus helm chart](https://github.com/bitnami/charts/tree/main/bitnami/kube-prometheus) to easily have a working Prometheus in your cluster. + +#### Integration with Prometheus Operator + +The chart can deploy `ServiceMonitor` objects for integration with Prometheus Operator installations. To do so, set the value `metrics.serviceMonitor.enabled=true`. Ensure that the Prometheus Operator `CustomResourceDefinitions` are installed in the cluster or it will fail with the following error: + +```text +no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1" +``` + +Install the [Bitnami Kube Prometheus helm chart](https://github.com/bitnami/charts/tree/main/bitnami/kube-prometheus) for having the necessary CRDs and the Prometheus Operator. + +### [Rolling VS Immutable tags](https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-understand-rolling-tags-containers-index.html) + +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. + +### Distributed mode + +By default, this chart provisions a MinIO® server in standalone mode. You can start MinIO® server in [distributed mode](https://docs.minio.io/docs/distributed-minio-quickstart-guide) with the following parameter: `mode=distributed` + +This chart bootstrap MinIO® server in distributed mode with 4 nodes by default. You can change the number of nodes using the `statefulset.replicaCount` parameter. For instance, you can deploy the chart with 8 nodes using the following parameters: + +```console +mode=distributed +statefulset.replicaCount=8 +``` + +You can also bootstrap MinIO® server in distributed mode in several zones, and using multiple drives per node. For instance, you can deploy the chart with 2 nodes per zone on 2 zones, using 2 drives per node: + +```console +mode=distributed +statefulset.replicaCount=2 +statefulset.zones=2 +statefulset.drivesPerNode=2 +``` + +> Note: The total number of drives should be greater than 4 to guarantee erasure coding. Please set a combination of nodes, and drives per node that match this condition. + +### Prometheus exporter + +MinIO® exports Prometheus metrics at `/minio/v2/metrics/cluster`. To allow Prometheus collecting your MinIO® metrics, modify the `values.yaml` adding the corresponding annotations: + +```diff +- podAnnotations: {} ++ podAnnotations: ++ prometheus.io/scrape: "true" ++ prometheus.io/path: "/minio/v2/metrics/cluster" ++ prometheus.io/port: "9000" +``` + +> Find more information about MinIO® metrics at + +### Ingress + +This chart provides support for Ingress resources. If you have an ingress controller installed on your cluster, such as [nginx-ingress-controller](https://github.com/bitnami/charts/tree/main/bitnami/nginx-ingress-controller) or [contour](https://github.com/bitnami/charts/tree/main/bitnami/contour) you can utilize the ingress controller to serve your application.To enable Ingress integration, set `ingress.enabled` to `true`. + +The most common scenario is to have one host name mapped to the deployment. In this case, the `ingress.hostname` property can be used to set the host name. The `ingress.tls` parameter can be used to add the TLS configuration for this host. + +However, it is also possible to have more than one host. To facilitate this, the `ingress.extraHosts` parameter (if available) can be set with the host names specified as an array. The `ingress.extraTLS` parameter (if available) can also be used to add the TLS configuration for extra hosts. + +> NOTE: For each host specified in the `ingress.extraHosts` parameter, it is necessary to set a name, path, and any annotations that the Ingress controller should know about. Not all annotations are supported by all Ingress controllers, but [this annotation reference document](https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md) lists the annotations supported by many popular Ingress controllers. + +Adding the TLS parameter (where available) will cause the chart to generate HTTPS URLs, and the application will be available on port 443. The actual TLS secrets do not have to be generated by this chart. However, if TLS is enabled, the Ingress record will not work until the TLS secret exists. + +[Learn more about Ingress controllers](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/). + +### Securing traffic using TLS + +This chart facilitates the creation of TLS secrets for use with the Ingress controller (although this is not mandatory). There are several common use cases: + +- Generate certificate secrets based on chart parameters. +- Enable externally generated certificates. +- Manage application certificates via an external service (like [cert-manager](https://github.com/jetstack/cert-manager/)). +- Create self-signed certificates within the chart (if supported). + +In the first two cases, a certificate and a key are needed. Files are expected in `.pem` format. + +Here is an example of a certificate file: + +> NOTE: There may be more than one certificate if there is a certificate chain. + +```text +-----BEGIN CERTIFICATE----- +MIID6TCCAtGgAwIBAgIJAIaCwivkeB5EMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV +... +jScrvkiBO65F46KioCL9h5tDvomdU1aqpI/CBzhvZn1c0ZTf87tGQR8NK7v7 +-----END CERTIFICATE----- +``` + +Here is an example of a certificate key: + +```text +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAvLYcyu8f3skuRyUgeeNpeDvYBCDcgq+LsWap6zbX5f8oLqp4 +... +wrj2wDbCDCFmfqnSJ+dKI3vFLlEz44sAV8jX/kd4Y6ZTQhlLbYc= +-----END RSA PRIVATE KEY----- +``` + +- If using Helm to manage the certificates based on the parameters, copy these values into the `certificate` and `key` values for a given `*.ingress.secrets` entry. +- If managing TLS secrets separately, it is necessary to create a TLS secret with name `INGRESS_HOSTNAME-tls` (where INGRESS_HOSTNAME is a placeholder to be replaced with the hostname you set using the `*.ingress.hostname` parameter). +- If your cluster has a [cert-manager](https://github.com/jetstack/cert-manager) add-on to automate the management and issuance of TLS certificates, add to `*.ingress.annotations` the [corresponding ones](https://cert-manager.io/docs/usage/ingress/#supported-annotations) for cert-manager. +- If using self-signed certificates created by Helm, set both `*.ingress.tls` and `*.ingress.selfSigned` to `true`. + +### Adding extra environment variables + +In case you want to add extra environment variables (useful for advanced operations like custom init scripts), you can use the `extraEnvVars` property. + +```yaml +extraEnvVars: + - name: MINIO_LOG_LEVEL + value: DEBUG +``` + +Alternatively, you can use a ConfigMap or a Secret with the environment variables. To do so, use the `extraEnvVarsCM` or the `extraEnvVarsSecret` values. + +### Sidecars and Init Containers + +If you have a need for additional containers to run within the same pod as the MinIO® app (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 +sidecars: + - name: your-image-name + image: your-image + imagePullPolicy: Always + ports: + - name: portname + containerPort: 1234 +``` + +Similarly, you can add extra init containers using the `initContainers` parameter. + +```yaml +initContainers: + - name: your-image-name + image: your-image + imagePullPolicy: Always + ports: + - name: portname + containerPort: 1234 +``` + +### Deploying extra resources + +There are cases where you may want to deploy extra objects, such a ConfigMap containing your app's configuration or some extra deployment with a micro service used by your app. For covering this case, the chart allows adding the full specification of other objects using the `extraDeploy` parameter. + +### Setting Pod's affinity + +This chart allows you to set your custom affinity using the `affinity` parameter. Find more information about Pod's affinity in the [kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). + +As an alternative, you can use of the preset configurations for pod affinity, pod anti-affinity, and node affinity available at the [bitnami/common](https://github.com/bitnami/charts/tree/main/bitnami/common#affinities) chart. To do so, set the `podAffinityPreset`, `podAntiAffinityPreset`, or `nodeAffinityPreset` parameters. + +### Backup and restore + +To back up and restore Helm chart deployments on Kubernetes, you need to back up the persistent volumes from the source deployment and attach them to a new deployment using [Velero](https://velero.io/), a Kubernetes backup/restore tool. Find the instructions for using Velero in [this guide](https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-backup-restore-deployments-velero-index.html). + +## Persistence + +The [Bitnami Object Storage based on MinIO(®)](https://github.com/bitnami/containers/tree/main/bitnami/minio) image stores data at the `/bitnami/minio/data` path of the container by default. +This can be modified with the `persistence.mountPath` value which modifies the `MINIO_DATA_DIR` environment variable of the container. + +The chart mounts a [Persistent Volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) at this location so that data within MinIO is persistent. The volume is created using dynamic volume provisioning. + +### Adjust permissions of persistent volume mountpoint + +As the image run as non-root by default, it is necessary to adjust the ownership of the persistent volume so that the container can write data into it. + +By default, the chart is configured to use Kubernetes Security Context to automatically change the ownership of the volume. However, this feature does not work in all Kubernetes distributions. +As an alternative, this chart supports using an initContainer to change the ownership of the volume before mounting it in the final destination. + +You can enable this initContainer by setting `volumePermissions.enabled` to `true`. + +## Parameters + +### Global parameters + +| Name | Description | Value | +| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `global.imageRegistry` | Global Docker image registry | `""` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | +| `global.defaultStorageClass` | Global default StorageClass for Persistent Volume(s) | `""` | +| `global.storageClass` | DEPRECATED: use global.defaultStorageClass instead | `""` | +| `global.security.allowInsecureImages` | Allows skipping image verification | `false` | +| `global.compatibility.openshift.adaptSecurityContext` | Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) | `auto` | + +### Common parameters + +| Name | Description | Value | +| ------------------- | -------------------------------------------------------------------------------------------- | --------------- | +| `nameOverride` | String to partially override common.names.fullname template (will maintain the release name) | `""` | +| `namespaceOverride` | String to fully override common.names.namespace | `""` | +| `fullnameOverride` | String to fully override common.names.fullname template | `""` | +| `commonLabels` | Labels to add to all deployed objects | `{}` | +| `commonAnnotations` | Annotations to add to all deployed objects | `{}` | +| `kubeVersion` | Force target Kubernetes version (using Helm capabilities if not set) | `""` | +| `clusterDomain` | Default Kubernetes cluster domain | `cluster.local` | +| `extraDeploy` | Array of extra objects to deploy with the release | `[]` | + +### MinIO® parameters + +| Name | Description | Value | +| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | +| `image.registry` | MinIO® image registry | `REGISTRY_NAME` | +| `image.repository` | MinIO® image repository | `REPOSITORY_NAME/minio` | +| `image.digest` | MinIO® image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `image.pullPolicy` | Image pull policy | `IfNotPresent` | +| `image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `image.debug` | Specify if debug logs should be enabled | `false` | +| `clientImage.registry` | MinIO® Client image registry | `REGISTRY_NAME` | +| `clientImage.repository` | MinIO® Client image repository | `REPOSITORY_NAME/minio-client` | +| `clientImage.digest` | MinIO® Client image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `mode` | MinIO® server mode (`standalone` or `distributed`) | `standalone` | +| `auth.rootUser` | MinIO® root username | `admin` | +| `auth.rootPassword` | Password for MinIO® root user | `""` | +| `auth.existingSecret` | Use existing secret for credentials details (`auth.rootUser` and `auth.rootPassword` will be ignored and picked up from this secret). | `""` | +| `auth.rootUserSecretKey` | Key where the MINIO_ROOT_USER username is being stored inside the existing secret `auth.existingSecret` | `""` | +| `auth.rootPasswordSecretKey` | Key where the MINIO_ROOT_USER password is being stored inside the existing secret `auth.existingSecret` | `""` | +| `auth.forcePassword` | Force users to specify required passwords | `false` | +| `auth.useCredentialsFiles` | Mount credentials as a files instead of using an environment variable | `false` | +| `auth.useSecret` | Uses a secret to mount the credential files. | `true` | +| `auth.forceNewKeys` | Force root credentials (user and password) to be reconfigured every time they change in the secrets | `false` | +| `defaultBuckets` | Comma, semi-colon or space separated list of buckets to create at initialization (only in standalone mode) | `""` | +| `disableWebUI` | Disable MinIO® Web UI | `false` | +| `tls.enabled` | Enable tls in front of the container | `false` | +| `tls.autoGenerated` | Generate automatically self-signed TLS certificates | `false` | +| `tls.existingSecret` | Name of an existing secret holding the certificate information | `""` | +| `tls.mountPath` | The mount path where the secret will be located | `""` | +| `extraEnvVars` | Extra environment variables to be set on MinIO® container | `[]` | +| `extraEnvVarsCM` | ConfigMap with extra environment variables | `""` | +| `extraEnvVarsSecret` | Secret with extra environment variables | `""` | +| `command` | Default container command (useful when using custom images). Use array form | `[]` | +| `args` | Default container args (useful when using custom images). Use array form | `[]` | + +### MinIO® deployment/statefulset parameters + +| Name | Description | Value | +| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | +| `schedulerName` | Specifies the schedulerName, if it's nil uses kube-scheduler | `""` | +| `terminationGracePeriodSeconds` | In seconds, time the given to the MinIO pod needs to terminate gracefully | `""` | +| `deployment.updateStrategy.type` | Deployment strategy type | `Recreate` | +| `statefulset.updateStrategy.type` | StatefulSet strategy type | `RollingUpdate` | +| `statefulset.podManagementPolicy` | StatefulSet controller supports relax its ordering guarantees while preserving its uniqueness and identity guarantees. There are two valid pod management policies: OrderedReady and Parallel | `Parallel` | +| `statefulset.replicaCount` | Number of pods per zone (only for MinIO® distributed mode). Should be even and `>= 4` | `4` | +| `statefulset.zones` | Number of zones (only for MinIO® distributed mode) | `1` | +| `statefulset.drivesPerNode` | Number of drives attached to every node (only for MinIO® distributed mode) | `1` | +| `provisioning.enabled` | Enable MinIO® provisioning Job | `false` | +| `provisioning.sleepTime` | Sleep time before checking Minio availability | `5` | +| `provisioning.schedulerName` | Name of the k8s scheduler (other than default) for MinIO® provisioning | `""` | +| `provisioning.nodeSelector` | Node labels for pod assignment. Evaluated as a template. | `{}` | +| `provisioning.podLabels` | Extra labels for provisioning pods | `{}` | +| `provisioning.podAnnotations` | Provisioning Pod annotations. | `{}` | +| `provisioning.command` | Default provisioning container command (useful when using custom images). Use array form | `[]` | +| `provisioning.args` | Default provisioning container args (useful when using custom images). Use array form | `[]` | +| `provisioning.extraCommands` | Optionally specify extra list of additional commands for MinIO® provisioning pod | `[]` | +| `provisioning.extraVolumes` | Optionally specify extra list of additional volumes for MinIO® provisioning pod | `[]` | +| `provisioning.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for MinIO® provisioning container | `[]` | +| `provisioning.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if provisioning.resources is set (provisioning.resources is recommended for production). | `nano` | +| `provisioning.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `provisioning.policies` | MinIO® policies provisioning | `[]` | +| `provisioning.users` | MinIO® users provisioning. Can be used in addition to provisioning.usersExistingSecrets. | `[]` | +| `provisioning.usersExistingSecrets` | Array if existing secrets containing MinIO® users to be provisioned. Can be used in addition to provisioning.users. | `[]` | +| `provisioning.groups` | MinIO® groups provisioning | `[]` | +| `provisioning.buckets` | MinIO® buckets, versioning, lifecycle, quota and tags provisioning | `[]` | +| `provisioning.config` | MinIO® config provisioning | `[]` | +| `provisioning.podSecurityContext.enabled` | Enable pod Security Context | `true` | +| `provisioning.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `provisioning.podSecurityContext.sysctls` | Set kernel settings using the sysctl interface | `[]` | +| `provisioning.podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `provisioning.podSecurityContext.fsGroup` | Group ID for the container | `1001` | +| `provisioning.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `provisioning.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `provisioning.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `provisioning.containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `provisioning.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `provisioning.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `provisioning.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `provisioning.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `provisioning.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `provisioning.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `provisioning.cleanupAfterFinished.enabled` | Enables Cleanup for Finished Jobs | `false` | +| `provisioning.cleanupAfterFinished.seconds` | Sets the value of ttlSecondsAfterFinished | `600` | +| `provisioning.networkPolicy.enabled` | Enable creation of NetworkPolicy resources | `true` | +| `provisioning.networkPolicy.allowExternalEgress` | Allow the pod to access any range of port and all destinations. | `true` | +| `provisioning.networkPolicy.extraIngress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `provisioning.networkPolicy.extraEgress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `automountServiceAccountToken` | Mount Service Account token in pod | `false` | +| `hostAliases` | MinIO® pod host aliases | `[]` | +| `containerPorts.api` | MinIO® container port to open for MinIO® API | `9000` | +| `containerPorts.console` | MinIO® container port to open for MinIO® Console | `9001` | +| `podSecurityContext.enabled` | Enable pod Security Context | `true` | +| `podSecurityContext.sysctls` | Set kernel settings using the sysctl interface | `[]` | +| `podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `podSecurityContext.fsGroup` | Group ID for the container | `1001` | +| `podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `OnRootMismatch` | +| `podSecurityContext.sysctls` | Set kernel settings using the sysctl interface | `[]` | +| `podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `podSecurityContext.fsGroupChangePolicy` | When K8s should preform chown on attached volumes | `OnRootMismatch` | +| `containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `podLabels` | Extra labels for MinIO® pods | `{}` | +| `podAnnotations` | Annotations for MinIO® pods | `{}` | +| `podAffinityPreset` | Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `nodeAffinityPreset.type` | Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `nodeAffinityPreset.key` | Node label key to match. Ignored if `affinity` is set. | `""` | +| `nodeAffinityPreset.values` | Node label values to match. Ignored if `affinity` is set. | `[]` | +| `affinity` | Affinity for pod assignment. Evaluated as a template. | `{}` | +| `nodeSelector` | Node labels for pod assignment. Evaluated as a template. | `{}` | +| `tolerations` | Tolerations for pod assignment. Evaluated as a template. | `[]` | +| `topologySpreadConstraints` | Topology Spread Constraints for MinIO® pods assignment spread across your cluster among failure-domains | `[]` | +| `priorityClassName` | MinIO® pods' priorityClassName | `""` | +| `runtimeClassName` | Name of the runtime class to be used by MinIO® pods' | `""` | +| `resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `micro` | +| `resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `livenessProbe.enabled` | Enable livenessProbe | `true` | +| `livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `5` | +| `livenessProbe.periodSeconds` | Period seconds for livenessProbe | `5` | +| `livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `5` | +| `livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `readinessProbe.enabled` | Enable readinessProbe | `true` | +| `readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `readinessProbe.periodSeconds` | Period seconds for readinessProbe | `5` | +| `readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `1` | +| `readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `5` | +| `readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `startupProbe.enabled` | Enable startupProbe | `false` | +| `startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `0` | +| `startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `startupProbe.failureThreshold` | Failure threshold for startupProbe | `60` | +| `startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `customLivenessProbe` | Override default liveness probe | `{}` | +| `customReadinessProbe` | Override default readiness probe | `{}` | +| `customStartupProbe` | Override default startup probe | `{}` | +| `lifecycleHooks` | for the MinIO® container(s) to automate configuration before or after startup | `{}` | +| `extraVolumes` | Optionally specify extra list of additional volumes for MinIO® pods | `[]` | +| `extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for MinIO® container(s) | `[]` | +| `initContainers` | Add additional init containers to the MinIO® pods | `[]` | +| `sidecars` | Add additional sidecar containers to the MinIO® pods | `[]` | + +### Traffic exposure parameters + +| Name | Description | Value | +| --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | +| `service.type` | MinIO® service type | `ClusterIP` | +| `service.ports.api` | MinIO® API service port | `9000` | +| `service.ports.console` | MinIO® Console service port | `9001` | +| `service.nodePorts.api` | Specify the MinIO® API nodePort value for the LoadBalancer and NodePort service types | `""` | +| `service.nodePorts.console` | Specify the MinIO® Console nodePort value for the LoadBalancer and NodePort service types | `""` | +| `service.clusterIP` | Service Cluster IP | `""` | +| `service.loadBalancerIP` | loadBalancerIP if service type is `LoadBalancer` (optional, cloud specific) | `""` | +| `service.loadBalancerSourceRanges` | Addresses that are allowed when service is LoadBalancer | `[]` | +| `service.externalTrafficPolicy` | Enable client source IP preservation | `Cluster` | +| `service.extraPorts` | Extra ports to expose in the service (normally used with the `sidecar` value) | `[]` | +| `service.annotations` | Annotations for MinIO® service | `{}` | +| `service.headless.annotations` | Annotations for the headless service. | `{}` | +| `ingress.enabled` | Enable ingress controller resource for MinIO Console | `false` | +| `ingress.apiVersion` | Force Ingress API version (automatically detected if not set) | `""` | +| `ingress.ingressClassName` | IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+) | `""` | +| `ingress.hostname` | Default host for the ingress resource | `minio.local` | +| `ingress.path` | The Path to MinIO®. You may need to set this to '/*' in order to use this with ALB ingress controllers. | `/` | +| `ingress.pathType` | Ingress path type | `ImplementationSpecific` | +| `ingress.servicePort` | Service port to be used | `minio-console` | +| `ingress.annotations` | Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. | `{}` | +| `ingress.tls` | Enable TLS configuration for the hostname defined at `ingress.hostname` parameter | `false` | +| `ingress.selfSigned` | Create a TLS secret for this ingress record using self-signed certificates generated by Helm | `false` | +| `ingress.extraHosts` | The list of additional hostnames to be covered with this ingress record. | `[]` | +| `ingress.extraPaths` | Any additional paths that may need to be added to the ingress under the main host | `[]` | +| `ingress.extraTls` | The tls configuration for additional hostnames to be covered with this ingress record. | `[]` | +| `ingress.secrets` | If you're providing your own certificates, please use this to add the certificates as secrets | `[]` | +| `ingress.extraRules` | Additional rules to be covered with this ingress record | `[]` | +| `apiIngress.enabled` | Enable ingress controller resource for MinIO API | `false` | +| `apiIngress.apiVersion` | Force Ingress API version (automatically detected if not set) | `""` | +| `apiIngress.ingressClassName` | IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+) | `""` | +| `apiIngress.hostname` | Default host for the ingress resource | `minio.local` | +| `apiIngress.path` | The Path to MinIO®. You may need to set this to '/*' in order to use this with ALB ingress controllers. | `/` | +| `apiIngress.pathType` | Ingress path type | `ImplementationSpecific` | +| `apiIngress.servicePort` | Service port to be used | `minio-api` | +| `apiIngress.annotations` | Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. | `{}` | +| `apiIngress.tls` | Enable TLS configuration for the hostname defined at `apiIngress.hostname` parameter | `false` | +| `apiIngress.selfSigned` | Create a TLS secret for this ingress record using self-signed certificates generated by Helm | `false` | +| `apiIngress.extraHosts` | The list of additional hostnames to be covered with this ingress record. | `[]` | +| `apiIngress.extraPaths` | Any additional paths that may need to be added to the ingress under the main host | `[]` | +| `apiIngress.extraTls` | The tls configuration for additional hostnames to be covered with this ingress record. | `[]` | +| `apiIngress.secrets` | If you're providing your own certificates, please use this to add the certificates as secrets | `[]` | +| `apiIngress.extraRules` | Additional rules to be covered with this ingress record | `[]` | +| `networkPolicy.enabled` | Enable creation of NetworkPolicy resources | `true` | +| `networkPolicy.allowExternal` | The Policy model to apply | `true` | +| `networkPolicy.allowExternalEgress` | Allow the pod to access any range of port and all destinations. | `true` | +| `networkPolicy.extraIngress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `networkPolicy.extraEgress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `networkPolicy.ingressNSMatchLabels` | Labels to match to allow traffic from other namespaces | `{}` | +| `networkPolicy.ingressNSPodMatchLabels` | Pod labels to match to allow traffic from other namespaces | `{}` | + +### Persistence parameters + +| Name | Description | Value | +| --------------------------- | -------------------------------------------------------------------------------------- | --------------------- | +| `persistence.enabled` | Enable MinIO® data persistence using PVC. If false, use emptyDir | `true` | +| `persistence.storageClass` | PVC Storage Class for MinIO® data volume | `""` | +| `persistence.mountPath` | Data volume mount path | `/bitnami/minio/data` | +| `persistence.accessModes` | PVC Access Modes for MinIO® data volume | `["ReadWriteOnce"]` | +| `persistence.size` | PVC Storage Request for MinIO® data volume | `8Gi` | +| `persistence.annotations` | Annotations for the PVC | `{}` | +| `persistence.existingClaim` | Name of an existing PVC to use (only in `standalone` mode) | `""` | +| `persistence.selector` | Configure custom selector for existing Persistent Volume. (only in `distributed` mode) | `{}` | + +### Volume Permissions parameters + +| Name | Description | Value | +| ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | +| `volumePermissions.enabled` | Enable init container that changes the owner and group of the persistent volume(s) mountpoint to `runAsUser:fsGroup` | `false` | +| `volumePermissions.image.registry` | Init container volume-permissions image registry | `REGISTRY_NAME` | +| `volumePermissions.image.repository` | Init container volume-permissions image repository | `REPOSITORY_NAME/os-shell` | +| `volumePermissions.image.digest` | Init container volume-permissions image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `volumePermissions.image.pullPolicy` | Init container volume-permissions image pull policy | `IfNotPresent` | +| `volumePermissions.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `volumePermissions.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if volumePermissions.resources is set (volumePermissions.resources is recommended for production). | `nano` | +| `volumePermissions.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `volumePermissions.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `volumePermissions.containerSecurityContext.runAsUser` | User ID for the init container | `0` | + +### RBAC parameters + +| Name | Description | Value | +| --------------------------------------------- | ----------------------------------------------------------- | ------- | +| `serviceAccount.create` | Enable the creation of a ServiceAccount for MinIO® pods | `true` | +| `serviceAccount.name` | Name of the created ServiceAccount | `""` | +| `serviceAccount.automountServiceAccountToken` | Enable/disable auto mounting of the service account token | `false` | +| `serviceAccount.annotations` | Custom annotations for MinIO® ServiceAccount | `{}` | + +### Other parameters + +| Name | Description | Value | +| -------------------- | --------------------------------------------------------------------------------- | ------ | +| `pdb.create` | Enable/disable a Pod Disruption Budget creation | `true` | +| `pdb.minAvailable` | Minimum number/percentage of pods that must still be available after the eviction | `""` | +| `pdb.maxUnavailable` | Maximum number/percentage of pods that may be made unavailable after the eviction | `""` | + +### Metrics parameters + +| Name | Description | Value | +| ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | +| `metrics.prometheusAuthType` | Authentication mode for Prometheus (`jwt` or `public`) | `public` | +| `metrics.enabled` | Enable the export of Prometheus metrics | `false` | +| `metrics.serviceMonitor.enabled` | If the operator is installed in your cluster, set to true to create a Service Monitor Entry | `false` | +| `metrics.serviceMonitor.namespace` | Namespace which Prometheus is running in | `""` | +| `metrics.serviceMonitor.labels` | Extra labels for the ServiceMonitor | `{}` | +| `metrics.serviceMonitor.jobLabel` | The name of the label on the target service to use as the job name in Prometheus | `""` | +| `metrics.serviceMonitor.paths` | HTTP paths to scrape for metrics | `["/minio/v2/metrics/cluster","/minio/v2/metrics/node"]` | +| `metrics.serviceMonitor.interval` | Interval at which metrics should be scraped | `30s` | +| `metrics.serviceMonitor.scrapeTimeout` | Specify the timeout after which the scrape is ended | `""` | +| `metrics.serviceMonitor.metricRelabelings` | MetricRelabelConfigs to apply to samples before ingestion | `[]` | +| `metrics.serviceMonitor.relabelings` | Metrics relabelings to add to the scrape endpoint, applied before scraping | `[]` | +| `metrics.serviceMonitor.honorLabels` | Specify honorLabels parameter to add the scrape endpoint | `false` | +| `metrics.serviceMonitor.selector` | Prometheus instance selector labels | `{}` | +| `metrics.serviceMonitor.apiVersion` | ApiVersion for the serviceMonitor Resource (defaults to "monitoring.coreos.com/v1") | `""` | +| `metrics.serviceMonitor.tlsConfig` | Additional TLS configuration for metrics endpoint with "https" scheme | `{}` | +| `metrics.prometheusRule.enabled` | Create a Prometheus Operator PrometheusRule (also requires `metrics.enabled` to be `true` and `metrics.prometheusRule.rules`) | `false` | +| `metrics.prometheusRule.namespace` | Namespace for the PrometheusRule Resource (defaults to the Release Namespace) | `""` | +| `metrics.prometheusRule.additionalLabels` | Additional labels that can be used so PrometheusRule will be discovered by Prometheus | `{}` | +| `metrics.prometheusRule.rules` | Prometheus Rule definitions | `[]` | + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +helm install my-release \ + --set auth.rootUser=minio-admin \ + --set auth.rootPassword=minio-secret-password \ + oci://REGISTRY_NAME/REPOSITORY_NAME/minio +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The above command sets the MinIO® Server root user and password to `minio-admin` and `minio-secret-password`, respectively. + +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 oci://REGISTRY_NAME/REPOSITORY_NAME/minio +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> **Tip**: You can use the default [values.yaml](https://github.com/bitnami/charts/tree/main/bitnami/minio/values.yaml) + +## Troubleshooting + +Find more information about how to deal with common errors related to Bitnami's Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues). + +## Upgrading + +### To 14.9.0 + +This version introduces image verification for security purposes. To disable it, set `global.security.allowInsecureImages` to `true`. More details at [GitHub issue](https://github.com/bitnami/charts/issues/30850). + +### To 14.0.0 + +This major bump changes the following security defaults: + +- `runAsGroup` is changed from `0` to `1001` +- `readOnlyRootFilesystem` is set to `true` +- `resourcesPreset` is changed from `none` to the minimum size working in our test suites (NOTE: `resourcesPreset` is not meant for production usage, but `resources` adapted to your use case). +- `global.compatibility.openshift.adaptSecurityContext` is changed from `disabled` to `auto`. + +This could potentially break any customization or init scripts used in your deployment. If this is the case, change the default values to the previous ones. + +### To 12.0.0 + +This version updates MinIO® to major version 2023. All gateway features have been removed from Minio since upstream completely dropped this feature. The related options have been removed in version 12.1.0. + +### To 11.0.0 + +This version deprecates the usage of `MINIO_ACCESS_KEY` and `MINIO_SECRET_KEY` environment variables in MINIO® container in favor of `MINIO_ROOT_USER` and `MINIO_ROOT_PASSWORD`. + +If you were already using the new variables, no issues are expected during upgrade. + +### To 9.0.0 + +This version updates MinIO® authentication parameters so they're aligned with the [current terminology](https://docs.min.io/minio/baremetal/security/minio-identity-management/user-management.html#minio-users-root). As a result the following parameters have been affected: + +- `accessKey.password` has been renamed to `auth.rootUser`. +- `secretKey.password` has been renamed to `auth.rootPassword`. +- `accessKey.forcePassword` and `secretKey.forcePassword` have been unified into `auth.forcePassword`. +- `existingSecret`, `useCredentialsFile` and `forceNewKeys` have been renamed to `auth.existingSecret`, `auth.useCredentialsFiles` and `forceNewKeys`, respectively. + +### To 8.0.0 + +This version updates MinIO® after some major changes, affecting its Web UI. MinIO® has replaced its MinIO® Browser with the MinIO® Console, and Web UI has been moved to a separated port. As a result the following variables have been affected: + +- `service.port` has been slit into `service.ports.api` (default: 9000) and `service.ports.console` (default: 9001). +- `containerPort` has been slit into `containerPorts.api` (default: 9000) and `containerPort.console` (default: 9001). +- `service.nodePort`has been slit into `service.nodePorts.api` and `service.nodePorts.console`. +- Service port `minio` has been replaced with `minio-api` and `minio-console` with target ports minio-api and minio-console respectively. +- Liveness, readiness and startup probes now use port `minio-console` instead of `minio`. + +Please note that Web UI, previously running on port 9000 will now use port 9001 leaving port 9000 for the MinIO® Server API. + +### To 7.0.0 + +This version introduces pod and container securityContext support. The previous configuration of `securityContext` has moved to `podSecurityContext` and `containerSecurityContext`. Apart from this case, no issues are expected to appear when upgrading. + +### To 5.0.0 + +This version standardizes the way of defining Ingress rules. When configuring a single hostname for the Ingress rule, set the `ingress.hostname` value. When defining more than one, set the `ingress.extraHosts` array. Apart from this case, no issues are expected to appear when upgrading. + +### To 4.1.0 + +This version introduces `bitnami/common`, a [library chart](https://helm.sh/docs/topics/library_charts/#helm) as a dependency. More documentation about this new utility could be found [here](https://github.com/bitnami/charts/tree/main/bitnami/common#bitnami-common-library-chart). Please, make sure that you have updated the chart dependencies before executing any upgrade. + +### To 4.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +#### What changes were introduced in this major version? + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts + +#### Considerations when upgrading to this version + +- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues +- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore +- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 + +#### Useful links + +- +- +- + +## License + +Copyright © 2025 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/backing-services/minio/charts/common/.helmignore b/backing-services/minio/charts/common/.helmignore new file mode 100644 index 0000000..d0e1084 --- /dev/null +++ b/backing-services/minio/charts/common/.helmignore @@ -0,0 +1,26 @@ +# 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 +.vscode/ +# img folder +img/ +# Changelog +CHANGELOG.md diff --git a/backing-services/minio/charts/common/Chart.yaml b/backing-services/minio/charts/common/Chart.yaml new file mode 100644 index 0000000..10fc86a --- /dev/null +++ b/backing-services/minio/charts/common/Chart.yaml @@ -0,0 +1,23 @@ +annotations: + category: Infrastructure + licenses: Apache-2.0 +apiVersion: v2 +appVersion: 2.30.0 +description: A Library Helm Chart for grouping common logic between bitnami charts. + This chart is not deployable by itself. +home: https://bitnami.com +icon: https://dyltqmyl993wv.cloudfront.net/downloads/logos/bitnami-mark.png +keywords: +- common +- helper +- template +- function +- bitnami +maintainers: +- name: Broadcom, Inc. All Rights Reserved. + url: https://github.com/bitnami/charts +name: common +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/common +type: library +version: 2.30.0 diff --git a/backing-services/minio/charts/common/README.md b/backing-services/minio/charts/common/README.md new file mode 100644 index 0000000..0e5f649 --- /dev/null +++ b/backing-services/minio/charts/common/README.md @@ -0,0 +1,235 @@ +# Bitnami Common Library Chart + +A [Helm Library Chart](https://helm.sh/docs/topics/library_charts/#helm) for grouping common logic between Bitnami charts. + +## TL;DR + +```yaml +dependencies: + - name: common + version: 2.x.x + repository: oci://registry-1.docker.io/bitnamicharts +``` + +```console +helm dependency update +``` + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "common.names.fullname" . }} +data: + myvalue: "Hello World" +``` + +Looking to use our applications in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the commercial edition of the Bitnami catalog. + +## Introduction + +This chart provides a common template helpers which can be used to develop new charts using [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ + +## Parameters + +## Special input schemas + +### ImageRoot + +```yaml +registry: + type: string + description: Docker registry where the image is located + example: docker.io + +repository: + type: string + description: Repository and image name + example: bitnami/nginx + +tag: + type: string + description: image tag + example: 1.16.1-debian-10-r63 + +pullPolicy: + type: string + description: Specify a imagePullPolicy.' + +pullSecrets: + type: array + items: + type: string + description: Optionally specify an array of imagePullSecrets (evaluated as templates). + +debug: + type: boolean + description: Set to true if you would like to see extra information on logs + example: false + +## An instance would be: +# registry: docker.io +# repository: bitnami/nginx +# tag: 1.16.1-debian-10-r63 +# pullPolicy: IfNotPresent +# debug: false +``` + +### Persistence + +```yaml +enabled: + type: boolean + description: Whether enable persistence. + example: true + +storageClass: + type: string + description: Ghost data Persistent Volume Storage Class, If set to "-", storageClassName: "" which disables dynamic provisioning. + example: "-" + +accessMode: + type: string + description: Access mode for the Persistent Volume Storage. + example: ReadWriteOnce + +size: + type: string + description: Size the Persistent Volume Storage. + example: 8Gi + +path: + type: string + description: Path to be persisted. + example: /bitnami + +## An instance would be: +# enabled: true +# storageClass: "-" +# accessMode: ReadWriteOnce +# size: 8Gi +# path: /bitnami +``` + +### ExistingSecret + +```yaml +name: + type: string + description: Name of the existing secret. + example: mySecret +keyMapping: + description: Mapping between the expected key name and the name of the key in the existing secret. + type: object + +## An instance would be: +# name: mySecret +# keyMapping: +# password: myPasswordKey +``` + +#### Example of use + +When we store sensitive data for a deployment in a secret, some times we want to give to users the possibility of using theirs existing secrets. + +```yaml +# templates/secret.yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }} + labels: + app: {{ include "common.names.fullname" . }} +type: Opaque +data: + password: {{ .Values.password | b64enc | quote }} + +# templates/dpl.yaml +--- +... + env: + - name: PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "common.secrets.name" (dict "existingSecret" .Values.existingSecret "context" $) }} + key: {{ include "common.secrets.key" (dict "existingSecret" .Values.existingSecret "key" "password") }} +... + +# values.yaml +--- +name: mySecret +keyMapping: + password: myPasswordKey +``` + +### ValidateValue + +#### NOTES.txt + +```console +{{- $validateValueConf00 := (dict "valueKey" "path.to.value00" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value01" "secret" "secretName" "field" "password-01") -}} + +{{ include "common.validations.values.multiple.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} +``` + +If we force those values to be empty we will see some alerts + +```console +helm install test mychart --set path.to.value00="",path.to.value01="" + 'path.to.value00' must not be empty, please add '--set path.to.value00=$PASSWORD_00' to the command. To get the current value: + + export PASSWORD_00=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-00}" | base64 -d) + + 'path.to.value01' must not be empty, please add '--set path.to.value01=$PASSWORD_01' to the command. To get the current value: + + export PASSWORD_01=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-01}" | base64 -d) +``` + +## Upgrading + +### To 1.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +#### What changes were introduced in this major version? + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- Use `type: library`. [Here](https://v3.helm.sh/docs/faq/#library-chart-support) you can find more information. +- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts + +#### Considerations when upgrading to this version + +- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues +- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore +- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 + +#### Useful links + +- +- +- + +## License + +Copyright © 2025 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/backing-services/minio/charts/common/templates/_affinities.tpl b/backing-services/minio/charts/common/templates/_affinities.tpl new file mode 100644 index 0000000..d387dbe --- /dev/null +++ b/backing-services/minio/charts/common/templates/_affinities.tpl @@ -0,0 +1,155 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a soft nodeAffinity definition +{{ include "common.affinities.nodes.soft" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.soft" -}} +preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} + weight: 1 +{{- end -}} + +{{/* +Return a hard nodeAffinity definition +{{ include "common.affinities.nodes.hard" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.hard" -}} +requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} +{{- end -}} + +{{/* +Return a nodeAffinity definition +{{ include "common.affinities.nodes" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.nodes.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.nodes.hard" . -}} + {{- end -}} +{{- end -}} + +{{/* +Return a topologyKey definition +{{ include "common.affinities.topologyKey" (dict "topologyKey" "BAR") -}} +*/}} +{{- define "common.affinities.topologyKey" -}} +{{ .topologyKey | default "kubernetes.io/hostname" -}} +{{- end -}} + +{{/* +Return a soft podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.soft" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "extraNamespaces" (list "namespace1" "namespace2") "context" $) -}} +*/}} +{{- define "common.affinities.pods.soft" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +{{- $extraNamespaces := default (list) .extraNamespaces -}} +preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if $extraNamespaces }} + namespaces: + - {{ .context.Release.Namespace }} + {{- with $extraNamespaces }} + {{ include "common.tplvalues.render" (dict "value" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: 1 + {{- range $extraPodAffinityTerms }} + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: {{ .weight | default 1 -}} + {{- end -}} +{{- end -}} + +{{/* +Return a hard podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.hard" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "extraNamespaces" (list "namespace1" "namespace2") "context" $) -}} +*/}} +{{- define "common.affinities.pods.hard" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +{{- $extraNamespaces := default (list) .extraNamespaces -}} +requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if $extraNamespaces }} + namespaces: + - {{ .context.Release.Namespace }} + {{- with $extraNamespaces }} + {{ include "common.tplvalues.render" (dict "value" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- range $extraPodAffinityTerms }} + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- end -}} +{{- end -}} + +{{/* +Return a podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.pods" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.pods.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.pods.hard" . -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/minio/charts/common/templates/_capabilities.tpl b/backing-services/minio/charts/common/templates/_capabilities.tpl new file mode 100644 index 0000000..6423fb1 --- /dev/null +++ b/backing-services/minio/charts/common/templates/_capabilities.tpl @@ -0,0 +1,253 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the target Kubernetes version +*/}} +{{- define "common.capabilities.kubeVersion" -}} +{{- default (default .Capabilities.KubeVersion.Version .Values.kubeVersion) ((.Values.global).kubeVersion) -}} +{{- end -}} + +{{/* +Return true if the apiVersion is supported +Usage: +{{ include "common.capabilities.apiVersions.has" (dict "version" "batch/v1" "context" $) }} +*/}} +{{- define "common.capabilities.apiVersions.has" -}} +{{- $providedAPIVersions := default .context.Values.apiVersions ((.context.Values.global).apiVersions) -}} +{{- if and (empty $providedAPIVersions) (.context.Capabilities.APIVersions.Has .version) -}} + {{- true -}} +{{- else if has .version $providedAPIVersions -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for poddisruptionbudget. +*/}} +{{- define "common.capabilities.policy.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.21-0" $kubeVersion) -}} +{{- print "policy/v1beta1" -}} +{{- else -}} +{{- print "policy/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "common.capabilities.networkPolicy.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.7-0" $kubeVersion) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for job. +*/}} +{{- define "common.capabilities.job.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.21-0" $kubeVersion) -}} +{{- print "batch/v1beta1" -}} +{{- else -}} +{{- print "batch/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for cronjob. +*/}} +{{- define "common.capabilities.cronjob.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.21-0" $kubeVersion) -}} +{{- print "batch/v1beta1" -}} +{{- else -}} +{{- print "batch/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for daemonset. +*/}} +{{- define "common.capabilities.daemonset.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.14-0" $kubeVersion) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for deployment. +*/}} +{{- define "common.capabilities.deployment.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.14-0" $kubeVersion) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for statefulset. +*/}} +{{- define "common.capabilities.statefulset.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.14-0" $kubeVersion) -}} +{{- print "apps/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "common.capabilities.ingress.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if (.Values.ingress).apiVersion -}} +{{- .Values.ingress.apiVersion -}} +{{- else if and (not (empty $kubeVersion)) (semverCompare "<1.14-0" $kubeVersion) -}} +{{- print "extensions/v1beta1" -}} +{{- else if and (not (empty $kubeVersion)) (semverCompare "<1.19-0" $kubeVersion) -}} +{{- print "networking.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end }} +{{- end -}} + +{{/* +Return the appropriate apiVersion for RBAC resources. +*/}} +{{- define "common.capabilities.rbac.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.17-0" $kubeVersion) -}} +{{- print "rbac.authorization.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "rbac.authorization.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for CRDs. +*/}} +{{- define "common.capabilities.crd.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.19-0" $kubeVersion) -}} +{{- print "apiextensions.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiextensions.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for APIService. +*/}} +{{- define "common.capabilities.apiService.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.10-0" $kubeVersion) -}} +{{- print "apiregistration.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiregistration.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Horizontal Pod Autoscaler. +*/}} +{{- define "common.capabilities.hpa.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" .context -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.23-0" $kubeVersion) -}} +{{- if .beta2 -}} +{{- print "autoscaling/v2beta2" -}} +{{- else -}} +{{- print "autoscaling/v2beta1" -}} +{{- end -}} +{{- else -}} +{{- print "autoscaling/v2" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Vertical Pod Autoscaler. +*/}} +{{- define "common.capabilities.vpa.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" .context -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.11-0" $kubeVersion) -}} +{{- print "autoscaling/v1beta1" -}} +{{- else if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "autoscaling/v1beta2" -}} +{{- else -}} +{{- print "autoscaling/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if PodSecurityPolicy is supported +*/}} +{{- define "common.capabilities.psp.supported" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if or (empty $kubeVersion) (semverCompare "<1.25-0" $kubeVersion) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if AdmissionConfiguration is supported +*/}} +{{- define "common.capabilities.admissionConfiguration.supported" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if or (empty $kubeVersion) (not (semverCompare "<1.23-0" $kubeVersion)) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for AdmissionConfiguration. +*/}} +{{- define "common.capabilities.admissionConfiguration.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.23-0" $kubeVersion) -}} +{{- print "apiserver.config.k8s.io/v1alpha1" -}} +{{- else if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "apiserver.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiserver.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for PodSecurityConfiguration. +*/}} +{{- define "common.capabilities.podSecurityConfiguration.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.23-0" $kubeVersion) -}} +{{- print "pod-security.admission.config.k8s.io/v1alpha1" -}} +{{- else if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "pod-security.admission.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "pod-security.admission.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the used Helm version is 3.3+. +A way to check the used Helm version was not introduced until version 3.3.0 with .Capabilities.HelmVersion, which contains an additional "{}}" structure. +This check is introduced as a regexMatch instead of {{ if .Capabilities.HelmVersion }} because checking for the key HelmVersion in <3.3 results in a "interface not found" error. +**To be removed when the catalog's minimun Helm version is 3.3** +*/}} +{{- define "common.capabilities.supportsHelmVersion" -}} +{{- if regexMatch "{(v[0-9])*[^}]*}}$" (.Capabilities | toString ) }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/minio/charts/common/templates/_compatibility.tpl b/backing-services/minio/charts/common/templates/_compatibility.tpl new file mode 100644 index 0000000..19c26db --- /dev/null +++ b/backing-services/minio/charts/common/templates/_compatibility.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return true if the detected platform is Openshift +Usage: +{{- include "common.compatibility.isOpenshift" . -}} +*/}} +{{- define "common.compatibility.isOpenshift" -}} +{{- if .Capabilities.APIVersions.Has "security.openshift.io/v1" -}} +{{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Render a compatible securityContext depending on the platform. By default it is maintained as it is. In other platforms like Openshift we remove default user/group values that do not work out of the box with the restricted-v1 SCC +Usage: +{{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) -}} +*/}} +{{- define "common.compatibility.renderSecurityContext" -}} +{{- $adaptedContext := .secContext -}} + +{{- if (((.context.Values.global).compatibility).openshift) -}} + {{- if or (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "force") (and (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "auto") (include "common.compatibility.isOpenshift" .context)) -}} + {{/* Remove incompatible user/group values that do not work in Openshift out of the box */}} + {{- $adaptedContext = omit $adaptedContext "fsGroup" "runAsUser" "runAsGroup" -}} + {{- if not .secContext.seLinuxOptions -}} + {{/* If it is an empty object, we remove it from the resulting context because it causes validation issues */}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{/* Remove empty seLinuxOptions object if global.compatibility.omitEmptySeLinuxOptions is set to true */}} +{{- if and (((.context.Values.global).compatibility).omitEmptySeLinuxOptions) (not .secContext.seLinuxOptions) -}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} +{{- end -}} +{{/* Remove fields that are disregarded when running the container in privileged mode */}} +{{- if $adaptedContext.privileged -}} + {{- $adaptedContext = omit $adaptedContext "capabilities" -}} +{{- end -}} +{{- omit $adaptedContext "enabled" | toYaml -}} +{{- end -}} diff --git a/backing-services/minio/charts/common/templates/_errors.tpl b/backing-services/minio/charts/common/templates/_errors.tpl new file mode 100644 index 0000000..93f3ffc --- /dev/null +++ b/backing-services/minio/charts/common/templates/_errors.tpl @@ -0,0 +1,85 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Throw error when upgrading using empty passwords values that must not be empty. + +Usage: +{{- $validationError00 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password00" "secret" "secretName" "field" "password-00") -}} +{{- $validationError01 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password01" "secret" "secretName" "field" "password-01") -}} +{{ include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $validationError00 $validationError01) "context" $) }} + +Required password params: + - validationErrors - String - Required. List of validation strings to be return, if it is empty it won't throw error. + - context - Context - Required. Parent context. +*/}} +{{- define "common.errors.upgrade.passwords.empty" -}} + {{- $validationErrors := join "" .validationErrors -}} + {{- if and $validationErrors .context.Release.IsUpgrade -}} + {{- $errorString := "\nPASSWORDS ERROR: You must provide your current passwords when upgrading the release." -}} + {{- $errorString = print $errorString "\n Note that even after reinstallation, old credentials may be needed as they may be kept in persistent volume claims." -}} + {{- $errorString = print $errorString "\n Further information can be obtained at https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues/#credential-errors-while-upgrading-chart-releases" -}} + {{- $errorString = print $errorString "\n%s" -}} + {{- printf $errorString $validationErrors | fail -}} + {{- end -}} +{{- end -}} + +{{/* +Throw error when original container images are replaced. +The error can be bypassed by setting the "global.security.allowInsecureImages" to true. In this case, +a warning message will be shown instead. + +Usage: +{{ include "common.errors.insecureImages" (dict "images" (list .Values.path.to.the.imageRoot) "context" $) }} +*/}} +{{- define "common.errors.insecureImages" -}} +{{- $relocatedImages := list -}} +{{- $replacedImages := list -}} +{{- $retaggedImages := list -}} +{{- $globalRegistry := ((.context.Values.global).imageRegistry) -}} +{{- $originalImages := .context.Chart.Annotations.images -}} +{{- range .images -}} + {{- $registryName := default .registry $globalRegistry -}} + {{- $fullImageNameNoTag := printf "%s/%s" $registryName .repository -}} + {{- $fullImageName := printf "%s:%s" $fullImageNameNoTag .tag -}} + {{- if not (contains $fullImageNameNoTag $originalImages) -}} + {{- if not (contains $registryName $originalImages) -}} + {{- $relocatedImages = append $relocatedImages $fullImageName -}} + {{- else if not (contains .repository $originalImages) -}} + {{- $replacedImages = append $replacedImages $fullImageName -}} + {{- end -}} + {{- end -}} + {{- if not (contains (printf "%s:%s" .repository .tag) $originalImages) -}} + {{- $retaggedImages = append $retaggedImages $fullImageName -}} + {{- end -}} +{{- end -}} + +{{- if and (or (gt (len $relocatedImages) 0) (gt (len $replacedImages) 0)) (((.context.Values.global).security).allowInsecureImages) -}} + {{- print "\n\n⚠ SECURITY WARNING: Verifying original container images was skipped. Please note this Helm chart was designed, tested, and validated on multiple platforms using a specific set of Bitnami and Tanzu Application Catalog containers. Substituting other containers is likely to cause degraded security and performance, broken chart features, and missing environment variables.\n" -}} +{{- else if (or (gt (len $relocatedImages) 0) (gt (len $replacedImages) 0)) -}} + {{- $errorString := "Original containers have been substituted for unrecognized ones. Deploying this chart with non-standard containers is likely to cause degraded security and performance, broken chart features, and missing environment variables." -}} + {{- $errorString = print $errorString "\n\nUnrecognized images:" -}} + {{- range (concat $relocatedImages $replacedImages) -}} + {{- $errorString = print $errorString "\n - " . -}} + {{- end -}} + {{- if or (contains "docker.io/bitnami/" $originalImages) (contains "docker.io/bitnamiprem/" $originalImages) -}} + {{- $errorString = print "\n\n⚠ ERROR: " $errorString -}} + {{- $errorString = print $errorString "\n\nIf you are sure you want to proceed with non-standard containers, you can skip container image verification by setting the global parameter 'global.security.allowInsecureImages' to true." -}} + {{- $errorString = print $errorString "\nFurther information can be obtained at https://github.com/bitnami/charts/issues/30850" -}} + {{- print $errorString | fail -}} + {{- else if gt (len $replacedImages) 0 -}} + {{- $errorString = print "\n\n⚠ WARNING: " $errorString -}} + {{- print $errorString -}} + {{- end -}} +{{- else if gt (len $retaggedImages) 0 -}} + {{- $warnString := "\n\n⚠ WARNING: Original containers have been retagged. Please note this Helm chart was tested, and validated on multiple platforms using a specific set of Tanzu Application Catalog containers. Substituting original image tags could cause unexpected behavior." -}} + {{- $warnString = print $warnString "\n\nRetagged images:" -}} + {{- range $retaggedImages -}} + {{- $warnString = print $warnString "\n - " . -}} + {{- end -}} + {{- print $warnString -}} +{{- end -}} +{{- end -}} \ No newline at end of file diff --git a/backing-services/minio/charts/common/templates/_images.tpl b/backing-services/minio/charts/common/templates/_images.tpl new file mode 100644 index 0000000..76bb7ce --- /dev/null +++ b/backing-services/minio/charts/common/templates/_images.tpl @@ -0,0 +1,115 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Return the proper image name. +If image tag and digest are not defined, termination fallbacks to chart appVersion. +{{ include "common.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" .Values.global "chart" .Chart ) }} +*/}} +{{- define "common.images.image" -}} +{{- $registryName := default .imageRoot.registry ((.global).imageRegistry) -}} +{{- $repositoryName := .imageRoot.repository -}} +{{- $separator := ":" -}} +{{- $termination := .imageRoot.tag | toString -}} + +{{- if not .imageRoot.tag }} + {{- if .chart }} + {{- $termination = .chart.AppVersion | toString -}} + {{- end -}} +{{- end -}} +{{- if .imageRoot.digest }} + {{- $separator = "@" -}} + {{- $termination = .imageRoot.digest | toString -}} +{{- end -}} +{{- if $registryName }} + {{- printf "%s/%s%s%s" $registryName $repositoryName $separator $termination -}} +{{- else -}} + {{- printf "%s%s%s" $repositoryName $separator $termination -}} +{{- end -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead) +{{ include "common.images.pullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global) }} +*/}} +{{- define "common.images.pullSecrets" -}} + {{- $pullSecrets := list }} + + {{- range ((.global).imagePullSecrets) -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end }} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) -}} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names evaluating values as templates +{{ include "common.images.renderPullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $) }} +*/}} +{{- define "common.images.renderPullSecrets" -}} + {{- $pullSecrets := list }} + {{- $context := .context }} + + {{- range (($context.Values.global).imagePullSecrets) -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) -}} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper image version (ingores image revision/prerelease info & fallbacks to chart appVersion) +{{ include "common.images.version" ( dict "imageRoot" .Values.path.to.the.image "chart" .Chart ) }} +*/}} +{{- define "common.images.version" -}} +{{- $imageTag := .imageRoot.tag | toString -}} +{{/* regexp from https://github.com/Masterminds/semver/blob/23f51de38a0866c5ef0bfc42b3f735c73107b700/version.go#L41-L44 */}} +{{- if regexMatch `^([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?$` $imageTag -}} + {{- $version := semver $imageTag -}} + {{- printf "%d.%d.%d" $version.Major $version.Minor $version.Patch -}} +{{- else -}} + {{- print .chart.AppVersion -}} +{{- end -}} +{{- end -}} + diff --git a/backing-services/minio/charts/common/templates/_ingress.tpl b/backing-services/minio/charts/common/templates/_ingress.tpl new file mode 100644 index 0000000..7d2b879 --- /dev/null +++ b/backing-services/minio/charts/common/templates/_ingress.tpl @@ -0,0 +1,73 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Generate backend entry that is compatible with all Kubernetes API versions. + +Usage: +{{ include "common.ingress.backend" (dict "serviceName" "backendName" "servicePort" "backendPort" "context" $) }} + +Params: + - serviceName - String. Name of an existing service backend + - servicePort - String/Int. Port name (or number) of the service. It will be translated to different yaml depending if it is a string or an integer. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.ingress.backend" -}} +{{- $apiVersion := (include "common.capabilities.ingress.apiVersion" .context) -}} +{{- if or (eq $apiVersion "extensions/v1beta1") (eq $apiVersion "networking.k8s.io/v1beta1") -}} +serviceName: {{ .serviceName }} +servicePort: {{ .servicePort }} +{{- else -}} +service: + name: {{ .serviceName }} + port: + {{- if typeIs "string" .servicePort }} + name: {{ .servicePort }} + {{- else if or (typeIs "int" .servicePort) (typeIs "float64" .servicePort) }} + number: {{ .servicePort | int }} + {{- end }} +{{- end -}} +{{- end -}} + +{{/* +Print "true" if the API pathType field is supported +Usage: +{{ include "common.ingress.supportsPathType" . }} +*/}} +{{- define "common.ingress.supportsPathType" -}} +{{- if (semverCompare "<1.18-0" (include "common.capabilities.kubeVersion" .)) -}} +{{- print "false" -}} +{{- else -}} +{{- print "true" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the ingressClassname field is supported +Usage: +{{ include "common.ingress.supportsIngressClassname" . }} +*/}} +{{- define "common.ingress.supportsIngressClassname" -}} +{{- if semverCompare "<1.18-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "false" -}} +{{- else -}} +{{- print "true" -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if cert-manager required annotations for TLS signed +certificates are set in the Ingress annotations +Ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations +Usage: +{{ include "common.ingress.certManagerRequest" ( dict "annotations" .Values.path.to.the.ingress.annotations ) }} +*/}} +{{- define "common.ingress.certManagerRequest" -}} +{{ if or (hasKey .annotations "cert-manager.io/cluster-issuer") (hasKey .annotations "cert-manager.io/issuer") (hasKey .annotations "kubernetes.io/tls-acme") }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/minio/charts/common/templates/_labels.tpl b/backing-services/minio/charts/common/templates/_labels.tpl new file mode 100644 index 0000000..0a0cc54 --- /dev/null +++ b/backing-services/minio/charts/common/templates/_labels.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Kubernetes standard labels +{{ include "common.labels.standard" (dict "customLabels" .Values.commonLabels "context" $) -}} +*/}} +{{- define "common.labels.standard" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{- $default := dict "app.kubernetes.io/name" (include "common.names.name" .context) "helm.sh/chart" (include "common.names.chart" .context) "app.kubernetes.io/instance" .context.Release.Name "app.kubernetes.io/managed-by" .context.Release.Service -}} +{{- with .context.Chart.AppVersion -}} +{{- $_ := set $default "app.kubernetes.io/version" . -}} +{{- end -}} +{{ template "common.tplvalues.merge" (dict "values" (list .customLabels $default) "context" .context) }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +helm.sh/chart: {{ include "common.names.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Chart.AppVersion }} +app.kubernetes.io/version: {{ . | quote }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Labels used on immutable fields such as deploy.spec.selector.matchLabels or svc.spec.selector +{{ include "common.labels.matchLabels" (dict "customLabels" .Values.podLabels "context" $) -}} + +We don't want to loop over custom labels appending them to the selector +since it's very likely that it will break deployments, services, etc. +However, it's important to overwrite the standard labels if the user +overwrote them on metadata.labels fields. +*/}} +{{- define "common.labels.matchLabels" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{ merge (pick (include "common.tplvalues.render" (dict "value" .customLabels "context" .context) | fromYaml) "app.kubernetes.io/name" "app.kubernetes.io/instance") (dict "app.kubernetes.io/name" (include "common.names.name" .context) "app.kubernetes.io/instance" .context.Release.Name ) | toYaml }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} +{{- end -}} diff --git a/backing-services/minio/charts/common/templates/_names.tpl b/backing-services/minio/charts/common/templates/_names.tpl new file mode 100644 index 0000000..ba83956 --- /dev/null +++ b/backing-services/minio/charts/common/templates/_names.tpl @@ -0,0 +1,71 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "common.names.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "common.names.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "common.names.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 dependency name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +Usage: +{{ include "common.names.dependency.fullname" (dict "chartName" "dependency-chart-name" "chartValues" .Values.dependency-chart "context" $) }} +*/}} +{{- define "common.names.dependency.fullname" -}} +{{- if .chartValues.fullnameOverride -}} +{{- .chartValues.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .chartName .chartValues.nameOverride -}} +{{- if contains $name .context.Release.Name -}} +{{- .context.Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .context.Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts. +*/}} +{{- define "common.names.namespace" -}} +{{- default .Release.Namespace .Values.namespaceOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a fully qualified app name adding the installation's namespace. +*/}} +{{- define "common.names.fullname.namespace" -}} +{{- printf "%s-%s" (include "common.names.fullname" .) (include "common.names.namespace" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/backing-services/minio/charts/common/templates/_resources.tpl b/backing-services/minio/charts/common/templates/_resources.tpl new file mode 100644 index 0000000..d8a43e1 --- /dev/null +++ b/backing-services/minio/charts/common/templates/_resources.tpl @@ -0,0 +1,50 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a resource request/limit object based on a given preset. +These presets are for basic testing and not meant to be used in production +{{ include "common.resources.preset" (dict "type" "nano") -}} +*/}} +{{- define "common.resources.preset" -}} +{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} +{{- $presets := dict + "nano" (dict + "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "2Gi") + ) + "micro" (dict + "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "2Gi") + ) + "small" (dict + "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "2Gi") + ) + "medium" (dict + "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "2Gi") + ) + "large" (dict + "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "2Gi") + ) + "xlarge" (dict + "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "2Gi") + ) + "2xlarge" (dict + "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "2Gi") + ) + }} +{{- if hasKey $presets .type -}} +{{- index $presets .type | toYaml -}} +{{- else -}} +{{- printf "ERROR: Preset key '%s' invalid. Allowed values are %s" .type (join "," (keys $presets)) | fail -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/minio/charts/common/templates/_secrets.tpl b/backing-services/minio/charts/common/templates/_secrets.tpl new file mode 100644 index 0000000..bfef469 --- /dev/null +++ b/backing-services/minio/charts/common/templates/_secrets.tpl @@ -0,0 +1,192 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Generate secret name. + +Usage: +{{ include "common.secrets.name" (dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $) }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - defaultNameSuffix - String - Optional. It is used only if we have several secrets in the same deployment. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.secrets.name" -}} +{{- $name := (include "common.names.fullname" .context) -}} + +{{- if .defaultNameSuffix -}} +{{- $name = printf "%s-%s" $name .defaultNameSuffix | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- with .existingSecret -}} +{{- if not (typeIs "string" .) -}} +{{- with .name -}} +{{- $name = . -}} +{{- end -}} +{{- else -}} +{{- $name = . -}} +{{- end -}} +{{- end -}} + +{{- printf "%s" $name -}} +{{- end -}} + +{{/* +Generate secret key. + +Usage: +{{ include "common.secrets.key" (dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName") }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - key - String - Required. Name of the key in the secret. +*/}} +{{- define "common.secrets.key" -}} +{{- $key := .key -}} + +{{- if .existingSecret -}} + {{- if not (typeIs "string" .existingSecret) -}} + {{- if .existingSecret.keyMapping -}} + {{- $key = index .existingSecret.keyMapping $.key -}} + {{- end -}} + {{- end }} +{{- end -}} + +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Generate secret password or retrieve one if already created. + +Usage: +{{ include "common.secrets.passwords.manage" (dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "honorProvidedValues" false "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - providedValues - List - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - length - int - Optional - Length of the generated random password. + - strong - Boolean - Optional - Whether to add symbols to the generated random password. + - chartName - String - Optional - Name of the chart used when said chart is deployed as a subchart. + - context - Context - Required - Parent context. + - failOnNew - Boolean - Optional - Default to true. If set to false, skip errors adding new keys to existing secrets. + - skipB64enc - Boolean - Optional - Default to false. If set to true, no the secret will not be base64 encrypted. + - skipQuote - Boolean - Optional - Default to false. If set to true, no quotes will be added around the secret. + - honorProvidedValues - Boolean - Optional - Default to false. If set to true, the values in providedValues have higher priority than an existing secret +The order in which this function returns a secret password: + 1. Password provided via the values.yaml if honorProvidedValues = true + (If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned) + 2. Already existing 'Secret' resource + (If a 'Secret' resource is found under the name provided to the 'secret' parameter to this function and that 'Secret' resource contains a key with the name passed as the 'key' parameter to this function then the value of this existing secret password will be returned) + 3. Password provided via the values.yaml if honorProvidedValues = false + (If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned) + 4. Randomly generated secret password + (A new random secret password with the length specified in the 'length' parameter will be generated and returned) + +*/}} +{{- define "common.secrets.passwords.manage" -}} + +{{- $password := "" }} +{{- $subchart := "" }} +{{- $chartName := default "" .chartName }} +{{- $passwordLength := default 10 .length }} +{{- $providedPasswordKey := include "common.utils.getKeyFromList" (dict "keys" .providedValues "context" $.context) }} +{{- $providedPasswordValue := include "common.utils.getValueFromKey" (dict "key" $providedPasswordKey "context" $.context) }} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data }} +{{- if $secretData }} + {{- if hasKey $secretData .key }} + {{- $password = index $secretData .key | b64dec }} + {{- else if not (eq .failOnNew false) }} + {{- printf "\nPASSWORDS ERROR: The secret \"%s\" does not contain the key \"%s\"\n" .secret .key | fail -}} + {{- end -}} +{{- end }} + +{{- if and $providedPasswordValue .honorProvidedValues }} + {{- $password = $providedPasswordValue | toString }} +{{- end }} + +{{- if not $password }} + {{- if $providedPasswordValue }} + {{- $password = $providedPasswordValue | toString }} + {{- else }} + {{- if .context.Values.enabled }} + {{- $subchart = $chartName }} + {{- end -}} + + {{- if not (eq .failOnNew false) }} + {{- $requiredPassword := dict "valueKey" $providedPasswordKey "secret" .secret "field" .key "subchart" $subchart "context" $.context -}} + {{- $requiredPasswordError := include "common.validations.values.single.empty" $requiredPassword -}} + {{- $passwordValidationErrors := list $requiredPasswordError -}} + {{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" $passwordValidationErrors "context" $.context) -}} + {{- end }} + + {{- if .strong }} + {{- $subStr := list (lower (randAlpha 1)) (randNumeric 1) (upper (randAlpha 1)) | join "_" }} + {{- $password = randAscii $passwordLength }} + {{- $password = regexReplaceAllLiteral "\\W" $password "@" | substr 5 $passwordLength }} + {{- $password = printf "%s%s" $subStr $password | toString | shuffle }} + {{- else }} + {{- $password = randAlphaNum $passwordLength }} + {{- end }} + {{- end -}} +{{- end -}} +{{- if not .skipB64enc }} +{{- $password = $password | b64enc }} +{{- end -}} +{{- if .skipQuote -}} +{{- printf "%s" $password -}} +{{- else -}} +{{- printf "%s" $password | quote -}} +{{- end -}} +{{- end -}} + +{{/* +Reuses the value from an existing secret, otherwise sets its value to a default value. + +Usage: +{{ include "common.secrets.lookup" (dict "secret" "secret-name" "key" "keyName" "defaultValue" .Values.myValue "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - defaultValue - String - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - context - Context - Required - Parent context. + +*/}} +{{- define "common.secrets.lookup" -}} +{{- $value := "" -}} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data -}} +{{- if and $secretData (hasKey $secretData .key) -}} + {{- $value = index $secretData .key -}} +{{- else if .defaultValue -}} + {{- $value = .defaultValue | toString | b64enc -}} +{{- end -}} +{{- if $value -}} +{{- printf "%s" $value -}} +{{- end -}} +{{- end -}} + +{{/* +Returns whether a previous generated secret already exists + +Usage: +{{ include "common.secrets.exists" (dict "secret" "secret-name" "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - context - Context - Required - Parent context. +*/}} +{{- define "common.secrets.exists" -}} +{{- $secret := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret) }} +{{- if $secret }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/minio/charts/common/templates/_storage.tpl b/backing-services/minio/charts/common/templates/_storage.tpl new file mode 100644 index 0000000..aa75856 --- /dev/null +++ b/backing-services/minio/charts/common/templates/_storage.tpl @@ -0,0 +1,21 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the proper Storage Class +{{ include "common.storage.class" ( dict "persistence" .Values.path.to.the.persistence "global" $) }} +*/}} +{{- define "common.storage.class" -}} +{{- $storageClass := (.global).storageClass | default .persistence.storageClass | default (.global).defaultStorageClass | default "" -}} +{{- if $storageClass -}} + {{- if (eq "-" $storageClass) -}} + {{- printf "storageClassName: \"\"" -}} + {{- else -}} + {{- printf "storageClassName: %s" $storageClass -}} + {{- end -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/minio/charts/common/templates/_tplvalues.tpl b/backing-services/minio/charts/common/templates/_tplvalues.tpl new file mode 100644 index 0000000..a04f4c1 --- /dev/null +++ b/backing-services/minio/charts/common/templates/_tplvalues.tpl @@ -0,0 +1,52 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Renders a value that contains template perhaps with scope if the scope is present. +Usage: +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ ) }} +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ "scope" $app ) }} +*/}} +{{- define "common.tplvalues.render" -}} +{{- $value := typeIs "string" .value | ternary .value (.value | toYaml) }} +{{- if contains "{{" (toJson .value) }} + {{- if .scope }} + {{- tpl (cat "{{- with $.RelativeScope -}}" $value "{{- end }}") (merge (dict "RelativeScope" .scope) .context) }} + {{- else }} + {{- tpl $value .context }} + {{- end }} +{{- else }} + {{- $value }} +{{- end }} +{{- end -}} + +{{/* +Merge a list of values that contains template after rendering them. +Merge precedence is consistent with http://masterminds.github.io/sprig/dicts.html#merge-mustmerge +Usage: +{{ include "common.tplvalues.merge" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }} +*/}} +{{- define "common.tplvalues.merge" -}} +{{- $dst := dict -}} +{{- range .values -}} +{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | merge $dst -}} +{{- end -}} +{{ $dst | toYaml }} +{{- end -}} + +{{/* +Merge a list of values that contains template after rendering them. +Merge precedence is consistent with https://masterminds.github.io/sprig/dicts.html#mergeoverwrite-mustmergeoverwrite +Usage: +{{ include "common.tplvalues.merge-overwrite" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }} +*/}} +{{- define "common.tplvalues.merge-overwrite" -}} +{{- $dst := dict -}} +{{- range .values -}} +{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | mergeOverwrite $dst -}} +{{- end -}} +{{ $dst | toYaml }} +{{- end -}} diff --git a/backing-services/minio/charts/common/templates/_utils.tpl b/backing-services/minio/charts/common/templates/_utils.tpl new file mode 100644 index 0000000..d53c74a --- /dev/null +++ b/backing-services/minio/charts/common/templates/_utils.tpl @@ -0,0 +1,77 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Print instructions to get a secret value. +Usage: +{{ include "common.utils.secret.getvalue" (dict "secret" "secret-name" "field" "secret-value-field" "context" $) }} +*/}} +{{- define "common.utils.secret.getvalue" -}} +{{- $varname := include "common.utils.fieldToEnvVar" . -}} +export {{ $varname }}=$(kubectl get secret --namespace {{ include "common.names.namespace" .context | quote }} {{ .secret }} -o jsonpath="{.data.{{ .field }}}" | base64 -d) +{{- end -}} + +{{/* +Build env var name given a field +Usage: +{{ include "common.utils.fieldToEnvVar" dict "field" "my-password" }} +*/}} +{{- define "common.utils.fieldToEnvVar" -}} + {{- $fieldNameSplit := splitList "-" .field -}} + {{- $upperCaseFieldNameSplit := list -}} + + {{- range $fieldNameSplit -}} + {{- $upperCaseFieldNameSplit = append $upperCaseFieldNameSplit ( upper . ) -}} + {{- end -}} + + {{ join "_" $upperCaseFieldNameSplit }} +{{- end -}} + +{{/* +Gets a value from .Values given +Usage: +{{ include "common.utils.getValueFromKey" (dict "key" "path.to.key" "context" $) }} +*/}} +{{- define "common.utils.getValueFromKey" -}} +{{- $splitKey := splitList "." .key -}} +{{- $value := "" -}} +{{- $latestObj := $.context.Values -}} +{{- range $splitKey -}} + {{- if not $latestObj -}} + {{- printf "please review the entire path of '%s' exists in values" $.key | fail -}} + {{- end -}} + {{- $value = ( index $latestObj . ) -}} + {{- $latestObj = $value -}} +{{- end -}} +{{- printf "%v" (default "" $value) -}} +{{- end -}} + +{{/* +Returns first .Values key with a defined value or first of the list if all non-defined +Usage: +{{ include "common.utils.getKeyFromList" (dict "keys" (list "path.to.key1" "path.to.key2") "context" $) }} +*/}} +{{- define "common.utils.getKeyFromList" -}} +{{- $key := first .keys -}} +{{- $reverseKeys := reverse .keys }} +{{- range $reverseKeys }} + {{- $value := include "common.utils.getValueFromKey" (dict "key" . "context" $.context ) }} + {{- if $value -}} + {{- $key = . }} + {{- end -}} +{{- end -}} +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Checksum a template at "path" containing a *single* resource (ConfigMap,Secret) for use in pod annotations, excluding the metadata (see #18376). +Usage: +{{ include "common.utils.checksumTemplate" (dict "path" "/configmap.yaml" "context" $) }} +*/}} +{{- define "common.utils.checksumTemplate" -}} +{{- $obj := include (print .context.Template.BasePath .path) .context | fromYaml -}} +{{ omit $obj "apiVersion" "kind" "metadata" | toYaml | sha256sum }} +{{- end -}} diff --git a/backing-services/minio/charts/common/templates/_warnings.tpl b/backing-services/minio/charts/common/templates/_warnings.tpl new file mode 100644 index 0000000..62c44df --- /dev/null +++ b/backing-services/minio/charts/common/templates/_warnings.tpl @@ -0,0 +1,109 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Warning about using rolling tag. +Usage: +{{ include "common.warnings.rollingTag" .Values.path.to.the.imageRoot }} +*/}} +{{- define "common.warnings.rollingTag" -}} + +{{- if and (contains "bitnami/" .repository) (not (.tag | toString | regexFind "-r\\d+$|sha256:")) }} +WARNING: Rolling tag detected ({{ .repository }}:{{ .tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. ++info https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-understand-rolling-tags-containers-index.html +{{- end }} +{{- end -}} + +{{/* +Warning about replaced images from the original. +Usage: +{{ include "common.warnings.modifiedImages" (dict "images" (list .Values.path.to.the.imageRoot) "context" $) }} +*/}} +{{- define "common.warnings.modifiedImages" -}} +{{- $affectedImages := list -}} +{{- $printMessage := false -}} +{{- $originalImages := .context.Chart.Annotations.images -}} +{{- range .images -}} + {{- $fullImageName := printf (printf "%s/%s:%s" .registry .repository .tag) -}} + {{- if not (contains $fullImageName $originalImages) }} + {{- $affectedImages = append $affectedImages (printf "%s/%s:%s" .registry .repository .tag) -}} + {{- $printMessage = true -}} + {{- end -}} +{{- end -}} +{{- if $printMessage }} + +⚠ SECURITY WARNING: Original containers have been substituted. This Helm chart was designed, tested, and validated on multiple platforms using a specific set of Bitnami and Tanzu Application Catalog containers. Substituting other containers is likely to cause degraded security and performance, broken chart features, and missing environment variables. + +Substituted images detected: +{{- range $affectedImages }} + - {{ . }} +{{- end }} +{{- end -}} +{{- end -}} + +{{/* +Warning about not setting the resource object in all deployments. +Usage: +{{ include "common.warnings.resources" (dict "sections" (list "path1" "path2") context $) }} +Example: +{{- include "common.warnings.resources" (dict "sections" (list "csiProvider.provider" "server" "volumePermissions" "") "context" $) }} +The list in the example assumes that the following values exist: + - csiProvider.provider.resources + - server.resources + - volumePermissions.resources + - resources +*/}} +{{- define "common.warnings.resources" -}} +{{- $values := .context.Values -}} +{{- $printMessage := false -}} +{{ $affectedSections := list -}} +{{- range .sections -}} + {{- if eq . "" -}} + {{/* Case where the resources section is at the root (one main deployment in the chart) */}} + {{- if not (index $values "resources") -}} + {{- $affectedSections = append $affectedSections "resources" -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Case where the are multiple resources sections (more than one main deployment in the chart) */}} + {{- $keys := split "." . -}} + {{/* We iterate through the different levels until arriving to the resource section. Example: a.b.c.resources */}} + {{- $section := $values -}} + {{- range $keys -}} + {{- $section = index $section . -}} + {{- end -}} + {{- if not (index $section "resources") -}} + {{/* If the section has enabled=false or replicaCount=0, do not include it */}} + {{- if and (hasKey $section "enabled") -}} + {{- if index $section "enabled" -}} + {{/* enabled=true */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else if and (hasKey $section "replicaCount") -}} + {{/* We need a casting to int because number 0 is not treated as an int by default */}} + {{- if (gt (index $section "replicaCount" | int) 0) -}} + {{/* replicaCount > 0 */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Default case, add it to the affected sections */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- if $printMessage }} + +WARNING: There are "resources" sections in the chart not set. Using "resourcesPreset" is not recommended for production. For production installations, please set the following values according to your workload needs: +{{- range $affectedSections }} + - {{ . }} +{{- end }} ++info https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +{{- end -}} +{{- end -}} diff --git a/backing-services/minio/charts/common/templates/validations/_cassandra.tpl b/backing-services/minio/charts/common/templates/validations/_cassandra.tpl new file mode 100644 index 0000000..f8fd213 --- /dev/null +++ b/backing-services/minio/charts/common/templates/validations/_cassandra.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.cassandra.values.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.cassandra.dbUser.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.dbUser.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled cassandra. + +Usage: +{{ include "common.cassandra.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.cassandra.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.cassandra.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key dbUser + +Usage: +{{ include "common.cassandra.values.key.dbUser" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.key.dbUser" -}} + {{- if .subchart -}} + cassandra.dbUser + {{- else -}} + dbUser + {{- end -}} +{{- end -}} diff --git a/backing-services/minio/charts/common/templates/validations/_mariadb.tpl b/backing-services/minio/charts/common/templates/validations/_mariadb.tpl new file mode 100644 index 0000000..6ea8c0f --- /dev/null +++ b/backing-services/minio/charts/common/templates/validations/_mariadb.tpl @@ -0,0 +1,108 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MariaDB required passwords are not empty. + +Usage: +{{ include "common.validations.values.mariadb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MariaDB values are stored, e.g: "mysql-passwords-secret" + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mariadb.passwords" -}} + {{- $existingSecret := include "common.mariadb.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mariadb.values.enabled" . -}} + {{- $architecture := include "common.mariadb.values.architecture" . -}} + {{- $authPrefix := include "common.mariadb.values.key.auth" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mariadb-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- if not (empty $valueUsername) -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mariadb-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replication") -}} + {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mariadb-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mariadb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mariadb. + +Usage: +{{ include "common.mariadb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mariadb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mariadb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mariadb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mariadb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.key.auth" -}} + {{- if .subchart -}} + mariadb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/backing-services/minio/charts/common/templates/validations/_mongodb.tpl b/backing-services/minio/charts/common/templates/validations/_mongodb.tpl new file mode 100644 index 0000000..e678a6d --- /dev/null +++ b/backing-services/minio/charts/common/templates/validations/_mongodb.tpl @@ -0,0 +1,67 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mongodb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDb is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mongodb. + +Usage: +{{ include "common.mongodb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mongodb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mongodb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mongodb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.key.auth" -}} + {{- if .subchart -}} + mongodb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mongodb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/minio/charts/common/templates/validations/_mysql.tpl b/backing-services/minio/charts/common/templates/validations/_mysql.tpl new file mode 100644 index 0000000..fbb65c3 --- /dev/null +++ b/backing-services/minio/charts/common/templates/validations/_mysql.tpl @@ -0,0 +1,67 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mysql.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mysql. + +Usage: +{{ include "common.mysql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mysql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mysql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mysql.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mysql.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.key.auth" -}} + {{- if .subchart -}} + mysql.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/backing-services/minio/charts/common/templates/validations/_postgresql.tpl b/backing-services/minio/charts/common/templates/validations/_postgresql.tpl new file mode 100644 index 0000000..51d4716 --- /dev/null +++ b/backing-services/minio/charts/common/templates/validations/_postgresql.tpl @@ -0,0 +1,105 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to decide whether evaluate global values. + +Usage: +{{ include "common.postgresql.values.use.global" (dict "key" "key-of-global" "context" $) }} +Params: + - key - String - Required. Field to be evaluated within global, e.g: "existingSecret" +*/}} +{{- define "common.postgresql.values.use.global" -}} + {{- if .context.Values.global -}} + {{- if .context.Values.global.postgresql -}} + {{- index .context.Values.global.postgresql .key | quote -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.postgresql.values.existingSecret" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.existingSecret" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "existingSecret" "context" .context) -}} + + {{- if .subchart -}} + {{- default (.context.Values.postgresql.existingSecret | quote) $globalValue -}} + {{- else -}} + {{- default (.context.Values.existingSecret | quote) $globalValue -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled postgresql. + +Usage: +{{ include "common.postgresql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key postgressPassword. + +Usage: +{{ include "common.postgresql.values.key.postgressPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.postgressPassword" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "postgresqlUsername" "context" .context) -}} + + {{- if not $globalValue -}} + {{- if .subchart -}} + postgresql.postgresqlPassword + {{- else -}} + postgresqlPassword + {{- end -}} + {{- else -}} + global.postgresql.postgresqlPassword + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled.replication. + +Usage: +{{ include "common.postgresql.values.enabled.replication" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.enabled.replication" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.replication.enabled -}} + {{- else -}} + {{- printf "%v" .context.Values.replication.enabled -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key replication.password. + +Usage: +{{ include "common.postgresql.values.key.replicationPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.replicationPassword" -}} + {{- if .subchart -}} + postgresql.replication.password + {{- else -}} + replication.password + {{- end -}} +{{- end -}} diff --git a/backing-services/minio/charts/common/templates/validations/_redis.tpl b/backing-services/minio/charts/common/templates/validations/_redis.tpl new file mode 100644 index 0000000..9fedfef --- /dev/null +++ b/backing-services/minio/charts/common/templates/validations/_redis.tpl @@ -0,0 +1,48 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for enabled redis. + +Usage: +{{ include "common.redis.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.redis.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.redis.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right prefix path for the values + +Usage: +{{ include "common.redis.values.key.prefix" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false +*/}} +{{- define "common.redis.values.keys.prefix" -}} + {{- if .subchart -}}redis.{{- else -}}{{- end -}} +{{- end -}} + +{{/* +Checks whether the redis chart's includes the standarizations (version >= 14) + +Usage: +{{ include "common.redis.values.standarized.version" (dict "context" $) }} +*/}} +{{- define "common.redis.values.standarized.version" -}} + + {{- $standarizedAuth := printf "%s%s" (include "common.redis.values.keys.prefix" .) "auth" -}} + {{- $standarizedAuthValues := include "common.utils.getValueFromKey" (dict "key" $standarizedAuth "context" .context) }} + + {{- if $standarizedAuthValues -}} + {{- true -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/minio/charts/common/templates/validations/_validations.tpl b/backing-services/minio/charts/common/templates/validations/_validations.tpl new file mode 100644 index 0000000..7cdee61 --- /dev/null +++ b/backing-services/minio/charts/common/templates/validations/_validations.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate values must not be empty. + +Usage: +{{- $validateValueConf00 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-01") -}} +{{ include "common.validations.values.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" +*/}} +{{- define "common.validations.values.multiple.empty" -}} + {{- range .required -}} + {{- include "common.validations.values.single.empty" (dict "valueKey" .valueKey "secret" .secret "field" .field "context" $.context) -}} + {{- end -}} +{{- end -}} + +{{/* +Validate a value must not be empty. + +Usage: +{{ include "common.validations.value.empty" (dict "valueKey" "mariadb.password" "secret" "secretName" "field" "my-password" "subchart" "subchart" "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" + - subchart - String - Optional - Name of the subchart that the validated password is part of. +*/}} +{{- define "common.validations.values.single.empty" -}} + {{- $value := include "common.utils.getValueFromKey" (dict "key" .valueKey "context" .context) }} + {{- $subchart := ternary "" (printf "%s." .subchart) (empty .subchart) }} + + {{- if not $value -}} + {{- $varname := "my-value" -}} + {{- $getCurrentValue := "" -}} + {{- if and .secret .field -}} + {{- $varname = include "common.utils.fieldToEnvVar" . -}} + {{- $getCurrentValue = printf " To get the current value:\n\n %s\n" (include "common.utils.secret.getvalue" .) -}} + {{- end -}} + {{- printf "\n '%s' must not be empty, please add '--set %s%s=$%s' to the command.%s" .valueKey $subchart .valueKey $varname $getCurrentValue -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/minio/charts/common/values.yaml b/backing-services/minio/charts/common/values.yaml new file mode 100644 index 0000000..de2cac5 --- /dev/null +++ b/backing-services/minio/charts/common/values.yaml @@ -0,0 +1,8 @@ +# Copyright Broadcom, Inc. All Rights Reserved. +# SPDX-License-Identifier: APACHE-2.0 + +## bitnami/common +## It is required by CI/CD tools and processes. +## @skip exampleValue +## +exampleValue: common-chart diff --git a/backing-services/minio/schoobus-onsite.values.yaml b/backing-services/minio/schoobus-onsite.values.yaml new file mode 100644 index 0000000..a095535 --- /dev/null +++ b/backing-services/minio/schoobus-onsite.values.yaml @@ -0,0 +1,8 @@ +global: + imageRegistry: "192.168.2.43:31898" + security: + allowInsecureImages: true + +auth: + rootUser: admin + rootPassword: "Tavana123" \ No newline at end of file diff --git a/backing-services/minio/school-stage-tavana.values.yaml b/backing-services/minio/school-stage-tavana.values.yaml new file mode 100644 index 0000000..abbe879 --- /dev/null +++ b/backing-services/minio/school-stage-tavana.values.yaml @@ -0,0 +1,21 @@ +global: + imageRegistry: "172.16.16.1:30516" + security: + allowInsecureImages: true + +clientImage: + repository: bitnami/minio-client + tag: 2025.2.15-debian-12-r0 + +image: + repository: bitnami/minio + tag: 2025.2.18-debian-12-r0 + +auth: + rootUser: admin + rootPassword: "Tavana123" + +livenessProbe: + enabled: false +readinessProbe: + enabled: false \ No newline at end of file diff --git a/backing-services/minio/schoolbus-demo.values.yaml b/backing-services/minio/schoolbus-demo.values.yaml new file mode 100644 index 0000000..a992a8b --- /dev/null +++ b/backing-services/minio/schoolbus-demo.values.yaml @@ -0,0 +1,29 @@ +global: + imageRegistry: "172.16.16.2:30516" + security: + allowInsecureImages: true + +clientImage: + repository: bitnami/minio-client + tag: 2025.2.15-debian-12-r0 + +image: + repository: bitnami/minio + tag: 2025.2.18-debian-12-r0 + +auth: + rootUser: admin + rootPassword: "Tavana123" + +livenessProbe: + enabled: false +readinessProbe: + enabled: false + +resources: + requests: + cpu: 200m + memory: 200Mi + limits: + cpu: 200m + memory: 200Mi \ No newline at end of file diff --git a/backing-services/minio/templates/NOTES.txt b/backing-services/minio/templates/NOTES.txt new file mode 100644 index 0000000..4d1188d --- /dev/null +++ b/backing-services/minio/templates/NOTES.txt @@ -0,0 +1,81 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +Did you know there are enterprise versions of the Bitnami catalog? For enhanced secure software supply chain features, unlimited pulls from Docker, LTS support, or application customization, see Bitnami Premium or Tanzu Application Catalog. See https://www.arrow.com/globalecs/na/vendors/bitnami for more information. + +** Please be patient while the chart is being deployed ** + +MinIO® can be accessed via port {{ .Values.service.port }} on the following DNS name from within your cluster: + + {{ include "common.names.fullname" . }}.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }} + +To get your credentials run: + + export ROOT_USER=$(kubectl get secret --namespace {{ .Release.Namespace }} {{ include "minio.secretName" . }} -o jsonpath="{.data.{{ include "minio.rootUserKey" . }}}" | base64 -d) + export ROOT_PASSWORD=$(kubectl get secret --namespace {{ .Release.Namespace }} {{ include "minio.secretName" . }} -o jsonpath="{.data.{{ include "minio.rootPasswordKey" . }}}" | base64 -d) + +To connect to your MinIO® server using a client: + +- Run a MinIO® Client pod and append the desired command (e.g. 'admin info'): + + kubectl run --namespace {{ .Release.Namespace }} {{ include "common.names.fullname" . }}-client \ + --rm --tty -i --restart='Never' \ + --env MINIO_SERVER_ROOT_USER=$ROOT_USER \ + --env MINIO_SERVER_ROOT_PASSWORD=$ROOT_PASSWORD \ + --env MINIO_SERVER_HOST={{ include "common.names.fullname" . }} \ + {{- if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }} + --labels="{{ include "common.names.fullname" . }}-client=true" \ + {{- end }} + --image {{ template "minio.clientImage" . }} -- admin info minio + +{{- if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }} + + NOTE: Since NetworkPolicy is enabled, only pods with label + "{{ template "common.names.fullname" . }}-client=true" will be able to connect to MinIO®. + +{{- end }} +{{- if (not .Values.disableWebUI) }} + +To access the MinIO® web UI: + +- Get the MinIO® URL: + +{{- if .Values.ingress.enabled }} + + You should be able to access your new MinIO® web UI through + + {{ if .Values.ingress.tls }}https{{ else }}http{{ end }}://{{ .Values.ingress.hostname }}/minio/ +{{- 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 {{ include "common.names.fullname" . }}' + + {{- $port:=.Values.service.ports.console | toString }} + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "common.names.fullname" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") + echo "MinIO® web URL: http://$SERVICE_IP{{- if ne $port "80" }}:{{ .Values.service.ports.console }}{{ end }}/minio" + +{{- else if contains "ClusterIP" .Values.service.type }} + + echo "MinIO® web URL: http://127.0.0.1:{{ .Values.containerPorts.console }}/minio" + kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ include "common.names.fullname" . }} {{ .Values.containerPorts.console }}:{{ .Values.service.ports.console }} + +{{- else if contains "NodePort" .Values.service.type }} + + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "common.names.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo "MinIO® web URL: http://$NODE_IP:$NODE_PORT/minio" + +{{- end }} +{{- else }} + + WARN: MinIO® Web UI is disabled. +{{- end }} + +{{- include "common.warnings.rollingTag" .Values.image }} +{{- include "common.warnings.rollingTag" .Values.clientImage }} +{{- include "common.warnings.rollingTag" .Values.volumePermissions.image }} +{{- include "minio.validateValues" . }} +{{- include "common.warnings.resources" (dict "sections" (list "provisioning" "" "volumePermissions") "context" $) }} +{{- include "common.warnings.modifiedImages" (dict "images" (list .Values.image .Values.clientImage .Values.volumePermissions.image) "context" $) }} +{{- include "common.errors.insecureImages" (dict "images" (list .Values.image .Values.clientImage .Values.volumePermissions.image) "context" $) }} diff --git a/backing-services/minio/templates/_helpers.tpl b/backing-services/minio/templates/_helpers.tpl new file mode 100644 index 0000000..222d9ca --- /dev/null +++ b/backing-services/minio/templates/_helpers.tpl @@ -0,0 +1,260 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the proper MinIO® image name +*/}} +{{- define "minio.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) }} + +{{- end -}} + +{{/* +Return the proper MinIO® Client image name +*/}} +{{- define "minio.clientImage" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.clientImage "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper image name (for the init container volume-permissions image) +*/}} +{{- define "minio.volumePermissions.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.volumePermissions.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "minio.imagePullSecrets" -}} +{{- include "common.images.renderPullSecrets" (dict "images" (list .Values.image .Values.clientImage .Values.volumePermissions.image) "context" $) -}} +{{- end -}} + +{{/* +Get the user to use to access MinIO® +*/}} +{{- define "minio.secret.userValue" -}} +{{- if (and (empty .Values.auth.rootUser) .Values.auth.forcePassword) }} + {{ required "A root username is required!" .Values.auth.rootUser }} +{{- else -}} + {{- include "common.secrets.passwords.manage" (dict "secret" (include "common.names.fullname" .) "key" "root-user" "providedValues" (list "auth.rootUser") "context" $) -}} +{{- end -}} +{{- end -}} + +{{/* +Get the password to use to access MinIO® +*/}} +{{- define "minio.secret.passwordValue" -}} +{{- if (and (empty .Values.auth.rootPassword) .Values.auth.forcePassword) }} + {{ required "A root password is required!" .Values.auth.rootPassword }} +{{- else -}} + {{- include "common.secrets.passwords.manage" (dict "secret" (include "common.names.fullname" .) "key" "root-password" "providedValues" (list "auth.rootPassword") "context" $) -}} +{{- end -}} +{{- end -}} + +{{/* +Get the credentials secret. +*/}} +{{- define "minio.secretName" -}} +{{- if .Values.auth.existingSecret -}} + {{- printf "%s" (tpl .Values.auth.existingSecret $) -}} +{{- else -}} + {{- printf "%s" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Get the root user key. +*/}} +{{- define "minio.rootUserKey" -}} +{{- if and (.Values.auth.existingSecret) (.Values.auth.rootUserSecretKey) -}} + {{- printf "%s" (tpl .Values.auth.rootUserSecretKey $) -}} +{{- else -}} + {{- "root-user" -}} +{{- end -}} +{{- end -}} + +{{/* +Get the root password key. +*/}} +{{- define "minio.rootPasswordKey" -}} +{{- if and (.Values.auth.existingSecret) (.Values.auth.rootPasswordSecretKey) -}} + {{- printf "%s" (tpl .Values.auth.rootPasswordSecretKey $) -}} +{{- else -}} + {{- "root-password" -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a secret object should be created +*/}} +{{- define "minio.createSecret" -}} +{{- if and (not .Values.auth.existingSecret) .Values.auth.useSecret -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a PVC object should be created (only in standalone mode) +*/}} +{{- define "minio.createPVC" -}} +{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) (eq .Values.mode "standalone") }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the PVC name (only in standalone mode) +*/}} +{{- define "minio.claimName" -}} +{{- if and .Values.persistence.existingClaim }} + {{- printf "%s" (tpl .Values.persistence.existingClaim $) -}} +{{- else -}} + {{- printf "%s" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Returns the proper service account name depending if an explicit service account name is set +in the values file. If the name is not set it will default to either common.names.fullname if serviceAccount.create +is true or default otherwise. +*/}} +{{- define "minio.serviceAccountName" -}} + {{- if .Values.serviceAccount.create -}} + {{ default (include "common.names.fullname" .) .Values.serviceAccount.name }} + {{- else -}} + {{ default "default" .Values.serviceAccount.name }} + {{- end -}} +{{- end -}} + +{{/* +Compile all warnings into a single message, and call fail. +*/}} +{{- define "minio.validateValues" -}} +{{- $messages := list -}} +{{- $messages := append $messages (include "minio.validateValues.mode" .) -}} +{{- $messages := append $messages (include "minio.validateValues.totalDrives" .) -}} +{{- $messages := append $messages (include "minio.validateValues.tls" .) -}} +{{- $messages := append $messages (include "minio.validateValues.defaultBuckets" .) -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}} +{{- end -}} +{{- end -}} + +{{/* +Validate values of MinIO® - must provide a valid mode ("distributed" or "standalone") +*/}} +{{- define "minio.validateValues.mode" -}} +{{- $allowedValues := list "distributed" "standalone" }} +{{- if not (has .Values.mode $allowedValues) -}} +minio: mode + Invalid mode selected. Valid values are "distributed" and + "standalone". Please set a valid mode (--set mode="xxxx") +{{- end -}} +{{- end -}} + +{{/* +Validate values of MinIO® - total number of drives should be greater than 4 +*/}} +{{- define "minio.validateValues.totalDrives" -}} +{{- $replicaCount := int .Values.statefulset.replicaCount }} +{{- $drivesPerNode := int .Values.statefulset.drivesPerNode }} +{{- $zones := int .Values.statefulset.zones }} +{{- $totalDrives := mul $replicaCount $zones $drivesPerNode }} +{{- if and (eq .Values.mode "distributed") (lt $totalDrives 4) -}} +minio: total drives + The total number of drives should be greater than 4 to guarantee erasure coding! + Please set a combination of nodes, and drives per node that match this condition. + For instance (--set statefulset.replicaCount=2 --set statefulset.drivesPerNode=2) +{{- end -}} +{{- end -}} + +{{/* +Validate values of MinIO® - TLS secret must provided if TLS is enabled +*/}} +{{- define "minio.validateValues.tls" -}} +{{- if and .Values.tls.enabled (not .Values.tls.existingSecret) (not .Values.tls.autoGenerated) }} +minio: tls.existingSecret, tls.autoGenerated + In order to enable TLS, you also need to provide + an existing secret containing the TLS certificates or + enable auto-generated certificates. +{{- end -}} +{{- end -}} + +{{/* +Validate values of MinIO® - defaultBuckets does not work in distributed mode +*/}} +{{- define "minio.validateValues.defaultBuckets" -}} +{{- if and (eq .Values.mode "distributed") (not (empty .Values.defaultBuckets)) }} +minio: defaultBuckets + defaultBuckets does not work in distributed mode. + Use a provisioning job instead. +{{- end -}} +{{- end -}} + +{{/* +Return the secret containing MinIO TLS certificates +*/}} +{{- define "minio.tlsSecretName" -}} +{{- if .Values.tls.existingSecret -}} + {{- printf "%s" (tpl .Values.tls.existingSecret $) -}} +{{- else -}} + {{- printf "%s-crt" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a TLS secret object should be created +*/}} +{{- define "minio.createTlsSecret" -}} +{{- if and .Values.tls.enabled .Values.tls.autoGenerated (not .Values.tls.existingSecret) }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Provisioning job labels (exclude matchLabels from standard labels) +*/}} +{{- define "minio.labels.provisioning" -}} +{{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.provisioning.podLabels .Values.commonLabels ) "context" . ) }} +{{- $provisioningLabels := (include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | fromYaml ) -}} +{{- range (include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | fromYaml | keys ) -}} +{{- $_ := unset $provisioningLabels . -}} +{{- end -}} +{{- print ($provisioningLabels | toYaml) -}} +{{- end -}} + +{{/* +Return the ingress anotation +*/}} +{{- define "minio.ingress.annotations" -}} +{{ .Values.ingress.annotations | toYaml }} +{{- end -}} + +{{/* +Return the api ingress anotation +*/}} +{{- define "minio.apiIngress.annotations" -}} +{{ .Values.apiIngress.annotations | toYaml }} +{{- end -}} + +{{/* +Return the ingress hostname +*/}} +{{- define "minio.ingress.hostname" -}} +{{- tpl .Values.ingress.hostname $ -}} +{{- end -}} + +{{/* +Return the api ingress hostname +*/}} +{{- define "minio.apiIngress.hostname" -}} +{{- tpl .Values.apiIngress.hostname $ -}} +{{- end -}} diff --git a/backing-services/minio/templates/api-ingress.yaml b/backing-services/minio/templates/api-ingress.yaml new file mode 100644 index 0000000..817aa81 --- /dev/null +++ b/backing-services/minio/templates/api-ingress.yaml @@ -0,0 +1,60 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.apiIngress.enabled -}} +apiVersion: {{ include "common.capabilities.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ include "common.names.fullname" . }}-api + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list (include "minio.apiIngress.annotations" . | fromYaml) .Values.commonAnnotations ) "context" . ) }} + {{- if $annotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.apiIngress.ingressClassName (include "common.ingress.supportsIngressClassname" .) }} + ingressClassName: {{ .Values.apiIngress.ingressClassName | quote }} + {{- end }} + rules: + {{- if (include "minio.apiIngress.hostname" .) }} + - host: {{ include "minio.apiIngress.hostname" . }} + http: + paths: + {{- if .Values.apiIngress.extraPaths }} + {{- toYaml .Values.apiIngress.extraPaths | nindent 10 }} + {{- end }} + - path: {{ .Values.apiIngress.path }} + {{- if eq "true" (include "common.ingress.supportsPathType" .) }} + pathType: {{ .Values.apiIngress.pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" .) "servicePort" "minio-api" "context" $) | nindent 14 }} + {{- end }} + {{- range .Values.apiIngress.extraHosts }} + - host: {{ .name | quote }} + http: + paths: + - path: {{ default "/" .path }} + {{- if eq "true" (include "common.ingress.supportsPathType" $) }} + pathType: {{ default "ImplementationSpecific" .pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" $) "servicePort" "minio-api" "context" $) | nindent 14 }} + {{- end }} + {{- if .Values.apiIngress.extraRules }} + {{- include "common.tplvalues.render" (dict "value" .Values.apiIngress.extraRules "context" $) | nindent 4 }} + {{- end }} + {{- $annotationsMap := include "common.tplvalues.render" (dict "value" $annotations "context" $) | fromYaml }} + {{- if or (and .Values.apiIngress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" $annotationsMap )) .Values.apiIngress.selfSigned)) .Values.apiIngress.extraTls }} + tls: + {{- if and .Values.apiIngress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" $annotationsMap )) .Values.apiIngress.selfSigned) }} + - hosts: + - {{ include "minio.apiIngress.hostname" . }} + secretName: {{ printf "%s-tls" (include "minio.apiIngress.hostname" .) }} + {{- end }} + {{- if .Values.apiIngress.extraTls }} + {{- include "common.tplvalues.render" ( dict "value" .Values.apiIngress.extraTls "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/minio/templates/distributed/headless-svc.yaml b/backing-services/minio/templates/distributed/headless-svc.yaml new file mode 100644 index 0000000..230829a --- /dev/null +++ b/backing-services/minio/templates/distributed/headless-svc.yaml @@ -0,0 +1,30 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (eq .Values.mode "distributed") }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-headless" (include "common.names.fullname" .) | trunc 63 }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.service.headless.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.service.headless.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" (dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + ports: + - name: minio-api + port: {{ .Values.service.ports.api }} + targetPort: minio-api + - name: minio-console + port: {{ .Values.service.ports.console }} + targetPort: minio-console + publishNotReadyAddresses: true + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} +{{- end }} diff --git a/backing-services/minio/templates/distributed/statefulset.yaml b/backing-services/minio/templates/distributed/statefulset.yaml new file mode 100644 index 0000000..122e30f --- /dev/null +++ b/backing-services/minio/templates/distributed/statefulset.yaml @@ -0,0 +1,367 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (eq .Values.mode "distributed") }} +{{- $fullname := include "common.names.fullname" . }} +{{- $headlessService := printf "%s-headless" (include "common.names.fullname" .) | trunc 63 }} +{{- $releaseNamespace := include "common.names.namespace" . }} +{{- $clusterDomain := .Values.clusterDomain }} +{{- $apiPort := toString .Values.containerPorts.api }} +{{- $replicaCount := int .Values.statefulset.replicaCount }} +{{- $zoneCount := int .Values.statefulset.zones }} +{{- $drivesPerNode := int .Values.statefulset.drivesPerNode }} +{{- $mountPath := .Values.persistence.mountPath }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ $fullname }} + namespace: {{ $releaseNamespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + serviceName: {{ $headlessService }} + replicas: {{ mul $zoneCount $replicaCount }} + podManagementPolicy: {{ .Values.statefulset.podManagementPolicy }} + {{- if .Values.statefulset.updateStrategy }} + updateStrategy: {{- toYaml .Values.statefulset.updateStrategy | nindent 4 }} + {{- end }} + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + {{- if or .Values.podAnnotations (include "minio.createSecret" .) }} + annotations: + {{- if (include "minio.createSecret" .) }} + checksum/credentials-secret: {{ include (print $.Template.BasePath "/secrets.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.podAnnotations "context" $) | nindent 8 }} + {{- end }} + {{- end }} + spec: + {{- include "minio.imagePullSecrets" . | nindent 6 }} + {{- if .Values.schedulerName }} + schedulerName: {{ .Values.schedulerName }} + {{- end }} + serviceAccountName: {{ template "minio.serviceAccountName" . }} + {{- if .Values.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAffinityPreset "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAntiAffinityPreset "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.nodeAffinityPreset.type "key" .Values.nodeAffinityPreset.key "values" .Values.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.nodeSelector "context" $) | nindent 8 }} + {{- end }} + automountServiceAccountToken: {{ .Values.automountServiceAccountToken }} + {{- if .Values.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.topologySpreadConstraints "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName | quote }} + {{- end }} + {{- if .Values.runtimeClassName }} + runtimeClassName: {{ .Values.runtimeClassName | quote }} + {{- end}} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} + {{- end }} + {{- if or .Values.initContainers (and .Values.volumePermissions.enabled .Values.persistence.enabled) }} + initContainers: + {{- if .Values.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }} + - name: volume-permissions + image: {{ template "minio.volumePermissions.image" . }} + imagePullPolicy: {{ default "" .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + - -ec + - | + {{- if and .Values.persistence.enabled (gt $drivesPerNode 1) }} + chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }} {{ range $diskId := until $drivesPerNode }}{{ $mountPath }}-{{ $diskId }} {{ end }} + {{- else }} + chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }} {{ $mountPath }} + {{- end }} + securityContext: {{- .Values.volumePermissions.containerSecurityContext | toYaml | nindent 12 }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- else if ne .Values.volumePermissions.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.volumePermissions.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if and .Values.persistence.enabled (gt $drivesPerNode 1) }} + {{- range $diskId := until $drivesPerNode }} + - name: data-{{ $diskId }} + mountPath: {{ $mountPath }}-{{ $diskId }} + {{- end }} + {{- else }} + - name: data + mountPath: {{ $mountPath }} + {{- end }} + {{- end }} + {{- end }} + containers: + - name: minio + image: {{ include "minio.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.args "context" $) | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" .Values.image.debug | quote }} + - name: MINIO_DISTRIBUTED_MODE_ENABLED + value: "yes" + - name: MINIO_DISTRIBUTED_NODES + {{- $clusters := list }} + {{- range $i := until $zoneCount }} + {{- $factor := mul $i $replicaCount }} + {{- $endIndex := sub (add $factor $replicaCount) 1 }} + {{- $beginIndex := mul $i $replicaCount }} + {{- $bucket := ternary (printf "%s-{0...%d}" $mountPath (sub $drivesPerNode 1)) $mountPath (gt $drivesPerNode 1) }} + {{- $clusters = append $clusters (printf "%s-{%d...%d}.%s.%s.svc.%s:%s%s" $fullname $beginIndex $endIndex $headlessService $releaseNamespace $clusterDomain $apiPort $bucket) }} + {{- end }} + value: {{ join "," $clusters | quote }} + - name: MINIO_SCHEME + value: {{ ternary "https" "http" .Values.tls.enabled | quote }} + - name: MINIO_FORCE_NEW_KEYS + value: {{ ternary "yes" "no" .Values.auth.forceNewKeys | quote }} + {{- if .Values.auth.useCredentialsFiles }} + - name: MINIO_ROOT_USER_FILE + value: "/opt/bitnami/minio/secrets/root-user" + - name: MINIO_ROOT_PASSWORD_FILE + value: "/opt/bitnami/minio/secrets/root-password" + {{- else }} + - name: MINIO_ROOT_USER + valueFrom: + secretKeyRef: + name: {{ include "minio.secretName" . }} + key: {{ include "minio.rootUserKey" . }} + - name: MINIO_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "minio.secretName" . }} + key: {{ include "minio.rootPasswordKey" . }} + {{- end }} + - name: MINIO_SKIP_CLIENT + value: {{ ternary "yes" "no" (empty .Values.defaultBuckets) | quote }} + {{- if .Values.defaultBuckets }} + - name: MINIO_DEFAULT_BUCKETS + value: {{ .Values.defaultBuckets }} + {{- end }} + - name: MINIO_BROWSER + value: {{ ternary "off" "on" .Values.disableWebUI | quote }} + - name: MINIO_PROMETHEUS_AUTH_TYPE + value: {{ .Values.metrics.prometheusAuthType | quote }} + {{- if .Values.tls.mountPath }} + - name: MINIO_CERTS_DIR + value: {{ .Values.tls.mountPath | quote }} + {{- end }} + - name: MINIO_CONSOLE_PORT_NUMBER + value: {{ .Values.containerPorts.console | quote }} + - name: MINIO_API_PORT_NUMBER + value: {{ .Values.containerPorts.api | quote }} + - name: MINIO_DATA_DIR + value: {{ ternary (printf "%s-0" $mountPath) $mountPath (gt $drivesPerNode 1) | quote }} + {{- if .Values.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.extraEnvVarsSecret "context" $) }} + {{- end }} + ports: + - name: minio-api + containerPort: {{ .Values.containerPorts.api }} + protocol: TCP + - name: minio-console + containerPort: {{ .Values.containerPorts.console }} + protocol: TCP + {{- if .Values.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: /minio/health/live + port: minio-api + scheme: {{ ternary "HTTPS" "HTTP" .Values.tls.enabled | quote }} + initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.readinessProbe.enabled }} + readinessProbe: + tcpSocket: + port: minio-api + initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + {{- end }} + {{- if .Values.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.startupProbe.enabled }} + startupProbe: + tcpSocket: + port: minio-api + initialDelaySeconds: {{ .Values.startupProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.startupProbe.periodSeconds }} + timeoutSeconds: {{ .Values.startupProbe.timeoutSeconds }} + successThreshold: {{ .Values.startupProbe.successThreshold }} + failureThreshold: {{ .Values.startupProbe.failureThreshold }} + {{- end }} + {{- if .Values.resources }} + resources: {{- toYaml .Values.resources | nindent 12 }} + {{- else if ne .Values.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.resourcesPreset) | nindent 12 }} + {{- end }} + {{- if .Values.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/minio/tmp + subPath: app-tmp-dir + - name: empty-dir + mountPath: /.mc + subPath: app-mc-dir + {{- if .Values.auth.useCredentialsFiles }} + - name: minio-credentials + mountPath: /opt/bitnami/minio/secrets/ + {{- end }} + {{- if .Values.tls.enabled }} + - name: minio-certs + mountPath: {{ default "/certs" .Values.tls.mountPath }} + {{- end }} + {{- if gt $drivesPerNode 1 }} + {{- range $diskId := until $drivesPerNode }} + - name: data-{{ $diskId }} + mountPath: {{ $mountPath }}-{{ $diskId }} + {{- end }} + {{- else }} + - name: data + mountPath: {{ $mountPath }} + {{- end }} + {{- if .Values.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: empty-dir + emptyDir: {} + {{- if .Values.auth.useCredentialsFiles }} + - name: minio-credentials + secret: + secretName: {{ include "minio.secretName" . }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: minio-certs + secret: + secretName: {{ include "minio.tlsSecretName" . }} + items: + - key: tls.crt + path: public.crt + - key: tls.key + path: private.key + - key: ca.crt + path: CAs/public.crt + {{- end }} + {{- if .Values.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraVolumes "context" $) | nindent 8 }} + {{- end }} + {{- if and (not .Values.persistence.enabled) (gt $drivesPerNode 1) }} + {{- range $diskId := until $drivesPerNode }} + - name: data-{{ $diskId }} + emptyDir: {} + {{- end }} + {{- else if not .Values.persistence.enabled }} + - name: data + emptyDir: {} + {{- else }} + volumeClaimTemplates: + {{- if gt $drivesPerNode 1 }} + {{- range $diskId := until $drivesPerNode }} + - metadata: + name: data-{{ $diskId }} + labels: {{- include "common.labels.matchLabels" ( dict "customLabels" $.Values.commonLabels "context" $ ) | nindent 10 }} + {{- if $.Values.persistence.annotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.persistence.annotations "context" $) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range $.Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ $.Values.persistence.size | quote }} + {{- if $.Values.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.selector "context" $) | nindent 10 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" $.Values.persistence "global" $.Values.global) | nindent 8 }} + {{- end }} + {{- else }} + - metadata: + name: data + labels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 10 }} + {{- if .Values.persistence.annotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.persistence.annotations "context" $) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- if .Values.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.selector "context" $) | nindent 10 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/minio/templates/extra-list.yaml b/backing-services/minio/templates/extra-list.yaml new file mode 100644 index 0000000..329f5c6 --- /dev/null +++ b/backing-services/minio/templates/extra-list.yaml @@ -0,0 +1,9 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/backing-services/minio/templates/ingress.yaml b/backing-services/minio/templates/ingress.yaml new file mode 100644 index 0000000..1d0d551 --- /dev/null +++ b/backing-services/minio/templates/ingress.yaml @@ -0,0 +1,60 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.ingress.enabled (not .Values.disableWebUI ) -}} +apiVersion: {{ include "common.capabilities.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list (include "minio.ingress.annotations" . | fromYaml) .Values.commonAnnotations ) "context" . ) }} + {{- if $annotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.ingressClassName (include "common.ingress.supportsIngressClassname" .) }} + ingressClassName: {{ .Values.ingress.ingressClassName | quote }} + {{- end }} + rules: + {{- if (include "minio.ingress.hostname" .) }} + - host: {{ include "minio.ingress.hostname" . }} + http: + paths: + {{- if .Values.ingress.extraPaths }} + {{- toYaml .Values.ingress.extraPaths | nindent 10 }} + {{- end }} + - path: {{ .Values.ingress.path }} + {{- if eq "true" (include "common.ingress.supportsPathType" .) }} + pathType: {{ .Values.ingress.pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" .) "servicePort" "minio-console" "context" $) | nindent 14 }} + {{- end }} + {{- range .Values.ingress.extraHosts }} + - host: {{ .name | quote }} + http: + paths: + - path: {{ default "/" .path }} + {{- if eq "true" (include "common.ingress.supportsPathType" $) }} + pathType: {{ default "ImplementationSpecific" .pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" $) "servicePort" "minio-console" "context" $) | nindent 14 }} + {{- end }} + {{- if .Values.ingress.extraRules }} + {{- include "common.tplvalues.render" (dict "value" .Values.ingress.extraRules "context" $) | nindent 4 }} + {{- end }} + {{- $annotationsMap := include "common.tplvalues.render" (dict "value" $annotations "context" $) | fromYaml }} + {{- if or (and .Values.ingress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" $annotationsMap )) .Values.ingress.selfSigned)) .Values.ingress.extraTls }} + tls: + {{- if and .Values.ingress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" $annotationsMap )) .Values.ingress.selfSigned) }} + - hosts: + - {{ include "minio.ingress.hostname" . }} + secretName: {{ printf "%s-tls" (include "minio.ingress.hostname" .) }} + {{- end }} + {{- if .Values.ingress.extraTls }} + {{- include "common.tplvalues.render" ( dict "value" .Values.ingress.extraTls "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/minio/templates/networkpolicy.yaml b/backing-services/minio/templates/networkpolicy.yaml new file mode 100644 index 0000000..37f6a0c --- /dev/null +++ b/backing-services/minio/templates/networkpolicy.yaml @@ -0,0 +1,83 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ include "common.capabilities.networkPolicy.apiVersion" . }} +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + policyTypes: + - Ingress + - Egress + {{- if .Values.networkPolicy.allowExternalEgress }} + egress: + - {} + {{- else }} + egress: + # Allow dns resolution + - ports: + - port: 53 + protocol: UDP + # Allow outbound connections to other cluster pods + - ports: + - port: {{ .Values.containerPorts.api }} + - port: {{ .Values.containerPorts.console }} + - port: {{ .Values.service.ports.api }} + - port: {{ .Values.service.ports.console }} + to: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 14 }} + {{- if .Values.networkPolicy.extraEgress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.networkPolicy.extraEgress "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} + ingress: + # Allow inbound connections + - ports: + - port: {{ .Values.containerPorts.console }} + - port: {{ .Values.containerPorts.api }} + {{- if not .Values.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: + {{ include "common.names.fullname" . }}-client: "true" + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 14 }} + {{- if or .Values.networkPolicy.ingressNSMatchLabels .Values.networkPolicy.ingressNSPodMatchLabels }} + - namespaceSelector: + matchLabels: + {{- if .Values.networkPolicy.ingressNSMatchLabels }} + {{- range $key, $value := .Values.networkPolicy.ingressNSMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{ else }} + {} + {{- end }} + {{- if .Values.networkPolicy.ingressNSPodMatchLabels }} + podSelector: + matchLabels: + {{- range $key, $value := .Values.networkPolicy.ingressNSPodMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- $extraIngress := coalesce .Values.networkPolicy.extraIngress .Values.networkPolicy.extraFromClauses }} + {{- if $extraIngress }} + {{- toYaml $extraIngress | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.networkPolicy.extraIngress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.networkPolicy.extraIngress "context" $ ) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/minio/templates/pdb.yaml b/backing-services/minio/templates/pdb.yaml new file mode 100644 index 0000000..e34aa45 --- /dev/null +++ b/backing-services/minio/templates/pdb.yaml @@ -0,0 +1,26 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.pdb.minAvailable }} + minAvailable: {{ .Values.pdb.minAvailable }} + {{- end }} + {{- if or .Values.pdb.maxUnavailable ( not .Values.pdb.minAvailable ) }} + maxUnavailable: {{ .Values.pdb.maxUnavailable | default 1 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} +{{- end }} diff --git a/backing-services/minio/templates/prometheusrule.yaml b/backing-services/minio/templates/prometheusrule.yaml new file mode 100644 index 0000000..5f1d6fe --- /dev/null +++ b/backing-services/minio/templates/prometheusrule.yaml @@ -0,0 +1,25 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled }} +{{- $releaseNamespace := default (include "common.names.namespace" .) .Values.metrics.prometheusRule.namespace }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ $releaseNamespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: metrics + {{- if .Values.metrics.prometheusRule.additionalLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.prometheusRule.additionalLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + groups: + - name: {{ include "common.names.fullname" . }} + rules: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.prometheusRule.rules "context" $ ) | nindent 6 }} +{{- end }} diff --git a/backing-services/minio/templates/provisioning-configmap.yaml b/backing-services/minio/templates/provisioning-configmap.yaml new file mode 100644 index 0000000..bf11bd1 --- /dev/null +++ b/backing-services/minio/templates/provisioning-configmap.yaml @@ -0,0 +1,76 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.provisioning.enabled }} +{{- $fullname := printf "%s-provisioning" (include "common.names.fullname" .) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $fullname }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: minio-provisioning + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + {{- range $bucket := .Values.provisioning.buckets }} + {{- if $bucket.lifecycle }} + bucket-{{ $bucket.name }}.json: | + { + "Rules": [ + {{- range $idx, $lifecycle := $bucket.lifecycle }} + {{- if not (eq $idx 0) }} + , + {{- end }} + { + "ID": "{{ $lifecycle.id }}", + "Status": "{{ ternary "Disabled" "Enabled" (and (not (empty $lifecycle.disabled)) $lifecycle.disabled) }}", + {{- if $lifecycle.expiry }} + "Expiration": { + {{- with $lifecycle.expiry.date }} + "Date": "{{ . }}" + {{- end }} + {{- with $lifecycle.expiry.days }} + "Days": {{ . }} + {{- end }} + } + {{- with $lifecycle.expiry.nonconcurrentDays }} + , + "NoncurrentVersionExpiration": { + "NoncurrentDays": {{ . }} + } + {{- end }} + {{- with $lifecycle.prefix }} + , + "Filter": { + "Prefix": "{{ . }}" + } + {{- end }} + } + {{- end }} + {{- end }} + ] + } + {{- end }} + {{- end }} + {{- range $policy := .Values.provisioning.policies }} + policy-{{ $policy.name }}.json: | + {{- $statementsLength := sub (len $policy.statements) 1 }} + { + "Version": "2012-10-17", + "Statement": [ + {{- range $i, $statement := $policy.statements }} + { + "Effect": "{{ default "Deny" $statement.effect }}"{{ if $statement.actions }}, + "Action": {{ toJson $statement.actions }}{{end}}{{ if $statement.resources }}, + "Resource": {{ toJson $statement.resources }}{{end}}{{ if $statement.condition }}, + "Condition": {{ toJson $statement.condition }}{{end}} + }{{ if lt $i $statementsLength }},{{end }} + {{- end }} + ] + } + {{- end }} +{{- end }} diff --git a/backing-services/minio/templates/provisioning-job.yaml b/backing-services/minio/templates/provisioning-job.yaml new file mode 100644 index 0000000..0355933 --- /dev/null +++ b/backing-services/minio/templates/provisioning-job.yaml @@ -0,0 +1,370 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.provisioning.enabled }} +{{- $fullname := printf "%s-provisioning" (include "common.names.fullname" .) }} +{{- $minioAlias := "provisioning" }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ $fullname }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: minio-provisioning + annotations: + helm.sh/hook: post-install,post-upgrade + helm.sh/hook-delete-policy: before-hook-creation + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.provisioning.cleanupAfterFinished.enabled }} + ttlSecondsAfterFinished: {{ .Values.provisioning.cleanupAfterFinished.seconds }} + {{- end }} + parallelism: 1 + template: + metadata: + labels: {{- include "minio.labels.provisioning" . | nindent 8 }} + app.kubernetes.io/component: minio-provisioning + {{- if .Values.provisioning.podAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.provisioning.podAnnotations "context" $) | nindent 8 }} + {{- end }} + spec: + {{- include "minio.imagePullSecrets" . | nindent 6 }} + {{- if .Values.provisioning.schedulerName }} + schedulerName: {{ .Values.provisioning.schedulerName }} + {{- end }} + restartPolicy: OnFailure + terminationGracePeriodSeconds: 0 + {{- if .Values.provisioning.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.provisioning.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + serviceAccountName: {{ template "minio.serviceAccountName" . }} + initContainers: + - name: wait-for-available-minio + image: {{ include "minio.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.provisioning.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.provisioning.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + command: + - /bin/bash + - -c + - |- + set -e; + echo "Waiting for Minio"; + wait-for-port \ + --host={{ include "common.names.fullname" . }} \ + --state=inuse \ + --timeout=120 \ + {{ .Values.service.ports.api | int64 }}; + echo "Minio is available"; + {{- if .Values.provisioning.resources }} + resources: {{- toYaml .Values.provisioning.resources | nindent 12 }} + {{- else if ne .Values.provisioning.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.provisioning.resourcesPreset) | nindent 12 }} + {{- end }} + containers: + - name: minio + image: {{ include "minio.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.provisioning.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.provisioning.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.provisioning.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.provisioning.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -c + - |- + set -e; + echo "Start Minio provisioning"; + + retry_while() { + local -r cmd="${1:?cmd is missing}" + local -r retries="${2:-12}" + local -r sleep_time="${3:-5}" + local return_value=1 + + read -r -a command <<< "$cmd" + for ((i = 1 ; i <= retries ; i+=1 )); do + "${command[@]}" && return_value=0 && break + sleep "$sleep_time" + done + return $return_value + } + + function attachPolicy() { + local tmp=$(mc admin $1 info {{ $minioAlias }} $2 | sed -n -e 's/^Policy.*: \(.*\)$/\1/p'); + IFS=',' read -r -a CURRENT_POLICIES <<< "$tmp"; + if [[ ! "${CURRENT_POLICIES[*]}" =~ "$3" ]]; then + mc admin policy attach {{ $minioAlias }} $3 --$1=$2; + fi; + }; + + function detachDanglingPolicies() { + local tmp=$(mc admin $1 info {{ $minioAlias }} $2 | sed -n -e 's/^Policy.*: \(.*\)$/\1/p'); + IFS=',' read -r -a CURRENT_POLICIES <<< "$tmp"; + IFS=',' read -r -a DESIRED_POLICIES <<< "$3"; + for current in "${CURRENT_POLICIES[@]}"; do + if [[ ! "${DESIRED_POLICIES[*]}" =~ "${current}" ]]; then + mc admin policy detach {{ $minioAlias }} $current --$1=$2; + fi; + done; + } + + function addUsersFromFile() { + local username=$(grep -oP '^username=\K.+' $1); + local password=$(grep -oP '^password=\K.+' $1); + local disabled=$(grep -oP '^disabled=\K.+' $1); + local policies_list=$(grep -oP '^policies=\K.+' $1); + local set_policies=$(grep -oP '^setPolicies=\K.+' $1); + + mc admin user add {{ $minioAlias }} "${username}" "${password}"; + + IFS=',' read -r -a POLICIES <<< "${policies_list}"; + for policy in "${POLICIES[@]}"; do + attachPolicy user "${username}" "${policy}"; + done; + if [ "${set_policies}" == "true" ]; then + detachDanglingPolicies user "${username}" "${policies_list}"; + fi; + + local user_status="enable"; + if [[ "${disabled}" != "" && "${disabled,,}" == "true" ]]; then + user_status="disable"; + fi; + + mc admin user "${user_status}" {{ $minioAlias }} "${username}"; + }; + + {{- $minioUrl := printf "$MINIO_SCHEME://%s:%d" (include "common.names.fullname" .) (.Values.service.ports.api | int) }} + {{- $minioRootUser := ternary ("$(<$MINIO_ROOT_USER_FILE)") ("$MINIO_ROOT_USER") (.Values.auth.useCredentialsFiles) }} + {{- $minioRootPassword := ternary ("$(<$MINIO_ROOT_PASSWORD_FILE)") ("$MINIO_ROOT_PASSWORD") (.Values.auth.useCredentialsFiles) }} + mc alias set {{ $minioAlias }} {{ $minioUrl }} {{ $minioRootUser }} {{ $minioRootPassword }}; + + {{- range $config := .Values.provisioning.config }} + {{- $options := list }} + {{- range $name, $value := $config.options }} + {{- $options = (printf "%s=%s" $name $value) | append $options }} + {{- end }} + {{- $options := join " " $options }} + mc admin config set {{ $minioAlias }} {{ $config.name }} {{ $options }}; + {{- end }} + + mc admin service restart {{ $minioAlias }} --wait --json; + + # Adding a sleep to ensure that the check below does not cause + # a race condition. We check for the MinIO port because the + # "mc admin service restart --wait" command is not working as expected + sleep {{ .Values.provisioning.sleepTime | default 5 }}; + echo "Waiting for Minio to be available after restart"; + if ! retry_while "mc admin info {{ $minioAlias }}"; then + echo "Error connecting to Minio" + exit 1 + fi + echo "Minio is available. Executing provisioning commands"; + + {{- range $policy := .Values.provisioning.policies }} + mc admin policy create {{ $minioAlias }} {{ $policy.name }} /etc/ilm/policy-{{ $policy.name }}.json; + {{- end }} + + {{- range $user := .Values.provisioning.users }} + mc admin user add {{ $minioAlias }} {{ $user.username }} {{ $user.password }}; + {{- range $policy := $user.policies }} + attachPolicy user {{ $user.username }} {{ $policy }}; + {{- end }} + {{- if $user.setPolicies }} + detachDanglingPolicies user {{ $user.username }} "{{ join "," $user.policies }}"; + {{- end }} + {{- $userStatus := ternary ("disable") ("enable") (and (not (empty $user.disabled)) $user.disabled) }} + mc admin user {{ $userStatus }} {{ $minioAlias }} {{ $user.username }}; + {{- end }} + {{- if gt (len .Values.provisioning.usersExistingSecrets) 0 }} + while read -d '' configFile; do + addUsersFromFile "${configFile}"; + done < <(find "/opt/bitnami/minio/users/" -type l -not -name '..data' -print0); + {{- end }} + + {{- range $group := .Values.provisioning.groups }} + mc admin group add {{ $minioAlias }} {{ $group.name }} {{ join " " $group.members }}; + {{- range $policy := $group.policies }} + attachPolicy group {{ $group.name }} {{ $policy }}; + {{- end }} + {{- if $group.setPolicies }} + detachDanglingPolicies group {{ $group.name }} "{{ join "," $group.policies }}"; + {{- end }} + {{- $groupStatus := ternary ("disable") ("enable") (and (not (empty $group.disabled)) $group.disabled) }} + mc admin group {{ $groupStatus }} {{ $minioAlias }} {{ $group.name }}; + {{- end }} + + {{- range $bucket := .Values.provisioning.buckets }} + {{- $target := printf "%s/%s" $minioAlias $bucket.name }} + {{- $region := ternary (printf "--region=%s" $bucket.region) ("") (not (empty $bucket.region)) }} + {{- $withLock := ternary ("--with-lock") ("") (and (not (empty $bucket.withLock)) $bucket.withLock) }} + mc mb {{ $target }} --ignore-existing {{ $region }} {{ $withLock }}; + + {{- if $bucket.lifecycle }} + mc ilm import {{ $minioAlias }}/{{ $bucket.name }} < /etc/ilm/bucket-{{ $bucket.name }}.json; + {{- end }} + + {{- with $bucket.quota }} + {{- if eq .type "hard" }} + mc quota set {{ $minioAlias }}/{{ $bucket.name }} {{ if .size }}--size {{ .size }}{{ end }}; + {{- else }} + mc quota {{ .type }} {{ $minioAlias }}/{{ $bucket.name }} {{ if .size }}--size {{ .size }}{{ end }}; + {{- end }} + {{- end }} + + {{- if (or ((empty $bucket.withLock)) (not $bucket.withLock)) }} + {{- $versioning := default "Suspended" $bucket.versioning }} + {{- if kindIs "bool" $bucket.versioning }} + {{- $versioning = ternary "Versioned" "Suspended" $bucket.versioning }} + {{- end }} + {{- if eq $versioning "Versioned" }} + mc version enable {{ $minioAlias }}/{{ $bucket.name }}; + {{- else if eq $versioning "Suspended" }} + mc version suspend {{ $minioAlias }}/{{ $bucket.name }}; + {{- else if ne $versioning "Unchanged" }} + {{- fail (printf "Invalid value '%s' for versioning of bucket '%s'" $versioning $bucket.name) }} + {{- end }} + {{- end }} + + {{- if $bucket.tags }} + {{- $target := printf "%s/%s" $minioAlias $bucket.name }} + {{- $tags := list }} + {{- range $name, $value := $bucket.tags }} + {{- $tags = (printf "%s=%s" $name $value) | append $tags }} + {{- end }} + {{- $tags = join "&" $tags | quote }} + mc tag set {{ $target }} {{ $tags }}; + {{- end }} + {{- end }} + + {{- if .Values.provisioning.extraCommands }} + {{ join ";" .Values.provisioning.extraCommands | nindent 14 }}; + {{- end }} + + echo "End Minio provisioning"; + {{- end }} + {{- if .Values.provisioning.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.provisioning.args "context" $) | nindent 12 }} + {{- end }} + env: + - name: MINIO_SCHEME + value: {{ ternary "https" "http" .Values.tls.enabled | quote }} + {{- if .Values.auth.useCredentialsFiles }} + - name: MINIO_ROOT_USER_FILE + value: "/opt/bitnami/minio/secrets/root-user" + - name: MINIO_ROOT_PASSWORD_FILE + value: "/opt/bitnami/minio/secrets/root-password" + {{- else }} + - name: MINIO_ROOT_USER + valueFrom: + secretKeyRef: + name: {{ include "minio.secretName" . }} + key: {{ include "minio.rootUserKey" . }} + - name: MINIO_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "minio.secretName" . }} + key: {{ include "minio.rootPasswordKey" . }} + {{- end }} + {{- if .Values.tls.mountPath }} + - name: MINIO_CERTS_DIR + value: {{ .Values.tls.mountPath | quote }} + {{- end }} + envFrom: + {{- if .Values.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.extraEnvVarsSecret "context" $) }} + {{- end }} + {{- if .Values.provisioning.resources }} + resources: {{- toYaml .Values.provisioning.resources | nindent 12 }} + {{- else if ne .Values.provisioning.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.provisioning.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /.mc + subPath: app-mc-dir + - name: empty-dir + mountPath: /opt/bitnami/minio/tmp + subPath: app-tmp-dir + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if .Values.provisioning.enabled }} + - name: minio-provisioning + mountPath: /etc/ilm + {{- end }} + {{- if .Values.auth.useCredentialsFiles }} + - name: minio-credentials + mountPath: /opt/bitnami/minio/secrets/ + {{- end }} + {{- if .Values.tls.enabled }} + - name: minio-certs + mountPath: {{ default "/certs" .Values.tls.mountPath }} + - name: minio-client-certs + mountPath: /.mc/certs + {{- end }} + {{- range $idx, $_ := .Values.provisioning.usersExistingSecrets }} + - name: {{ printf "users-secret-%d" $idx }} + mountPath: /opt/bitnami/minio/users/{{ $idx }}/ + {{- end }} + {{- if .Values.provisioning.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.provisioning.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.provisioning.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.provisioning.nodeSelector "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: empty-dir + emptyDir: {} + {{- if .Values.provisioning.enabled }} + - name: minio-provisioning + configMap: + name: {{ $fullname }} + {{- end }} + {{- if .Values.auth.useCredentialsFiles }} + - name: minio-credentials + secret: + secretName: {{ include "minio.secretName" . }} + {{- end }} + {{- range $idx, $userSecret := .Values.provisioning.usersExistingSecrets }} + - name: {{ printf "users-secret-%d" $idx }} + secret: + secretName: {{ $userSecret }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: minio-certs + secret: + secretName: {{ include "minio.tlsSecretName" . }} + items: + - key: tls.crt + path: public.crt + - key: tls.key + path: private.key + - key: ca.crt + path: CAs/public.crt + - name: minio-client-certs + secret: + secretName: {{ include "minio.tlsSecretName" . }} + items: + - key: ca.crt + path: CAs/public.crt + {{- end }} + {{- if .Values.provisioning.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.provisioning.extraVolumes "context" $) | nindent 8 }} + {{- end }} +{{- end }} diff --git a/backing-services/minio/templates/provisioning-networkpolicy.yaml b/backing-services/minio/templates/provisioning-networkpolicy.yaml new file mode 100644 index 0000000..ea9fb4a --- /dev/null +++ b/backing-services/minio/templates/provisioning-networkpolicy.yaml @@ -0,0 +1,50 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.provisioning.enabled .Values.provisioning.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ include "common.capabilities.networkPolicy.apiVersion" . }} +metadata: + name: {{ printf "%s-provisioning" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + podSelector: + matchLabels: + app.kubernetes.io/component: minio-provisioning + policyTypes: + - Ingress + - Egress + {{- if .Values.provisioning.networkPolicy.allowExternalEgress }} + egress: + - {} + {{- else }} + egress: + # Allow dns resolution + - ports: + - port: 53 + protocol: UDP + # Allow outbound connections to other cluster pods + - ports: + - port: {{ .Values.containerPorts.api }} + - port: {{ .Values.containerPorts.console }} + - port: {{ .Values.service.ports.api }} + - port: {{ .Values.service.ports.console }} + to: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 14 }} + {{- if .Values.provisioning.networkPolicy.extraEgress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.dataCoord.networkPolicy.extraEgress "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} + ingress: + {{- if .Values.provisioning.networkPolicy.extraIngress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.initJob.networkPolicy.extraIngress "context" $ ) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/minio/templates/pvc.yaml b/backing-services/minio/templates/pvc.yaml new file mode 100644 index 0000000..33e6727 --- /dev/null +++ b/backing-services/minio/templates/pvc.yaml @@ -0,0 +1,26 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "minio.createPVC" .) }} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.persistence.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.persistence.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" (dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) | nindent 2 }} +{{- end }} diff --git a/backing-services/minio/templates/secrets.yaml b/backing-services/minio/templates/secrets.yaml new file mode 100644 index 0000000..aed9e97 --- /dev/null +++ b/backing-services/minio/templates/secrets.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "minio.createSecret" .) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + root-user: {{ include "minio.secret.userValue" . }} + root-password: {{ include "minio.secret.passwordValue" . }} +{{- end }} diff --git a/backing-services/minio/templates/service.yaml b/backing-services/minio/templates/service.yaml new file mode 100644 index 0000000..1230a2b --- /dev/null +++ b/backing-services/minio/templates/service.yaml @@ -0,0 +1,51 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" (dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + {{- if and (eq .Values.service.type "ClusterIP") .Values.service.clusterIP }} + clusterIP: {{ .Values.service.clusterIP }} + {{- end }} + {{- if or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{- toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + ports: + - name: minio-api + port: {{ .Values.service.ports.api }} + targetPort: minio-api + {{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.api)) }} + nodePort: {{ .Values.service.nodePorts.api }} + {{- else if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- end }} + - name: minio-console + port: {{ .Values.service.ports.console }} + targetPort: minio-console + {{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.console)) }} + nodePort: {{ .Values.service.nodePorts.console }} + {{- else if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} diff --git a/backing-services/minio/templates/serviceaccount.yaml b/backing-services/minio/templates/serviceaccount.yaml new file mode 100644 index 0000000..ac3f463 --- /dev/null +++ b/backing-services/minio/templates/serviceaccount.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "minio.serviceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" (dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +secrets: + - name: {{ include "common.names.fullname" . }} +{{- end }} diff --git a/backing-services/minio/templates/servicemonitor.yaml b/backing-services/minio/templates/servicemonitor.yaml new file mode 100644 index 0000000..1fa14e7 --- /dev/null +++ b/backing-services/minio/templates/servicemonitor.yaml @@ -0,0 +1,66 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} +{{- /* TODO: On major version upgrade, add .Values.metrics.enabled to that check */}} +{{- if .Values.metrics.serviceMonitor.enabled }} +{{- $releaseNamespace := default (include "common.names.namespace" .) .Values.metrics.serviceMonitor.namespace }} +apiVersion: {{ default "monitoring.coreos.com/v1" .Values.metrics.serviceMonitor.apiVersion }} +kind: ServiceMonitor +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ $releaseNamespace | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.serviceMonitor.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + endpoints: + {{- /* Backward Compatibility for .Values.metrics.serviceMonitor.path */}} + {{- $paths := list }} + {{- if (.Values.metrics.serviceMonitor.paths | empty | not) }} + {{- $paths = .Values.metrics.serviceMonitor.paths }} + {{- end }} + {{- if (.Values.metrics.serviceMonitor.path | empty | not) }} + {{- $paths = prepend $paths .Values.metrics.serviceMonitor.path }} + {{- end }} + {{- range $idx, $path := ($paths | uniq) }} + {{- with $ }} + - port: minio-api + path: {{ $path }} + {{- if .Values.metrics.serviceMonitor.interval }} + interval: {{ .Values.metrics.serviceMonitor.interval }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.honorLabels }} + honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: {{- toYaml .Values.metrics.serviceMonitor.metricRelabelings | nindent 8 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.relabelings }} + relabelings: {{- toYaml .Values.metrics.serviceMonitor.relabelings | nindent 8 }} + {{- end }} + {{- if .Values.tls.enabled }} + scheme: https + {{- end }} + {{- if .Values.metrics.serviceMonitor.tlsConfig }} + tlsConfig: {{- toYaml .Values.metrics.serviceMonitor.tlsConfig | nindent 8 }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.jobLabel }} + jobLabel: {{ .Values.metrics.serviceMonitor.jobLabel }} + {{- end }} + namespaceSelector: + matchNames: + - {{ include "common.names.namespace" . | quote }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + {{- if .Values.metrics.serviceMonitor.selector }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.serviceMonitor.selector "context" $) | nindent 6 }} + {{- end }} +{{- end }} diff --git a/backing-services/minio/templates/standalone/deployment.yaml b/backing-services/minio/templates/standalone/deployment.yaml new file mode 100644 index 0000000..7a33bf3 --- /dev/null +++ b/backing-services/minio/templates/standalone/deployment.yaml @@ -0,0 +1,280 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (eq .Values.mode "standalone") }} +apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} +kind: Deployment +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + {{- if .Values.deployment.updateStrategy }} + strategy: {{- toYaml .Values.deployment.updateStrategy | nindent 4 }} + {{- end }} + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + {{- if or .Values.podAnnotations (include "minio.createSecret" .) }} + annotations: + {{- if (include "minio.createSecret" .) }} + checksum/credentials-secret: {{ include (print $.Template.BasePath "/secrets.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.podAnnotations "context" $) | nindent 8 }} + {{- end }} + {{- end }} + spec: + {{- include "minio.imagePullSecrets" . | nindent 6 }} + {{- if .Values.schedulerName }} + schedulerName: {{ .Values.schedulerName }} + {{- end }} + serviceAccountName: {{ template "minio.serviceAccountName" . }} + {{- if .Values.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAffinityPreset "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAntiAffinityPreset "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.nodeAffinityPreset.type "key" .Values.nodeAffinityPreset.key "values" .Values.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.topologySpreadConstraints "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName | quote }} + {{- end }} + {{- if .Values.runtimeClassName }} + runtimeClassName: {{ .Values.runtimeClassName | quote }} + {{- end}} + automountServiceAccountToken: {{ .Values.automountServiceAccountToken }} + {{- if .Values.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} + {{- end }} + {{- if or .Values.initContainers (and .Values.volumePermissions.enabled .Values.persistence.enabled) }} + initContainers: + {{- if .Values.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }} + - name: volume-permissions + image: {{ template "minio.volumePermissions.image" . }} + imagePullPolicy: {{ default "" .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + - -ec + - | + chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }} {{ .Values.persistence.mountPath }} + securityContext: {{- .Values.volumePermissions.containerSecurityContext | toYaml | nindent 12 }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- else if ne .Values.volumePermissions.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.volumePermissions.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: data + mountPath: {{ .Values.persistence.mountPath }} + {{- end }} + {{- end }} + containers: + - name: minio + image: {{ include "minio.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.args "context" $) | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" .Values.image.debug | quote }} + - name: MINIO_SCHEME + value: {{ ternary "https" "http" .Values.tls.enabled | quote }} + - name: MINIO_FORCE_NEW_KEYS + value: {{ ternary "yes" "no" .Values.auth.forceNewKeys | quote }} + - name: MINIO_API_PORT_NUMBER + value: {{ .Values.containerPorts.api | quote }} + {{- if .Values.auth.useCredentialsFiles }} + - name: MINIO_ROOT_USER_FILE + value: "/opt/bitnami/minio/secrets/root-user" + - name: MINIO_ROOT_PASSWORD_FILE + value: "/opt/bitnami/minio/secrets/root-password" + {{- else }} + - name: MINIO_ROOT_USER + valueFrom: + secretKeyRef: + name: {{ include "minio.secretName" . }} + key: {{ include "minio.rootUserKey" . }} + - name: MINIO_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "minio.secretName" . }} + key: {{ include "minio.rootPasswordKey" . }} + {{- end }} + {{- if .Values.defaultBuckets }} + - name: MINIO_DEFAULT_BUCKETS + value: {{ .Values.defaultBuckets }} + {{- end }} + - name: MINIO_BROWSER + value: {{ ternary "off" "on" .Values.disableWebUI | quote }} + - name: MINIO_PROMETHEUS_AUTH_TYPE + value: {{ .Values.metrics.prometheusAuthType | quote }} + - name: MINIO_CONSOLE_PORT_NUMBER + value: {{ .Values.containerPorts.console | quote }} + {{- if .Values.tls.mountPath }} + - name: MINIO_CERTS_DIR + value: {{ .Values.tls.mountPath | quote }} + {{- end }} + {{- if .Values.persistence.mountPath }} + - name: MINIO_DATA_DIR + value: {{ .Values.persistence.mountPath | quote }} + {{- end }} + {{- if .Values.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.extraEnvVarsSecret "context" $) }} + {{- end }} + ports: + - name: minio-api + containerPort: {{ .Values.containerPorts.api }} + protocol: TCP + - name: minio-console + containerPort: {{ .Values.containerPorts.console }} + protocol: TCP + {{- if .Values.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: /minio/health/live + port: minio-api + scheme: {{ ternary "HTTPS" "HTTP" .Values.tls.enabled | quote }} + initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.readinessProbe.enabled }} + readinessProbe: + tcpSocket: + port: minio-api + initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + {{- end }} + {{- if .Values.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.startupProbe.enabled }} + startupProbe: + tcpSocket: + port: minio-console + initialDelaySeconds: {{ .Values.startupProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.startupProbe.periodSeconds }} + timeoutSeconds: {{ .Values.startupProbe.timeoutSeconds }} + successThreshold: {{ .Values.startupProbe.successThreshold }} + failureThreshold: {{ .Values.startupProbe.failureThreshold }} + {{- end }} + {{- if .Values.resources }} + resources: {{- toYaml .Values.resources | nindent 12 }} + {{- else if ne .Values.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.resourcesPreset) | nindent 12 }} + {{- end }} + {{- if .Values.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/minio/tmp + subPath: app-tmp-dir + - name: empty-dir + mountPath: /.mc + subPath: app-mc-dir + {{- if and .Values.auth.useSecret .Values.auth.useCredentialsFiles }} + - name: minio-credentials + mountPath: /opt/bitnami/minio/secrets/ + {{- end }} + - name: data + mountPath: {{ .Values.persistence.mountPath }} + {{- if .Values.tls.enabled }} + - name: minio-certs + mountPath: {{ default "/certs" .Values.tls.mountPath }} + {{- end }} + {{- if .Values.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: empty-dir + emptyDir: {} + {{- if and .Values.auth.useSecret .Values.auth.useCredentialsFiles }} + - name: minio-credentials + secret: + secretName: {{ include "minio.secretName" . }} + {{- end }} + - name: data + {{- if .Values.persistence.enabled }} + persistentVolumeClaim: + claimName: {{ include "minio.claimName" . }} + {{- else }} + emptyDir: {} + {{- end }} + {{- if .Values.tls.enabled }} + - name: minio-certs + secret: + secretName: {{ include "minio.tlsSecretName" . }} + items: + - key: tls.crt + path: public.crt + - key: tls.key + path: private.key + - key: ca.crt + path: CAs/public.crt + {{- end }} + {{- if .Values.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraVolumes "context" $) | nindent 8 }} + {{- end }} +{{- end }} diff --git a/backing-services/minio/templates/tls-secrets.yaml b/backing-services/minio/templates/tls-secrets.yaml new file mode 100644 index 0000000..765664a --- /dev/null +++ b/backing-services/minio/templates/tls-secrets.yaml @@ -0,0 +1,69 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.ingress.enabled }} +{{- if .Values.ingress.secrets }} +{{- range .Values.ingress.secrets }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .name }} + namespace: {{ include "common.names.namespace" $ | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $.Values.commonLabels "context" $ ) | nindent 4 }} + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ .certificate | b64enc }} + tls.key: {{ .key | b64enc }} +--- +{{- end }} +{{- end }} +{{- if and .Values.ingress.tls .Values.ingress.selfSigned }} +{{- $secretName := printf "%s-tls" .Values.ingress.hostname }} +{{- $ca := genCA "minio-ca" 365 }} +{{- $cert := genSignedCert .Values.ingress.hostname nil (list .Values.ingress.hostname) 365 $ca }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.crt" "defaultValue" $cert.Cert "context" $) }} + tls.key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.key" "defaultValue" $cert.Key "context" $) }} + ca.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }} +{{- end }} +{{- end }} +{{- if (include "minio.createTlsSecret" .) }} +{{- $secretName := printf "%s-crt" (include "common.names.fullname" .) }} +{{- $ca := genCA "minio-ca" 365 }} +{{- $releaseNamespace := include "common.names.namespace" . }} +{{- $clusterDomain := .Values.clusterDomain }} +{{- $fullname := include "common.names.fullname" . }} +{{- $serviceName := include "common.names.fullname" . }} +{{- $headlessServiceName := printf "%s-headless" (include "common.names.fullname" .) }} +{{- $altNames := list (printf "*.%s.%s.svc.%s" $serviceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $serviceName $releaseNamespace $clusterDomain) (printf "*.%s.%s.svc.%s" $headlessServiceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $headlessServiceName $releaseNamespace $clusterDomain) "127.0.0.1" "localhost" $fullname }} +{{- $cert := genSignedCert $fullname nil $altNames 365 $ca }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.crt" "defaultValue" $cert.Cert "context" $) }} + tls.key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.key" "defaultValue" $cert.Key "context" $) }} + ca.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }} +{{- end }} diff --git a/backing-services/minio/values.yaml b/backing-services/minio/values.yaml new file mode 100644 index 0000000..eb8e0ae --- /dev/null +++ b/backing-services/minio/values.yaml @@ -0,0 +1,1278 @@ +# Copyright Broadcom, Inc. All Rights Reserved. +# SPDX-License-Identifier: APACHE-2.0 + +## @section Global parameters +## 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, imagePullSecrets and storageClass + +## @param global.imageRegistry Global Docker image registry +## @param global.imagePullSecrets Global Docker registry secret names as an array +## @param global.defaultStorageClass Global default StorageClass for Persistent Volume(s) +## @param global.storageClass DEPRECATED: use global.defaultStorageClass instead +## +global: + imageRegistry: "" + ## e.g. + ## imagePullSecrets: + ## - myRegistryKeySecretName + ## + imagePullSecrets: [] + defaultStorageClass: "" + storageClass: "" + ## Security parameters + ## + security: + ## @param global.security.allowInsecureImages Allows skipping image verification + allowInsecureImages: false + ## Compatibility adaptations for Kubernetes platforms + ## + compatibility: + ## Compatibility adaptations for Openshift + ## + openshift: + ## @param global.compatibility.openshift.adaptSecurityContext Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) + ## + adaptSecurityContext: auto +## @section Common parameters + +## @param nameOverride String to partially override common.names.fullname template (will maintain the release name) +## +nameOverride: "" +## @param namespaceOverride String to fully override common.names.namespace +## +namespaceOverride: "" +## @param fullnameOverride String to fully override common.names.fullname template +## +fullnameOverride: "" +## @param commonLabels Labels to add to all deployed objects +## +commonLabels: {} +## @param commonAnnotations Annotations to add to all deployed objects +## +commonAnnotations: {} +## @param kubeVersion Force target Kubernetes version (using Helm capabilities if not set) +## +kubeVersion: "" +## @param clusterDomain Default Kubernetes cluster domain +## +clusterDomain: cluster.local +## @param extraDeploy Array of extra objects to deploy with the release +## +extraDeploy: [] +## @section MinIO® parameters + +## Bitnami MinIO® image version +## ref: https://hub.docker.com/r/bitnami/minio/tags/ +## @param image.registry [default: REGISTRY_NAME] MinIO® image registry +## @param image.repository [default: REPOSITORY_NAME/minio] MinIO® image repository +## @skip image.tag MinIO® image tag (immutable tags are recommended) +## @param image.digest MinIO® image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag +## @param image.pullPolicy Image pull policy +## @param image.pullSecrets Specify docker-registry secret names as an array +## @param image.debug Specify if debug logs should be enabled +## +image: + registry: docker.io + repository: bitnami/minio + tag: 2025.2.18-debian-12-r0 + digest: "" + ## Specify a imagePullPolicy + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Set to true if you would like to see extra information on logs + ## + debug: false +## Bitnami MinIO® Client image version +## ref: https://hub.docker.com/r/bitnami/minio-client/tags/ +## @param clientImage.registry [default: REGISTRY_NAME] MinIO® Client image registry +## @param clientImage.repository [default: REPOSITORY_NAME/minio-client] MinIO® Client image repository +## @skip clientImage.tag MinIO® Client image tag (immutable tags are recommended) +## @param clientImage.digest MinIO® Client image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag +## +clientImage: + registry: docker.io + repository: bitnami/minio-client + tag: 2025.2.15-debian-12-r0 + digest: "" +## @param mode MinIO® server mode (`standalone` or `distributed`) +## ref: https://docs.minio.io/docs/distributed-minio-quickstart-guide +## +mode: standalone +## MinIO® authentication parameters +## +auth: + ## @param auth.rootUser MinIO® root username + ## + rootUser: admin + ## @param auth.rootPassword Password for MinIO® root user + ## + rootPassword: "" + ## @param auth.existingSecret Use existing secret for credentials details (`auth.rootUser` and `auth.rootPassword` will be ignored and picked up from this secret). + ## + existingSecret: "" + ## @param auth.rootUserSecretKey Key where the MINIO_ROOT_USER username is being stored inside the existing secret `auth.existingSecret` + ## + rootUserSecretKey: "" + ## @param auth.rootPasswordSecretKey Key where the MINIO_ROOT_USER password is being stored inside the existing secret `auth.existingSecret` + ## + rootPasswordSecretKey: "" + ## @param auth.forcePassword Force users to specify required passwords + ## + forcePassword: false + ## @param auth.useCredentialsFiles Mount credentials as a files instead of using an environment variable + ## + useCredentialsFiles: false + ## @param auth.useSecret Uses a secret to mount the credential files. + ## + useSecret: true + ## @param auth.forceNewKeys Force root credentials (user and password) to be reconfigured every time they change in the secrets + ## + forceNewKeys: false +## @param defaultBuckets Comma, semi-colon or space separated list of buckets to create at initialization (only in standalone mode) +## e.g: +## defaultBuckets: "my-bucket, my-second-bucket" +## +defaultBuckets: "" +## @param disableWebUI Disable MinIO® Web UI +## ref: https://github.com/minio/minio/tree/master/docs/config/#browser +## +disableWebUI: false +## Enable tls in front of MinIO® containers. +## +tls: + ## @param tls.enabled Enable tls in front of the container + ## + enabled: false + ## @param tls.autoGenerated Generate automatically self-signed TLS certificates + ## + autoGenerated: false + ## @param tls.existingSecret Name of an existing secret holding the certificate information + ## + existingSecret: "" + ## @param tls.mountPath The mount path where the secret will be located + ## Custom mount path where the certificates will be located, if empty will default to /certs + mountPath: "" +## @param extraEnvVars Extra environment variables to be set on MinIO® container +## e.g: +## extraEnvVars: +## - name: FOO +## value: "bar" +## +extraEnvVars: [] +## @param extraEnvVarsCM ConfigMap with extra environment variables +## +extraEnvVarsCM: "" +## @param extraEnvVarsSecret Secret with extra environment variables +## +extraEnvVarsSecret: "" +## @param command Default container command (useful when using custom images). Use array form +## +command: [] +## @param args Default container args (useful when using custom images). Use array form +## +args: [] +## @section MinIO® deployment/statefulset parameters + +## @param schedulerName Specifies the schedulerName, if it's nil uses kube-scheduler +## https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +schedulerName: "" +## @param terminationGracePeriodSeconds In seconds, time the given to the MinIO pod needs to terminate gracefully +## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods +## +terminationGracePeriodSeconds: "" +## MinIO® deployment parameters +## Only when 'mode' is 'standalone' +## +deployment: + ## @param deployment.updateStrategy.type Deployment strategy type + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## e.g: + ## updateStrategy: + ## type: RollingUpdate + ## rollingUpdate: + ## maxSurge: 25% + ## maxUnavailable: 25% + ## + updateStrategy: + type: Recreate +## MinIO® statefulset parameters +## Only when mode is 'distributed' +## +statefulset: + ## @param statefulset.updateStrategy.type StatefulSet strategy type + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## e.g: + ## updateStrategy: + ## type: RollingUpdate + ## rollingUpdate: + ## maxSurge: 25% + ## maxUnavailable: 25% + ## + updateStrategy: + type: RollingUpdate + ## @param statefulset.podManagementPolicy StatefulSet controller supports relax its ordering guarantees while preserving its uniqueness and identity guarantees. There are two valid pod management policies: OrderedReady and Parallel + ## ref: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#pod-management-policy + ## + podManagementPolicy: Parallel + ## @param statefulset.replicaCount Number of pods per zone (only for MinIO® distributed mode). Should be even and `>= 4` + ## + replicaCount: 4 + ## @param statefulset.zones Number of zones (only for MinIO® distributed mode) + ## + zones: 1 + ## @param statefulset.drivesPerNode Number of drives attached to every node (only for MinIO® distributed mode) + ## + drivesPerNode: 1 +## MinIO® provisioning +## +provisioning: + ## @param provisioning.enabled Enable MinIO® provisioning Job + ## + enabled: false + ## @param provisioning.sleepTime Sleep time before checking Minio availability + ## + sleepTime: 5 + ## @param provisioning.schedulerName Name of the k8s scheduler (other than default) for MinIO® provisioning + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param provisioning.nodeSelector Node labels for pod assignment. Evaluated as a template. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/ + ## + nodeSelector: {} + ## @param provisioning.podLabels Extra labels for provisioning pods + ## Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param provisioning.podAnnotations Provisioning Pod annotations. + ## + podAnnotations: {} + ## @param provisioning.command Default provisioning container command (useful when using custom images). Use array form + ## + command: [] + ## @param provisioning.args Default provisioning container args (useful when using custom images). Use array form + ## + args: [] + ## @param provisioning.extraCommands Optionally specify extra list of additional commands for MinIO® provisioning pod + ## + extraCommands: [] + ## @param provisioning.extraVolumes Optionally specify extra list of additional volumes for MinIO® provisioning pod + ## + extraVolumes: [] + ## @param provisioning.extraVolumeMounts Optionally specify extra list of additional volumeMounts for MinIO® provisioning container + ## + extraVolumeMounts: [] + ## 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:'. + ## @param provisioning.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if provisioning.resources is set (provisioning.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param provisioning.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## @param provisioning.policies MinIO® policies provisioning + ## https://docs.min.io/docs/minio-admin-complete-guide.html#policy + ## e.g. + ## policies: + ## - name: custom-bucket-specific-policy + ## statements: + ## - resources: + ## - "arn:aws:s3:::my-bucket" + ## actions: + ## - "s3:GetBucketLocation" + ## - "s3:ListBucket" + ## - "s3:ListBucketMultipartUploads" + ## - resources: + ## - "arn:aws:s3:::my-bucket/*" + ## # Allowed values: "Allow" | "Deny" + ## # Defaults to "Deny" if not specified + ## effect: "Allow" + ## actions: + ## - "s3:AbortMultipartUpload" + ## - "s3:DeleteObject" + ## - "s3:GetObject" + ## - "s3:ListMultipartUploadParts" + ## - "s3:PutObject" + ## condition: + ## StringLike: + ## "s3:prefix": + ## - "${aws:username}/*" + policies: [] + ## @param provisioning.users MinIO® users provisioning. Can be used in addition to provisioning.usersExistingSecrets. + ## https://docs.min.io/docs/minio-admin-complete-guide.html#user + ## e.g. + ## users: + ## - username: test-username + ## password: test-password + ## disabled: false + ## policies: + ## - readwrite + ## - consoleAdmin + ## - diagnostics + ## # When set to true, it will replace all policies with the specified. + ## # When false, the policies will be added to the existing. + ## setPolicies: false + users: [] + ## @param provisioning.usersExistingSecrets Array if existing secrets containing MinIO® users to be provisioned. Can be used in addition to provisioning.users. + ## https://docs.min.io/docs/minio-admin-complete-guide.html#user + ## + ## Instead of configuring users inside values.yaml, referring to existing Kubernetes secrets containing user + ## configurations is possible. + ## e.g. + ## usersExistingSecrets: + ## - centralized-minio-users + ## + ## All provided Kubernetes secrets require a specific data structure. The same data from the provisioning.users example above + ## can be defined via secrets with the following data structure. The secret keys have no meaning to the provisioning job except that + ## they are used as filenames. + ## ## apiVersion: v1 + ## ## kind: Secret + ## ## metadata: + ## ## name: centralized-minio-users + ## ## type: Opaque + ## ## stringData: + ## ## username1: | + ## ## username=test-username + ## ## password=test-password + ## ## disabled=false + ## ## policies=readwrite,consoleAdmin,diagnostics + ## ## setPolicies=false + usersExistingSecrets: [] + ## @param provisioning.groups MinIO® groups provisioning + ## https://docs.min.io/docs/minio-admin-complete-guide.html#group + ## e.g. + ## groups + ## - name: test-group + ## disabled: false + ## members: + ## - test-username + ## policies: + ## - readwrite + ## # When set to true, it will replace all policies with the specified. + ## # When false, the policies will be added to the existing. + ## setPolicies: false + groups: [] + ## @param provisioning.buckets MinIO® buckets, versioning, lifecycle, quota and tags provisioning + ## Buckets https://docs.min.io/docs/minio-client-complete-guide.html#mb + ## Lifecycle https://docs.min.io/docs/minio-client-complete-guide.html#ilm + ## Quotas https://docs.min.io/docs/minio-admin-complete-guide.html#bucket + ## Tags https://docs.min.io/docs/minio-client-complete-guide.html#tag + ## Versioning https://docs.min.io/docs/minio-client-complete-guide.html#version + ## e.g. + ## buckets: + ## - name: test-bucket + ## region: us-east-1 + ## # Only when mode is 'distributed' + ## # Allowed values: "Versioned" | "Suspended" | "Unchanged" + ## # Defaults to "Suspended" if not specified. + ## # For compatibility, accepts boolean values as well, where true maps + ## # to "Versioned" and false to "Suspended". + ## # ref: https://docs.minio.io/docs/distributed-minio-quickstart-guide + ## versioning: Suspended + ## # Versioning is automatically enabled if withLock is true + ## # ref: https://docs.min.io/docs/minio-bucket-versioning-guide.html + ## withLock: true + ## # Only when mode is 'distributed' + ## # ref: https://docs.minio.io/docs/distributed-minio-quickstart-guide + ## lifecycle: + ## - id: TestPrefix7dRetention + ## prefix: test-prefix + ## disabled: false + ## expiry: + ## days: 7 + ## # Days !OR! date + ## # date: "2021-11-11T00:00:00Z" + ## nonconcurrentDays: 3 + ## # Only when mode is 'distributed' + ## # ref: https://docs.minio.io/docs/distributed-minio-quickstart-guide + ## quota: + ## # set (hard still works as an alias but is deprecated) or clear(+ omit size) + ## type: set + ## size: 10GiB + ## tags: + ## key1: value1 + buckets: [] + ## @param provisioning.config MinIO® config provisioning + ## https://docs.min.io/docs/minio-server-configuration-guide.html + ## e.g. + ## config: + ## - name: region + ## options: + ## name: us-east-1 + config: [] + ## MinIO® pod Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param provisioning.podSecurityContext.enabled Enable pod Security Context + ## @param provisioning.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy + ## @param provisioning.podSecurityContext.sysctls Set kernel settings using the sysctl interface + ## @param provisioning.podSecurityContext.supplementalGroups Set filesystem extra groups + ## @param provisioning.podSecurityContext.fsGroup Group ID for the container + ## + podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + sysctls: [] + supplementalGroups: [] + fsGroup: 1001 + ## MinIO® container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param provisioning.containerSecurityContext.enabled Enabled containers' Security Context + ## @param provisioning.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param provisioning.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param provisioning.containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup + ## @param provisioning.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param provisioning.containerSecurityContext.privileged Set container's Security Context privileged + ## @param provisioning.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param provisioning.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param provisioning.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param provisioning.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## Automatic Cleanup for Finished Jobs + ## @param provisioning.cleanupAfterFinished.enabled Enables Cleanup for Finished Jobs + ## @param provisioning.cleanupAfterFinished.seconds Sets the value of ttlSecondsAfterFinished + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/ + ## + cleanupAfterFinished: + enabled: false + seconds: 600 + ## Network Policy configuration + ## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ + ## + networkPolicy: + ## @param provisioning.networkPolicy.enabled Enable creation of NetworkPolicy resources + ## + enabled: true + ## @param provisioning.networkPolicy.allowExternalEgress Allow the pod to access any range of port and all destinations. + ## + allowExternalEgress: true + ## @param provisioning.networkPolicy.extraIngress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraIngress: + ## - ports: + ## - port: 1234 + ## from: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraIngress: [] + ## @param provisioning.networkPolicy.extraEgress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraEgress: + ## - ports: + ## - port: 1234 + ## to: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraEgress: [] +## @param automountServiceAccountToken Mount Service Account token in pod +## +automountServiceAccountToken: false +## @param hostAliases MinIO® pod host aliases +## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ +## +hostAliases: [] +## @param containerPorts.api MinIO® container port to open for MinIO® API +## @param containerPorts.console MinIO® container port to open for MinIO® Console +## +containerPorts: + api: 9000 + console: 9001 +## MinIO® pod Security Context +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod +## @param podSecurityContext.enabled Enable pod Security Context +## @param podSecurityContext.sysctls Set kernel settings using the sysctl interface +## @param podSecurityContext.supplementalGroups Set filesystem extra groups +## @param podSecurityContext.fsGroup Group ID for the container +## @param podSecurityContext.fsGroupChangePolicy Set filesystem group change policy +## @param podSecurityContext.sysctls Set kernel settings using the sysctl interface +## @param podSecurityContext.supplementalGroups Set filesystem extra groups +## @param podSecurityContext.fsGroupChangePolicy When K8s should preform chown on attached volumes +## +podSecurityContext: + enabled: true + sysctls: [] + supplementalGroups: [] + fsGroup: 1001 + fsGroupChangePolicy: "OnRootMismatch" +## MinIO® container Security Context +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container +## @param containerSecurityContext.enabled Enabled containers' Security Context +## @param containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container +## @param containerSecurityContext.runAsUser Set containers' Security Context runAsUser +## @param containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup +## @param containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot +## @param containerSecurityContext.privileged Set container's Security Context privileged +## @param containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem +## @param containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation +## @param containerSecurityContext.capabilities.drop List of capabilities to be dropped +## @param containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile +## +containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" +## @param podLabels Extra labels for MinIO® pods +## Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +## +podLabels: {} +## @param podAnnotations Annotations for MinIO® pods +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +## +podAnnotations: {} +## @param podAffinityPreset Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## +podAffinityPreset: "" +## @param podAntiAffinityPreset Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## +podAntiAffinityPreset: soft +## Node affinity preset +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity +## +nodeAffinityPreset: + ## @param nodeAffinityPreset.type Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param nodeAffinityPreset.key Node label key to match. Ignored if `affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param nodeAffinityPreset.values Node label values to match. Ignored if `affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] +## @param affinity Affinity for pod assignment. Evaluated as a template. +## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +## Note: podAffinityPreset, podAntiAffinityPreset, and nodeAffinityPreset will be ignored when it's set +## +affinity: {} +## @param nodeSelector Node labels for pod assignment. Evaluated as a template. +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ +## +nodeSelector: {} +## @param tolerations Tolerations for pod assignment. Evaluated as a template. +## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +## +tolerations: [] +## @param topologySpreadConstraints Topology Spread Constraints for MinIO® pods assignment spread across your cluster among failure-domains +## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#spread-constraints-for-pods +## +topologySpreadConstraints: [] +## @param priorityClassName MinIO® pods' priorityClassName +## +priorityClassName: "" +## @param runtimeClassName Name of the runtime class to be used by MinIO® pods' +## ref: https://kubernetes.io/docs/concepts/containers/runtime-class/ +## +runtimeClassName: "" +## MinIO® containers' resource requests and limits +## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ +## 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:'. +## @param resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). +## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 +## +resourcesPreset: "micro" +## @param resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) +## Example: +## resources: +## requests: +## cpu: 2 +## memory: 512Mi +## limits: +## cpu: 3 +## memory: 1024Mi +## +resources: {} +## Configure extra options for liveness probe +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes +## @param livenessProbe.enabled Enable livenessProbe +## @param livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe +## @param livenessProbe.periodSeconds Period seconds for livenessProbe +## @param livenessProbe.timeoutSeconds Timeout seconds for livenessProbe +## @param livenessProbe.failureThreshold Failure threshold for livenessProbe +## @param livenessProbe.successThreshold Success threshold for livenessProbe +## +livenessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 +## Configure extra options for readiness probe +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes +## @param readinessProbe.enabled Enable readinessProbe +## @param readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe +## @param readinessProbe.periodSeconds Period seconds for readinessProbe +## @param readinessProbe.timeoutSeconds Timeout seconds for readinessProbe +## @param readinessProbe.failureThreshold Failure threshold for readinessProbe +## @param readinessProbe.successThreshold Success threshold for readinessProbe +## +readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 5 +## Configure extra options for startupProbe probe +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes +## @param startupProbe.enabled Enable startupProbe +## @param startupProbe.initialDelaySeconds Initial delay seconds for startupProbe +## @param startupProbe.periodSeconds Period seconds for startupProbe +## @param startupProbe.timeoutSeconds Timeout seconds for startupProbe +## @param startupProbe.failureThreshold Failure threshold for startupProbe +## @param startupProbe.successThreshold Success threshold for startupProbe +## +startupProbe: + enabled: false + initialDelaySeconds: 0 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 60 +## @param customLivenessProbe Override default liveness probe +## +customLivenessProbe: {} +## @param customReadinessProbe Override default readiness probe +## +customReadinessProbe: {} +## @param customStartupProbe Override default startup probe +## +customStartupProbe: {} +## @param lifecycleHooks for the MinIO® container(s) to automate configuration before or after startup +## +lifecycleHooks: {} +## @param extraVolumes Optionally specify extra list of additional volumes for MinIO® pods +## +extraVolumes: [] +## @param extraVolumeMounts Optionally specify extra list of additional volumeMounts for MinIO® container(s) +## +extraVolumeMounts: [] +## @param initContainers Add additional init containers to the MinIO® pods +## e.g: +## initContainers: +## - name: your-image-name +## image: your-image +## imagePullPolicy: Always +## ports: +## - name: portname +## containerPort: 1234 +## +initContainers: [] +## @param sidecars Add additional sidecar containers to the MinIO® pods +## e.g: +## sidecars: +## - name: your-image-name +## image: your-image +## imagePullPolicy: Always +## ports: +## - name: portname +## containerPort: 1234 +## +sidecars: [] +## @section Traffic exposure parameters + +## MinIO® Service properties +## +service: + ## @param service.type MinIO® service type + ## + type: NodePort + ## @param service.ports.api MinIO® API service port + ## @param service.ports.console MinIO® Console service port + ## + ports: + api: 9000 + console: 9001 + ## @param service.nodePorts.api Specify the MinIO® API nodePort value for the LoadBalancer and NodePort service types + ## @param service.nodePorts.console Specify the MinIO® Console nodePort value for the LoadBalancer and NodePort service types + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + nodePorts: + api: "" + console: "" + ## @param service.clusterIP Service Cluster IP + ## e.g.: + ## clusterIP: None + ## + clusterIP: "" + ## @param service.loadBalancerIP loadBalancerIP if service type is `LoadBalancer` (optional, cloud specific) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerIP: "" + ## @param service.loadBalancerSourceRanges Addresses that are allowed when service is LoadBalancer + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param service.externalTrafficPolicy Enable client source IP preservation + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param service.extraPorts Extra ports to expose in the service (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param service.annotations Annotations for MinIO® service + ## This can be used to set the LoadBalancer service type to internal only. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + annotations: {} + ## Headless service properties + ## + headless: + ## @param service.headless.annotations Annotations for the headless service. + ## + annotations: {} +## Configure the ingress resource that allows you to access the +## MinIO® Console. Set up the URL +## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/ +## +ingress: + ## @param ingress.enabled Enable ingress controller resource for MinIO Console + ## + enabled: false + ## @param ingress.apiVersion Force Ingress API version (automatically detected if not set) + ## + apiVersion: "" + ## @param ingress.ingressClassName IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+) + ## This is supported in Kubernetes 1.18+ and required if you have more than one IngressClass marked as the default for your cluster. + ## ref: https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/ + ## + ingressClassName: "" + ## @param ingress.hostname Default host for the ingress resource + ## + hostname: minio.local + ## @param ingress.path The Path to MinIO®. You may need to set this to '/*' in order to use this with ALB ingress controllers. + ## + path: / + ## @param ingress.pathType Ingress path type + ## + pathType: ImplementationSpecific + ## @param ingress.servicePort Service port to be used + ## Default is http. Alternative is https. + ## + servicePort: minio-console + ## @param ingress.annotations Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. + ## For a full list of possible ingress annotations, please see + ## ref: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md + ## Use this parameter to set the required annotations for cert-manager, see + ## ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations + ## + ## e.g: + ## annotations: + ## kubernetes.io/ingress.class: nginx + ## cert-manager.io/cluster-issuer: cluster-issuer-name + ## + annotations: {} + ## @param ingress.tls Enable TLS configuration for the hostname defined at `ingress.hostname` parameter + ## TLS certificates will be retrieved from a TLS secret with name: `{{- printf "%s-tls" .Values.ingress.hostname }}` + ## You can: + ## - Use the `ingress.secrets` parameter to create this TLS secret + ## - Rely on cert-manager to create it by setting the corresponding annotations + ## - Rely on Helm to create self-signed certificates by setting `ingress.selfSigned=true` + ## + tls: false + ## @param ingress.selfSigned Create a TLS secret for this ingress record using self-signed certificates generated by Helm + ## + selfSigned: false + ## @param ingress.extraHosts The list of additional hostnames to be covered with this ingress record. + ## Most likely the hostname above will be enough, but in the event more hosts are needed, this is an array + ## e.g: + ## extraHosts: + ## - name: minio.local + ## path: / + ## + extraHosts: [] + ## @param ingress.extraPaths Any additional paths that may need to be added to the ingress under the main host + ## For example: The ALB ingress controller requires a special rule for handling SSL redirection. + ## extraPaths: + ## - path: /* + ## backend: + ## serviceName: ssl-redirect + ## servicePort: use-annotation + ## + extraPaths: [] + ## @param ingress.extraTls The tls configuration for additional hostnames to be covered with this ingress record. + ## see: https://kubernetes.io/docs/concepts/services-networking/ingress/#tls + ## e.g: + ## extraTls: + ## - hosts: + ## - minio.local + ## secretName: minio.local-tls + ## + extraTls: [] + ## @param ingress.secrets If you're providing your own certificates, please use this to add the certificates as secrets + ## key and certificate are expected in PEM format + ## name should line up with a secretName set further up + ## + ## If it is not set and you're using cert-manager, this is unneeded, as it will create a secret for you with valid certificates + ## If it is not set and you're NOT using cert-manager either, self-signed certificates will be created valid for 365 days + ## It is also possible to create and manage the certificates outside of this helm chart + ## Please see README.md for more information + ## + ## Example + ## secrets: + ## - name: minio.local-tls + ## key: "" + ## certificate: "" + ## + secrets: [] + ## @param ingress.extraRules Additional rules to be covered with this ingress record + ## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-rules + ## e.g: + ## extraRules: + ## - host: example.local + ## http: + ## path: / + ## backend: + ## service: + ## name: example-svc + ## port: + ## name: http + ## + extraRules: [] +## Configure the ingress resource that allows you to access the +## MinIO® API. Set up the URL +## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/ +## +apiIngress: + ## @param apiIngress.enabled Enable ingress controller resource for MinIO API + ## + enabled: false + ## @param apiIngress.apiVersion Force Ingress API version (automatically detected if not set) + ## + apiVersion: "" + ## @param apiIngress.ingressClassName IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+) + ## This is supported in Kubernetes 1.18+ and required if you have more than one IngressClass marked as the default for your cluster. + ## ref: https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/ + ## + ingressClassName: "" + ## @param apiIngress.hostname Default host for the ingress resource + ## + hostname: minio.local + ## @param apiIngress.path The Path to MinIO®. You may need to set this to '/*' in order to use this with ALB ingress controllers. + ## + path: / + ## @param apiIngress.pathType Ingress path type + ## + pathType: ImplementationSpecific + ## @param apiIngress.servicePort Service port to be used + ## Default is http. Alternative is https. + ## + servicePort: minio-api + ## @param apiIngress.annotations Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. + ## For a full list of possible ingress annotations, please see + ## ref: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md + ## Use this parameter to set the required annotations for cert-manager, see + ## ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations + ## + ## e.g: + ## annotations: + ## kubernetes.io/ingress.class: nginx + ## cert-manager.io/cluster-issuer: cluster-issuer-name + ## + annotations: {} + ## @param apiIngress.tls Enable TLS configuration for the hostname defined at `apiIngress.hostname` parameter + ## TLS certificates will be retrieved from a TLS secret with name: `{{- printf "%s-tls" .Values.apiIngress.hostname }}` + ## You can: + ## - Use the `ingress.secrets` parameter to create this TLS secret + ## - Rely on cert-manager to create it by setting the corresponding annotations + ## - Rely on Helm to create self-signed certificates by setting `ingress.selfSigned=true` + ## + tls: false + ## @param apiIngress.selfSigned Create a TLS secret for this ingress record using self-signed certificates generated by Helm + ## + selfSigned: false + ## @param apiIngress.extraHosts The list of additional hostnames to be covered with this ingress record. + ## Most likely the hostname above will be enough, but in the event more hosts are needed, this is an array + ## e.g: + ## extraHosts: + ## - name: minio.local + ## path: / + ## + extraHosts: [] + ## @param apiIngress.extraPaths Any additional paths that may need to be added to the ingress under the main host + ## For example: The ALB ingress controller requires a special rule for handling SSL redirection. + ## extraPaths: + ## - path: /* + ## backend: + ## serviceName: ssl-redirect + ## servicePort: use-annotation + ## + extraPaths: [] + ## @param apiIngress.extraTls The tls configuration for additional hostnames to be covered with this ingress record. + ## see: https://kubernetes.io/docs/concepts/services-networking/ingress/#tls + ## e.g: + ## extraTls: + ## - hosts: + ## - minio.local + ## secretName: minio.local-tls + ## + extraTls: [] + ## @param apiIngress.secrets If you're providing your own certificates, please use this to add the certificates as secrets + ## key and certificate are expected in PEM format + ## name should line up with a secretName set further up + ## + ## If it is not set and you're using cert-manager, this is unneeded, as it will create a secret for you with valid certificates + ## If it is not set and you're NOT using cert-manager either, self-signed certificates will be created valid for 365 days + ## It is also possible to create and manage the certificates outside of this helm chart + ## Please see README.md for more information + ## + ## Example + ## secrets: + ## - name: minio.local-tls + ## key: "" + ## certificate: "" + ## + secrets: [] + ## @param apiIngress.extraRules Additional rules to be covered with this ingress record + ## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-rules + ## e.g: + ## extraRules: + ## - host: example.local + ## http: + ## path: / + ## backend: + ## service: + ## name: example-svc + ## port: + ## name: http + ## + extraRules: [] +## Network Policy configuration +## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ +## +networkPolicy: + ## @param networkPolicy.enabled Enable creation of NetworkPolicy resources + ## + enabled: true + ## @param networkPolicy.allowExternal The Policy model to apply + ## When set to false, only pods with the correct client label will have network access to the ports MinIO is + ## listening on. When true, MinIO will accept connections from any source (with the correct destination port). + ## + allowExternal: true + ## @param networkPolicy.allowExternalEgress Allow the pod to access any range of port and all destinations. + ## + allowExternalEgress: true + ## @param networkPolicy.extraIngress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraIngress: + ## - ports: + ## - port: 1234 + ## from: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraIngress: [] + ## @param networkPolicy.extraEgress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraEgress: + ## - ports: + ## - port: 1234 + ## to: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraEgress: [] + ## @param networkPolicy.ingressNSMatchLabels [object] Labels to match to allow traffic from other namespaces + ## @param networkPolicy.ingressNSPodMatchLabels [object] Pod labels to match to allow traffic from other namespaces + ## + ingressNSMatchLabels: {} + ingressNSPodMatchLabels: {} +## @section Persistence parameters + +## Enable persistence using Persistent Volume Claims +## ref: https://kubernetes.io/docs/concepts/storage/persistent-volumes/ +## +persistence: + ## @param persistence.enabled Enable MinIO® data persistence using PVC. If false, use emptyDir + ## + enabled: true + ## @param persistence.storageClass PVC Storage Class for MinIO® data volume + ## 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: "" + ## @param persistence.mountPath Data volume mount path + ## + mountPath: /bitnami/minio/data + ## @param persistence.accessModes PVC Access Modes for MinIO® data volume + ## + accessModes: + - ReadWriteOnce + ## @param persistence.size PVC Storage Request for MinIO® data volume + ## + size: 8Gi + ## @param persistence.annotations Annotations for the PVC + ## + annotations: {} + ## @param persistence.existingClaim Name of an existing PVC to use (only in `standalone` mode) + ## + existingClaim: "" + ## @param persistence.selector Configure custom selector for existing Persistent Volume. (only in `distributed` mode) + ## selector: + ## matchLabels: + ## volume: + ## + selector: {} +## @section Volume Permissions parameters + +## Init containers parameters: +## volumePermissions: Change the owner and group of the persistent volume mountpoint to runAsUser:fsGroup values from the securityContext section. +## +volumePermissions: + ## @param volumePermissions.enabled Enable init container that changes the owner and group of the persistent volume(s) mountpoint to `runAsUser:fsGroup` + ## + enabled: false + ## @param volumePermissions.image.registry [default: REGISTRY_NAME] Init container volume-permissions image registry + ## @param volumePermissions.image.repository [default: REPOSITORY_NAME/os-shell] Init container volume-permissions image repository + ## @skip volumePermissions.image.tag Init container volume-permissions image tag (immutable tags are recommended) + ## @param volumePermissions.image.digest Init container volume-permissions image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param volumePermissions.image.pullPolicy Init container volume-permissions image pull policy + ## @param volumePermissions.image.pullSecrets Specify docker-registry secret names as an array + ## + image: + registry: docker.io + repository: bitnami/os-shell + tag: 12-debian-12-r38 + digest: "" + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Init container' resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## 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:'. + ## @param volumePermissions.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if volumePermissions.resources is set (volumePermissions.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param volumePermissions.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Init container' Security Context + ## Note: the chown of the data folder is done to containerSecurityContext.runAsUser + ## and not the below volumePermissions.containerSecurityContext.runAsUser + ## @param volumePermissions.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param volumePermissions.containerSecurityContext.runAsUser User ID for the init container + ## + containerSecurityContext: + seLinuxOptions: {} + runAsUser: 0 +## @section RBAC parameters + +## Specifies whether a ServiceAccount should be created +## +serviceAccount: + ## @param serviceAccount.create Enable the creation of a ServiceAccount for MinIO® pods + ## + create: true + ## @param serviceAccount.name Name of the created ServiceAccount + ## If not set and create is true, a name is generated using the common.names.fullname template + ## + name: "" + ## @param serviceAccount.automountServiceAccountToken Enable/disable auto mounting of the service account token + ## + automountServiceAccountToken: false + ## @param serviceAccount.annotations Custom annotations for MinIO® ServiceAccount + ## + annotations: {} +## @section Other parameters + +## MinIO® Pod Disruption Budget configuration in distributed mode. +## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ +## +pdb: + ## @param pdb.create Enable/disable a Pod Disruption Budget creation + ## + create: true + ## @param pdb.minAvailable Minimum number/percentage of pods that must still be available after the eviction + ## + minAvailable: "" + ## @param pdb.maxUnavailable Maximum number/percentage of pods that may be made unavailable after the eviction + ## + maxUnavailable: "" +## @section Metrics parameters +metrics: + ## @param metrics.prometheusAuthType Authentication mode for Prometheus (`jwt` or `public`) + ## To allow public access without authentication for prometheus metrics set environment as follows. + ## + prometheusAuthType: public + ## @param metrics.enabled Enable the export of Prometheus metrics + ## + enabled: false + ## Prometheus Operator ServiceMonitor configuration + ## + serviceMonitor: + ## @param metrics.serviceMonitor.enabled If the operator is installed in your cluster, set to true to create a Service Monitor Entry + ## + enabled: false + ## @param metrics.serviceMonitor.namespace Namespace which Prometheus is running in + ## + namespace: "" + ## @param metrics.serviceMonitor.labels Extra labels for the ServiceMonitor + ## + labels: {} + ## @param metrics.serviceMonitor.jobLabel The name of the label on the target service to use as the job name in Prometheus + ## + jobLabel: "" + ## DEPRECATED metrics.serviceMonitor.path - please use `metrics.serviceMonitor.paths` instead + ## + ## path: /minio/v2/metrics/cluster + ## @param metrics.serviceMonitor.paths HTTP paths to scrape for metrics + ## + paths: + - /minio/v2/metrics/cluster + - /minio/v2/metrics/node + ## @param metrics.serviceMonitor.interval Interval at which metrics should be scraped + ## + interval: 30s + ## @param metrics.serviceMonitor.scrapeTimeout Specify the timeout after which the scrape is ended + ## e.g: + ## scrapeTimeout: 30s + scrapeTimeout: "" + ## @param metrics.serviceMonitor.metricRelabelings MetricRelabelConfigs to apply to samples before ingestion + ## + metricRelabelings: [] + ## @param metrics.serviceMonitor.relabelings Metrics relabelings to add to the scrape endpoint, applied before scraping + ## + relabelings: [] + ## @param metrics.serviceMonitor.honorLabels Specify honorLabels parameter to add the scrape endpoint + ## + honorLabels: false + ## @param metrics.serviceMonitor.selector Prometheus instance selector labels + ## ref: https://github.com/bitnami/charts/tree/main/bitnami/prometheus-operator#prometheus-configuration + ## + selector: {} + ## @param metrics.serviceMonitor.apiVersion ApiVersion for the serviceMonitor Resource (defaults to "monitoring.coreos.com/v1") + apiVersion: "" + ## @param metrics.serviceMonitor.tlsConfig Additional TLS configuration for metrics endpoint with "https" scheme + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#monitoring.coreos.com/v1.TLSConfig + tlsConfig: {} + ## Prometheus Operator PrometheusRule configuration + ## + prometheusRule: + ## @param metrics.prometheusRule.enabled Create a Prometheus Operator PrometheusRule (also requires `metrics.enabled` to be `true` and `metrics.prometheusRule.rules`) + ## + enabled: false + ## @param metrics.prometheusRule.namespace Namespace for the PrometheusRule Resource (defaults to the Release Namespace) + ## + namespace: "" + ## @param metrics.prometheusRule.additionalLabels Additional labels that can be used so PrometheusRule will be discovered by Prometheus + ## + additionalLabels: {} + ## @param metrics.prometheusRule.rules Prometheus Rule definitions + # - alert: minio cluster nodes offline + # annotations: + # summary: "minio cluster nodes offline" + # description: "minio cluster nodes offline, pod {{`{{`}} $labels.pod {{`}}`}} service {{`{{`}} $labels.job {{`}}`}} offline" + # for: 10m + # expr: minio_cluster_nodes_offline_total > 0 + # labels: + # severity: critical + # group: PaaS + ## + rules: [] diff --git a/backing-services/mongodb/.helmignore b/backing-services/mongodb/.helmignore new file mode 100644 index 0000000..207983f --- /dev/null +++ b/backing-services/mongodb/.helmignore @@ -0,0 +1,25 @@ +# 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 +# img folder +img/ +# Changelog +CHANGELOG.md diff --git a/backing-services/mongodb/Chart.lock b/backing-services/mongodb/Chart.lock new file mode 100644 index 0000000..46ce374 --- /dev/null +++ b/backing-services/mongodb/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + version: 2.26.0 +digest: sha256:5ff7837915aef0067bd32271ee2b10c990774c16c4b6fe0a7c5eb6e53530ce08 +generated: "2024-10-25T12:54:49.697596669Z" diff --git a/backing-services/mongodb/Chart.yaml b/backing-services/mongodb/Chart.yaml new file mode 100644 index 0000000..1701cc1 --- /dev/null +++ b/backing-services/mongodb/Chart.yaml @@ -0,0 +1,41 @@ +annotations: + category: Database + images: | + - name: kubectl + image: docker.io/bitnami/kubectl:1.31.2-debian-12-r3 + - name: mongodb + image: docker.io/bitnami/mongodb:8.0.3-debian-12-r0 + - name: mongodb-exporter + image: docker.io/bitnami/mongodb-exporter:0.41.2-debian-12-r1 + - name: nginx + image: docker.io/bitnami/nginx:1.27.2-debian-12-r2 + - name: os-shell + image: docker.io/bitnami/os-shell:12-debian-12-r32 + licenses: Apache-2.0 +apiVersion: v2 +appVersion: 8.0.3 +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + tags: + - bitnami-common + version: 2.x.x +description: MongoDB(R) is a relational open source NoSQL database. Easy to use, it + stores data in JSON-like documents. Automated scalability and high-performance. + Ideal for developing cloud native applications. +home: https://bitnami.com +icon: https://bitnami.com/assets/stacks/mongodb/img/mongodb-stack-220x234.png +keywords: +- mongodb +- database +- nosql +- cluster +- replicaset +- replication +maintainers: +- name: Broadcom, Inc. All Rights Reserved. + url: https://github.com/bitnami/charts +name: mongodb +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/mongodb +version: 16.2.1 diff --git a/backing-services/mongodb/README.md b/backing-services/mongodb/README.md new file mode 100644 index 0000000..9a27623 --- /dev/null +++ b/backing-services/mongodb/README.md @@ -0,0 +1,1182 @@ + + +# MongoDB(R) packaged by Bitnami + +MongoDB(R) is a relational open source NoSQL database. Easy to use, it stores data in JSON-like documents. Automated scalability and high-performance. Ideal for developing cloud native applications. + +[Overview of MongoDB®](http://www.mongodb.org) + +Disclaimer: The respective trademarks mentioned in the offering are owned by the respective companies. We do not provide a commercial license for any of these products. This listing has an open-source license. MongoDB(R) is run and maintained by MongoDB, which is a completely separate project from Bitnami. + +## TL;DR + +```console +helm install my-release oci://registry-1.docker.io/bitnamicharts/mongodb +``` + +Looking to use MongoDBreg; in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the commercial edition of the Bitnami catalog. + +## Introduction + +This chart bootstraps a [MongoDB(®)](https://github.com/bitnami/containers/tree/main/bitnami/mongodb) deployment on a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters. + +## Architecture + +This chart allows installing MongoDB(®) using two different architecture setups: `standalone` or `replicaset`. Use the `architecture` parameter to choose the one to use: + +```console +architecture="standalone" +architecture="replicaset" +``` + +### Standalone architecture + +The *standalone* architecture installs a deployment (or StatefulSet) with one MongoDB® server (it cannot be scaled): + +```text + ---------------- + | MongoDB® | + | svc | + ---------------- + | + v + ------------ + |MongoDB®| + | Server | + | Pod | + ----------- +``` + +### Replicaset architecture + +The chart also supports the *replicaset* architecture with and without a MongoDB(®) Arbiter: + +When the MongoDB(®) Arbiter is enabled, the chart installs two StatefulSets: A StatefulSet with N MongoDB(®) servers (organised with one primary and N-1 secondary nodes), and a StatefulSet with one MongoDB(®) arbiter node (it cannot be scaled). + +```text + ---------------- ---------------- ---------------- ------------- + | MongoDB® 0 | | MongoDB® 1 | | MongoDB® N | | Arbiter | + | external svc | | external svc | | external svc | | svc | + ---------------- ---------------- ---------------- ------------- + | | | | + v v v v + ---------------- ---------------- ---------------- -------------- + | MongoDB® 0 | | MongoDB® 1 | | MongoDB® N | | MongoDB® | + | Server | | Server | | Server | | Arbiter | + | Pod | | Pod | | Pod | | Pod | + ---------------- ---------------- ---------------- -------------- + primary secondary secondary +``` + +The PSA model is useful when the third Availability Zone cannot hold a full MongoDB(®) instance. The MongoDB(®) Arbiter as decision maker is lightweight and can run alongside other workloads. + +> NOTE: An update takes your MongoDB(®) replicaset offline if the Arbiter is enabled and the number of MongoDB(®) replicas is two. Helm applies updates to the StatefulSets for the MongoDB(®) instance and the Arbiter at the same time so you lose two out of three quorum votes. + +Without the Arbiter, the chart deploys a single statefulset with N MongoDB(®) servers (organised with one primary and N-1 secondary nodes). + +```text + ---------------- ---------------- ---------------- + | MongoDB® 0 | | MongoDB® 1 | | MongoDB® N | + | external svc | | external svc | | external svc | + ---------------- ---------------- ---------------- + | | | + v v v + ---------------- ---------------- ---------------- + | MongoDB® 0 | | MongoDB® 1 | | MongoDB® N | + | Server | | Server | | Server | + | Pod | | Pod | | Pod | + ---------------- ---------------- ---------------- + primary secondary secondary +``` + +There are no services load balancing requests between MongoDB(®) nodes; instead, each node has an associated service to access them individually. + +> NOTE: Although the first replica is initially assigned the primary role, any of the secondary nodes can become the primary if it is down, or during upgrades. Do not make any assumption about what replica has the primary role. Instead, configure your MongoDB(®) client with the list of MongoDB(®) hostnames so it can dynamically choose the node to send requests. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ +- 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 oci://REGISTRY_NAME/REPOSITORY_NAME/mongodb +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The command deploys MongoDB(®) 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` + +## Configuration and installation details + +### Resource requests and limits + +Bitnami charts allow setting resource requests and limits for all containers inside the chart deployment. These are inside the `resources` value (check parameter table). Setting requests is essential for production workloads and these should be adapted to your specific use case. + +To make this process easier, the chart contains the `resourcesPreset` values, which automatically sets the `resources` section according to different presets. Check these presets in [the bitnami/common chart](https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15). However, in production workloads using `resourcePreset` is discouraged as it may not fully adapt to your specific needs. Find more information on container resource management in the [official Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). + +### [Rolling vs Immutable tags](https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-understand-rolling-tags-containers-index.html) + +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. + +### Customize a new MongoDB instance + +The [Bitnami MongoDB(®) image](https://github.com/bitnami/containers/tree/main/bitnami/mongodb) supports the use of custom scripts to initialize a fresh instance. In order to execute the scripts, two options are available: + +- Specify them using the `initdbScripts` parameter as dict. +- Define an external Kubernetes ConfigMap with all the initialization scripts by setting the `initdbScriptsConfigMap` parameter. Note that this will override the previous option. + +The allowed script extensions are `.sh` and `.js`. + +### Replicaset: Access MongoDB(®) nodes from outside the cluster + +In order to access MongoDB(®) nodes from outside the cluster when using a replicaset architecture, a specific service per MongoDB(®) pod will be created. There are two ways of configuring external access: + +- Using LoadBalancer services +- Using NodePort services. + +#### Use LoadBalancer services + +Three alternatives are available to use *LoadBalancer* services: + +- Use random load balancer IP addresses using an *initContainer* that waits for the IP addresses to be ready and discovers them automatically. An example deployment configuration is shown below: + + ```yaml + architecture: replicaset + replicaCount: 2 + externalAccess: + enabled: true + service: + type: LoadBalancer + autoDiscovery: + enabled: true + serviceAccount: + create: true + automountServiceAccountToken: true + rbac: + create: true + ``` + + > NOTE: This option requires creating RBAC rules on clusters where RBAC policies are enabled. + +- Manually specify the load balancer IP addresses. An example deployment configuration is shown below, with the placeholder EXTERNAL-IP-ADDRESS-X used in place of the load balancer IP addresses: + + ```yaml + architecture: replicaset + replicaCount: 2 + externalAccess: + enabled: true + service: + type: LoadBalancer + loadBalancerIPs: + - 'EXTERNAL-IP-ADDRESS-1' + - 'EXTERNAL-IP-ADDRESS-2' + ``` + + > NOTE: This option requires knowing the load balancer IP addresses, so that each MongoDB® node's advertised hostname is configured with it. + +- Specify `externalAccess.service.publicNames`. These names must be resolvable by the MongoDB® containers. To ensure that, if this value is set, an initContainer is added to wait for the ip addresses associated to those names. We can combine this feature with `external-dns`, setting the required annotations to configure the load balancer names: + + ```yaml + architecture: replicaset + replicaCount: 2 + externalAccess: + enabled: true + service: + type: LoadBalancer + publicNames: + - 'mongodb-0.example.com' + - 'mongodb-1.example.com' + annotationsList: + - external-dns.alpha.kubernetes.io/hostname: mongodb-0.example.com + - external-dns.alpha.kubernetes.io/hostname: mongodb-1.example.com + ``` + + > NOTE: If register new DNS records for those names is not an option, the release can be upgraded setting `hostAliases` with the public IPs assigned to the external services. + +#### Use NodePort services + +Manually specify the node ports to use. An example deployment configuration is shown below, with the placeholder NODE-PORT-X used in place of the node ports: + +```text +architecture=replicaset +replicaCount=2 +externalAccess.enabled=true +externalAccess.service.type=NodePort +externalAccess.service.nodePorts[0]='NODE-PORT-1' +externalAccess.service.nodePorts[1]='NODE-PORT-2' +``` + +> NOTE: This option requires knowing the node ports that will be exposed, so each MongoDB® node's advertised hostname is configured with it. + +The pod will try to get the external IP address of the node using the command `curl -s https://ipinfo.io/IP-ADDRESS` unless the `externalAccess.service.domain` parameter is set. + +### Bootstrapping with an External Cluster + +This chart is equipped with the ability to bring online a set of Pods that connect to an existing MongoDB(®) deployment that lies outside of Kubernetes. This effectively creates a hybrid MongoDB(®) Deployment where both Pods in Kubernetes and Instances such as Virtual Machines can partake in a single MongoDB(®) Deployment. This is helpful in situations where one may be migrating MongoDB(®) from Virtual Machines into Kubernetes, for example. To take advantage of this, use the following as an example configuration: + +```yaml +externalAccess: + externalMaster: + enabled: true + host: external-mongodb-0.internal +``` + +:warning: To bootstrap MongoDB(®) with an external master that lies outside of Kubernetes, be sure to set up external access using any of the suggested methods in this chart to have connectivity between the MongoDB(®) members. :warning: + +### Add extra environment variables + +To add extra environment variables (useful for advanced operations like custom init scripts), use the `extraEnvVars` property. + +```yaml +extraEnvVars: + - name: LOG_LEVEL + value: error +``` + +Alternatively, you can use a ConfigMap or a Secret with the environment variables. To do so, use the `extraEnvVarsCM` or the `extraEnvVarsSecret` properties. + +### Use Sidecars and Init Containers + +If additional containers are needed in the same pod (such as additional metrics or logging exporters), they can be defined using the `sidecars` config parameter. + +```yaml +sidecars: +- name: your-image-name + image: your-image + imagePullPolicy: Always + ports: + - name: portname + containerPort: 1234 +``` + +If these sidecars export extra ports, extra port definitions can be added using the `service.extraPorts` parameter (where available), as shown in the example below: + +```yaml +service: + extraPorts: + - name: extraPort + port: 11311 + targetPort: 11311 +``` + +> NOTE: This Helm chart already includes sidecar containers for the Prometheus exporters (where applicable). These can be activated by adding the `--enable-metrics=true` parameter at deployment time. The `sidecars` parameter should therefore only be used for any extra sidecar containers. + +If additional init containers are needed in the same pod, they can be defined using the `initContainers` parameter. Here is an example: + +```yaml +initContainers: + - name: your-image-name + image: your-image + imagePullPolicy: Always + ports: + - name: portname + containerPort: 1234 +``` + +Learn more about [sidecar containers](https://kubernetes.io/docs/concepts/workloads/pods/) and [init containers](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/). + +### Backup and restore MongoDB(R) deployments + +Two different approaches are available to back up and restore Bitnami MongoDB® Helm chart deployments on Kubernetes: + +- Back up the data from the source deployment and restore it in a new deployment using MongoDB® built-in backup/restore tools. +- Back up the persistent volumes from the source deployment and attach them to a new deployment using Velero, a Kubernetes backup/restore tool. + +#### Method 1: Backup and restore data using MongoDB® built-in tools + +This method involves the following steps: + +- Use the *mongodump* tool to create a snapshot of the data in the source cluster. +- Create a new MongoDB® Cluster deployment and forward the MongoDB® Cluster service port for the new deployment. +- Restore the data using the *mongorestore* tool to import the backup to the new cluster. + +> NOTE: Under this approach, it is important to create the new deployment on the destination cluster using the same credentials as the original deployment on the source cluster. + +#### Method 2: Back up and restore persistent data volumes + +This method involves copying the persistent data volumes for the MongoDB® nodes and reusing them in a new deployment with [Velero](https://velero.io/), an open source Kubernetes backup/restore tool. This method is only suitable when: + +- The Kubernetes provider is [supported by Velero](https://velero.io/docs/latest/supported-providers/). +- Both clusters are on the same Kubernetes provider, as this is a requirement of [Velero's native support for migrating persistent volumes](https://velero.io/docs/latest/migration-case/). +- The restored deployment on the destination cluster will have the same name, namespace, topology and credentials as the original deployment on the source cluster. + +This method involves the following steps: + +- Install Velero on the source and destination clusters. +- Use Velero to back up the PersistentVolumes (PVs) used by the deployment on the source cluster. +- Use Velero to restore the backed-up PVs on the destination cluster. +- Create a new deployment on the destination cluster with the same chart, deployment name, credentials and other parameters as the original. This new deployment will use the restored PVs and hence the original data. + +Refer to our detailed [tutorial on backing up and restoring MongoDB® chart deployments on Kubernetes](https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-backup-restore-data-mongodb-kubernetes-index.html), which covers both these approaches, for more information. + +### Use custom Prometheus rules + +Custom Prometheus rules can be defined for the Prometheus Operator by using the `prometheusRule` parameter. A basic configuration example is shown below: + +```text + metrics: + enabled: true + prometheusRule: + enabled: true + rules: + - name: rule1 + rules: + - alert: HighRequestLatency + expr: job:request_latency_seconds:mean5m{job="myjob"} > 0.5 + for: 10m + labels: + severity: page + annotations: + summary: High request latency +``` + +### Enable SSL/TLS + +This chart supports enabling SSL/TLS between nodes in the cluster, as well as between MongoDB(®) clients and nodes, by setting the `MONGODB_EXTRA_FLAGS` and `MONGODB_CLIENT_EXTRA_FLAGS` container environment variables, together with the correct `MONGODB_ADVERTISED_HOSTNAME`. To enable full TLS encryption, set the `tls.enabled` parameter to `true`. + +#### Generate the self-signed certificates via pre-install Helm hooks + +The `secrets-ca.yaml` file utilizes the Helm "pre-install" hook to ensure that the certificates will only be generated on chart install. + +The `genCA()` function will create a new self-signed x509 certificate authority. The `genSignedCert()` function creates an object with the certificate and key, which are base64-encoded and used in a YAML-like object. The `genSignedCert()` function is passed the CN, an empty IP list (the nil part), the validity and the CA created previously. + +A Kubernetes Secret is used to hold the signed certificate created above, and the `initContainer` sets up the rest. Using Helm's hook annotations ensures that the certificates will only be generated on chart install. This will prevent overriding the certificates if the chart is upgraded. + +#### Use your own CA + +To use your own CA, set `tls.caCert` and `tls.caKey` with appropriate base64 encoded data. The `secrets-ca.yaml` file will utilize this data to create the Secret. + +> NOTE: Currently, only RSA private keys are supported. + +#### Use your own certificates + +To use your own certificates, set `tls.standalone.existingSecret`, `tls.replicaset.existingSecrets`, `tls.hidden.existingSecrets` and/or `tls.arbiter.existingSecret` secrets according to your needs. All of them must be references to `kubernetes.io/tls` secrets and the certificates must be created using the same CA. The CA can be added directly to each secret using the `ca.crt` key: + +```shell +kubectl create secret tls "mongodb-0-cert" --cert="mongodb-0.crt" --key="mongodb-0.key" +kubectl patch secret "mongodb-0-cert" -p="{\"data\":{\"ca.crt\": \"$(cat ca.crt | base64 -w0 )\"}}" +``` + +Or adding it to the "endpoint certificate" and setting the value `tls.pemChainIncluded`. If we reuse the example above, the `mongodb-0.crt` file should include CA cert and we shouldn't need to patch the secret to add the `ca.crt` set key. + +> NOTE: Certificates should be signed for the fully qualified domain names. If `externalAccess.service.publicNames`is set, those names should be used in the certificates set in `tls.replicaset.existingSecrets`. + +#### Access the cluster + +To access the cluster, enable the init container which generates the MongoDB(®) server/client PEM key needed to access the cluster. Please be sure to include the `$my_hostname` section with your actual hostname, and the alternative hostnames section should contain the hostnames that should be allowed access to the MongoDB(®) replicaset. Additionally, if external access is enabled, the load balancer IP addresses are added to the alternative names list. + +> NOTE: You will be generating self-signed certificates for the MongoDB(®) deployment. The init container generates a new MongoDB(®) private key which will be used to create a Certificate Authority (CA) and the public certificate for the CA. The Certificate Signing Request will be created as well and signed using the private key of the CA previously created. Finally, the PEM bundle will be created using the private key and public certificate. This process will be repeated for each node in the cluster. + +#### Start the cluster + +After the certificates have been generated and made available to the containers at the correct mount points, the MongoDB(®) server will be started with TLS enabled. The options for the TLS mode will be one of `disabled`, `allowTLS`, `preferTLS`, or `requireTLS`. This value can be changed via the `MONGODB_EXTRA_FLAGS` field using the `tlsMode` parameter. The client should now be able to connect to the TLS-enabled cluster with the provided certificates. + +### Set Pod affinity + +This chart allows you to set your custom affinity using the `XXX.affinity` parameter(s). Find more information about Pod affinity in the [Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). + +As an alternative, you can use the preset configurations for pod affinity, pod anti-affinity, and node affinity available at the [bitnami/common](https://github.com/bitnami/charts/tree/main/bitnami/common#affinities) chart. To do so, set the `XXX.podAffinityPreset`, `XXX.podAntiAffinityPreset`, or `XXX.nodeAffinityPreset` parameters. + +## Persistence + +The [Bitnami MongoDB(®)](https://github.com/bitnami/containers/tree/main/bitnami/mongodb) image stores the MongoDB(®) data and configurations at the `/bitnami/mongodb` path of the container. + +The chart mounts a [Persistent Volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) at this location. The volume is created using dynamic volume provisioning. + +If you encounter errors when working with persistent volumes, refer to our [troubleshooting guide for persistent volumes](https://docs.bitnami.com/kubernetes/faq/troubleshooting/troubleshooting-persistence-volumes/). + +## Parameters + +### Global parameters + +| Name | Description | Value | +| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | +| `global.imageRegistry` | Global Docker image registry | `""` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | +| `global.defaultStorageClass` | Global default StorageClass for Persistent Volume(s) | `""` | +| `global.storageClass` | DEPRECATED: use global.defaultStorageClass instead | `""` | +| `global.namespaceOverride` | Override the namespace for resource deployed by the chart, but can itself be overridden by the local namespaceOverride | `""` | +| `global.compatibility.openshift.adaptSecurityContext` | Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) | `auto` | + +### Common parameters + +| Name | Description | Value | +| ------------------------- | --------------------------------------------------------------------------------------------------------- | --------------- | +| `nameOverride` | String to partially override mongodb.fullname template (will maintain the release name) | `""` | +| `fullnameOverride` | String to fully override mongodb.fullname template | `""` | +| `namespaceOverride` | String to fully override common.names.namespace | `""` | +| `kubeVersion` | Force target Kubernetes version (using Helm capabilities if not set) | `""` | +| `clusterDomain` | Default Kubernetes cluster domain | `cluster.local` | +| `extraDeploy` | Array of extra objects to deploy with the release | `[]` | +| `commonLabels` | Add labels to all the deployed resources (sub-charts are not considered). Evaluated as a template | `{}` | +| `commonAnnotations` | Common annotations to add to all Mongo resources (sub-charts are not considered). Evaluated as a template | `{}` | +| `topologyKey` | Override common lib default topology key. If empty - "kubernetes.io/hostname" is used | `""` | +| `serviceBindings.enabled` | Create secret for service binding (Experimental) | `false` | +| `enableServiceLinks` | Whether information about services should be injected into pod's environment variable | `true` | +| `diagnosticMode.enabled` | Enable diagnostic mode (all probes will be disabled and the command will be overridden) | `false` | +| `diagnosticMode.command` | Command to override all containers in the deployment | `["sleep"]` | +| `diagnosticMode.args` | Args to override all containers in the deployment | `["infinity"]` | + +### MongoDB(®) parameters + +| Name | Description | Value | +| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | +| `image.registry` | MongoDB(®) image registry | `REGISTRY_NAME` | +| `image.repository` | MongoDB(®) image registry | `REPOSITORY_NAME/mongodb` | +| `image.digest` | MongoDB(®) image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `image.pullPolicy` | MongoDB(®) image pull policy | `IfNotPresent` | +| `image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `image.debug` | Set to true if you would like to see extra information on logs | `false` | +| `schedulerName` | Name of the scheduler (other than default) to dispatch pods | `""` | +| `architecture` | MongoDB(®) architecture (`standalone` or `replicaset`) | `standalone` | +| `useStatefulSet` | Set to true to use a StatefulSet instead of a Deployment (only when `architecture=standalone`) | `false` | +| `auth.enabled` | Enable authentication | `true` | +| `auth.rootUser` | MongoDB(®) root user | `root` | +| `auth.rootPassword` | MongoDB(®) root password | `""` | +| `auth.usernames` | List of custom users to be created during the initialization | `[]` | +| `auth.passwords` | List of passwords for the custom users set at `auth.usernames` | `[]` | +| `auth.databases` | List of custom databases to be created during the initialization | `[]` | +| `auth.username` | DEPRECATED: use `auth.usernames` instead | `""` | +| `auth.password` | DEPRECATED: use `auth.passwords` instead | `""` | +| `auth.database` | DEPRECATED: use `auth.databases` instead | `""` | +| `auth.replicaSetKey` | Key used for authentication in the replicaset (only when `architecture=replicaset`) | `""` | +| `auth.existingSecret` | Existing secret with MongoDB(®) credentials (keys: `mongodb-passwords`, `mongodb-root-password`, `mongodb-metrics-password`, `mongodb-replica-set-key`) | `""` | +| `tls.enabled` | Enable MongoDB(®) TLS support between nodes in the cluster as well as between mongo clients and nodes | `false` | +| `tls.mTLS.enabled` | IF TLS support is enabled, require clients to provide certificates | `true` | +| `tls.autoGenerated` | Generate a custom CA and self-signed certificates | `true` | +| `tls.existingSecret` | Existing secret with TLS certificates (keys: `mongodb-ca-cert`, `mongodb-ca-key`) | `""` | +| `tls.caCert` | Custom CA certificated (base64 encoded) | `""` | +| `tls.caKey` | CA certificate private key (base64 encoded) | `""` | +| `tls.pemChainIncluded` | Flag to denote that the Certificate Authority (CA) certificates are bundled with the endpoint cert. | `false` | +| `tls.standalone.existingSecret` | Existing secret with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. | `""` | +| `tls.replicaset.existingSecrets` | Array of existing secrets with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. | `[]` | +| `tls.hidden.existingSecrets` | Array of existing secrets with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. | `[]` | +| `tls.arbiter.existingSecret` | Existing secret with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. | `""` | +| `tls.image.registry` | Init container TLS certs setup image registry | `REGISTRY_NAME` | +| `tls.image.repository` | Init container TLS certs setup image repository | `REPOSITORY_NAME/nginx` | +| `tls.image.digest` | Init container TLS certs setup image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `tls.image.pullPolicy` | Init container TLS certs setup image pull policy | `IfNotPresent` | +| `tls.image.pullSecrets` | Init container TLS certs specify docker-registry secret names as an array | `[]` | +| `tls.extraDnsNames` | Add extra dns names to the CA, can solve x509 auth issue for pod clients | `[]` | +| `tls.mode` | Allows to set the tls mode which should be used when tls is enabled (options: `allowTLS`, `preferTLS`, `requireTLS`) | `requireTLS` | +| `tls.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if tls.resources is set (tls.resources is recommended for production). | `nano` | +| `tls.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `tls.securityContext` | Init container generate-tls-cert Security context | `{}` | +| `automountServiceAccountToken` | Mount Service Account token in pod | `false` | +| `hostAliases` | Add deployment host aliases | `[]` | +| `replicaSetName` | Name of the replica set (only when `architecture=replicaset`) | `rs0` | +| `replicaSetHostnames` | Enable DNS hostnames in the replicaset config (only when `architecture=replicaset`) | `true` | +| `enableIPv6` | Switch to enable/disable IPv6 on MongoDB(®) | `false` | +| `directoryPerDB` | Switch to enable/disable DirectoryPerDB on MongoDB(®) | `false` | +| `systemLogVerbosity` | MongoDB(®) system log verbosity level | `0` | +| `disableSystemLog` | Switch to enable/disable MongoDB(®) system log | `false` | +| `disableJavascript` | Switch to enable/disable MongoDB(®) server-side JavaScript execution | `false` | +| `enableJournal` | Switch to enable/disable MongoDB(®) Journaling | `true` | +| `configuration` | MongoDB(®) configuration file to be used for Primary and Secondary nodes | `""` | + +### replicaSetConfigurationSettings settings applied during runtime (not via configuration file) + +| Name | Description | Value | +| ----------------------------------------------- | --------------------------------------------------------------------------------------------------- | ------- | +| `replicaSetConfigurationSettings.enabled` | Enable MongoDB(®) Switch to enable/disable configuring MongoDB(®) run time rs.conf settings | `false` | +| `replicaSetConfigurationSettings.configuration` | run-time rs.conf settings | `{}` | +| `existingConfigmap` | Name of existing ConfigMap with MongoDB(®) configuration for Primary and Secondary nodes | `""` | +| `initdbScripts` | Dictionary of initdb scripts | `{}` | +| `initdbScriptsConfigMap` | Existing ConfigMap with custom initdb scripts | `""` | +| `command` | Override default container command (useful when using custom images) | `[]` | +| `args` | Override default container args (useful when using custom images) | `[]` | +| `extraFlags` | MongoDB(®) additional command line flags | `[]` | +| `extraEnvVars` | Extra environment variables to add to MongoDB(®) pods | `[]` | +| `extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars | `""` | +| `extraEnvVarsSecret` | Name of existing Secret containing extra env vars (in case of sensitive data) | `""` | + +### MongoDB(®) statefulset parameters + +| Name | Description | Value | +| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | +| `annotations` | Additional labels to be added to the MongoDB(®) statefulset. Evaluated as a template | `{}` | +| `labels` | Annotations to be added to the MongoDB(®) statefulset. Evaluated as a template | `{}` | +| `replicaCount` | Number of MongoDB(®) nodes | `2` | +| `updateStrategy.type` | Strategy to use to replace existing MongoDB(®) pods. When architecture=standalone and useStatefulSet=false, | `RollingUpdate` | +| `podManagementPolicy` | Pod management policy for MongoDB(®) | `OrderedReady` | +| `podAffinityPreset` | MongoDB(®) Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `podAntiAffinityPreset` | MongoDB(®) Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `nodeAffinityPreset.type` | MongoDB(®) Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `nodeAffinityPreset.key` | MongoDB(®) Node label key to match Ignored if `affinity` is set. | `""` | +| `nodeAffinityPreset.values` | MongoDB(®) Node label values to match. Ignored if `affinity` is set. | `[]` | +| `affinity` | MongoDB(®) Affinity for pod assignment | `{}` | +| `nodeSelector` | MongoDB(®) Node labels for pod assignment | `{}` | +| `tolerations` | MongoDB(®) Tolerations for pod assignment | `[]` | +| `topologySpreadConstraints` | MongoDB(®) Spread Constraints for Pods | `[]` | +| `lifecycleHooks` | LifecycleHook for the MongoDB(®) container(s) to automate configuration before or after startup | `{}` | +| `terminationGracePeriodSeconds` | MongoDB(®) Termination Grace Period | `""` | +| `podLabels` | MongoDB(®) pod labels | `{}` | +| `podAnnotations` | MongoDB(®) Pod annotations | `{}` | +| `priorityClassName` | Name of the existing priority class to be used by MongoDB(®) pod(s) | `""` | +| `runtimeClassName` | Name of the runtime class to be used by MongoDB(®) pod(s) | `""` | +| `podSecurityContext.enabled` | Enable MongoDB(®) pod(s)' Security Context | `true` | +| `podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `podSecurityContext.fsGroup` | Group ID for the volumes of the MongoDB(®) pod(s) | `1001` | +| `podSecurityContext.sysctls` | sysctl settings of the MongoDB(®) pod(s)' | `[]` | +| `containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `small` | +| `resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `containerPorts.mongodb` | MongoDB(®) container port | `27017` | +| `livenessProbe.enabled` | Enable livenessProbe | `true` | +| `livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `30` | +| `livenessProbe.periodSeconds` | Period seconds for livenessProbe | `20` | +| `livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `10` | +| `livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `readinessProbe.enabled` | Enable readinessProbe | `true` | +| `readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` | +| `readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `startupProbe.enabled` | Enable startupProbe | `false` | +| `startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `5` | +| `startupProbe.periodSeconds` | Period seconds for startupProbe | `20` | +| `startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `10` | +| `startupProbe.failureThreshold` | Failure threshold for startupProbe | `30` | +| `startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `customLivenessProbe` | Override default liveness probe for MongoDB(®) containers | `{}` | +| `customReadinessProbe` | Override default readiness probe for MongoDB(®) containers | `{}` | +| `customStartupProbe` | Override default startup probe for MongoDB(®) containers | `{}` | +| `initContainers` | Add additional init containers for the hidden node pod(s) | `[]` | +| `sidecars` | Add additional sidecar containers for the MongoDB(®) pod(s) | `[]` | +| `extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the MongoDB(®) container(s) | `[]` | +| `extraVolumes` | Optionally specify extra list of additional volumes to the MongoDB(®) statefulset | `[]` | +| `pdb.create` | Enable/disable a Pod Disruption Budget creation for MongoDB(®) pod(s) | `true` | +| `pdb.minAvailable` | Minimum number/percentage of MongoDB(®) pods that must still be available after the eviction | `""` | +| `pdb.maxUnavailable` | Maximum number/percentage of MongoDB(®) pods that may be made unavailable after the eviction. Defaults to `1` if both `pdb.minAvailable` and `pdb.maxUnavailable` are empty. | `""` | + +### Traffic exposure parameters + +| Name | Description | Value | +| ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | +| `service.nameOverride` | MongoDB(®) service name | `""` | +| `service.type` | Kubernetes Service type (only for standalone architecture) | `ClusterIP` | +| `service.portName` | MongoDB(®) service port name (only for standalone architecture) | `mongodb` | +| `service.ports.mongodb` | MongoDB(®) service port. | `27017` | +| `service.nodePorts.mongodb` | Port to bind to for NodePort and LoadBalancer service types (only for standalone architecture) | `""` | +| `service.clusterIP` | MongoDB(®) service cluster IP (only for standalone architecture) | `""` | +| `service.externalIPs` | Specify the externalIP value ClusterIP service type (only for standalone architecture) | `[]` | +| `service.loadBalancerIP` | loadBalancerIP for MongoDB(®) Service (only for standalone architecture) | `""` | +| `service.loadBalancerClass` | loadBalancerClass for MongoDB(®) Service (only for standalone architecture) | `""` | +| `service.loadBalancerSourceRanges` | Address(es) that are allowed when service is LoadBalancer (only for standalone architecture) | `[]` | +| `service.allocateLoadBalancerNodePorts` | Wheter to allocate node ports when service type is LoadBalancer | `true` | +| `service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `service.annotations` | Provide any additional annotations that may be required | `{}` | +| `service.externalTrafficPolicy` | service external traffic policy (only for standalone architecture) | `Local` | +| `service.sessionAffinity` | Control where client requests go, to the same pod or round-robin | `None` | +| `service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `service.headless.annotations` | Annotations for the headless service. | `{}` | +| `externalAccess.enabled` | Enable Kubernetes external cluster access to MongoDB(®) nodes (only for replicaset architecture) | `false` | +| `externalAccess.autoDiscovery.enabled` | Enable using an init container to auto-detect external IPs by querying the K8s API | `false` | +| `externalAccess.autoDiscovery.image.registry` | Init container auto-discovery image registry | `REGISTRY_NAME` | +| `externalAccess.autoDiscovery.image.repository` | Init container auto-discovery image repository | `REPOSITORY_NAME/kubectl` | +| `externalAccess.autoDiscovery.image.digest` | Init container auto-discovery image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `externalAccess.autoDiscovery.image.pullPolicy` | Init container auto-discovery image pull policy | `IfNotPresent` | +| `externalAccess.autoDiscovery.image.pullSecrets` | Init container auto-discovery image pull secrets | `[]` | +| `externalAccess.autoDiscovery.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if externalAccess.autoDiscovery.resources is set (externalAccess.autoDiscovery.resources is recommended for production). | `nano` | +| `externalAccess.autoDiscovery.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `externalAccess.dnsCheck.image.registry` | Init container dns-check image registry | `REGISTRY_NAME` | +| `externalAccess.dnsCheck.image.repository` | Init container dns-check image repository | `REPOSITORY_NAME/kubectl` | +| `externalAccess.dnsCheck.image.digest` | Init container dns-check image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `externalAccess.dnsCheck.image.pullPolicy` | Init container dns-check image pull policy | `IfNotPresent` | +| `externalAccess.dnsCheck.image.pullSecrets` | Init container dns-check image pull secrets | `[]` | +| `externalAccess.dnsCheck.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if externalAccess.autoDiscovery.resources is set (externalAccess.autoDiscovery.resources is recommended for production). | `nano` | +| `externalAccess.dnsCheck.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `externalAccess.externalMaster.enabled` | Use external master for bootstrapping | `false` | +| `externalAccess.externalMaster.host` | External master host to bootstrap from | `""` | +| `externalAccess.externalMaster.port` | Port for MongoDB(®) service external master host | `27017` | +| `externalAccess.service.type` | Kubernetes Service type for external access. Allowed values: NodePort, LoadBalancer or ClusterIP | `LoadBalancer` | +| `externalAccess.service.portName` | MongoDB(®) port name used for external access when service type is LoadBalancer | `mongodb` | +| `externalAccess.service.ports.mongodb` | MongoDB(®) port used for external access when service type is LoadBalancer | `27017` | +| `externalAccess.service.loadBalancerIPs` | Array of load balancer IPs for MongoDB(®) nodes | `[]` | +| `externalAccess.service.publicNames` | Array of public names. The size should be equal to the number of replicas. | `[]` | +| `externalAccess.service.loadBalancerClass` | loadBalancerClass when service type is LoadBalancer | `""` | +| `externalAccess.service.loadBalancerSourceRanges` | Address(es) that are allowed when service is LoadBalancer | `[]` | +| `externalAccess.service.allocateLoadBalancerNodePorts` | Whether to allocate node ports when service type is LoadBalancer | `true` | +| `externalAccess.service.externalTrafficPolicy` | MongoDB(®) service external traffic policy | `Local` | +| `externalAccess.service.nodePorts` | Array of node ports used to configure MongoDB(®) advertised hostname when service type is NodePort | `[]` | +| `externalAccess.service.domain` | Domain or external IP used to configure MongoDB(®) advertised hostname when service type is NodePort | `""` | +| `externalAccess.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `externalAccess.service.annotations` | Service annotations for external access. These annotations are common for all services created. | `{}` | +| `externalAccess.service.annotationsList` | Service annotations for eache external service. This value contains a list allowing different annotations per each external service. | `[]` | +| `externalAccess.service.sessionAffinity` | Control where client requests go, to the same pod or round-robin | `None` | +| `externalAccess.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `externalAccess.hidden.enabled` | Enable Kubernetes external cluster access to MongoDB(®) hidden nodes | `false` | +| `externalAccess.hidden.service.type` | Kubernetes Service type for external access. Allowed values: NodePort or LoadBalancer | `LoadBalancer` | +| `externalAccess.hidden.service.portName` | MongoDB(®) port name used for external access when service type is LoadBalancer | `mongodb` | +| `externalAccess.hidden.service.ports.mongodb` | MongoDB(®) port used for external access when service type is LoadBalancer | `27017` | +| `externalAccess.hidden.service.loadBalancerIPs` | Array of load balancer IPs for MongoDB(®) nodes | `[]` | +| `externalAccess.hidden.service.loadBalancerClass` | loadBalancerClass when service type is LoadBalancer | `""` | +| `externalAccess.hidden.service.loadBalancerSourceRanges` | Address(es) that are allowed when service is LoadBalancer | `[]` | +| `externalAccess.hidden.service.allocateLoadBalancerNodePorts` | Wheter to allocate node ports when service type is LoadBalancer | `true` | +| `externalAccess.hidden.service.externalTrafficPolicy` | MongoDB(®) service external traffic policy | `Local` | +| `externalAccess.hidden.service.nodePorts` | Array of node ports used to configure MongoDB(®) advertised hostname when service type is NodePort. Length must be the same as replicaCount | `[]` | +| `externalAccess.hidden.service.domain` | Domain or external IP used to configure MongoDB(®) advertised hostname when service type is NodePort | `""` | +| `externalAccess.hidden.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `externalAccess.hidden.service.annotations` | Service annotations for external access | `{}` | +| `externalAccess.hidden.service.sessionAffinity` | Control where client requests go, to the same pod or round-robin | `None` | +| `externalAccess.hidden.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | + +### Network policy parameters + +| Name | Description | Value | +| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | +| `networkPolicy.enabled` | Specifies whether a NetworkPolicy should be created | `true` | +| `networkPolicy.allowExternal` | Don't require server label for connections | `true` | +| `networkPolicy.allowExternalEgress` | Allow the pod to access any range of port and all destinations. | `true` | +| `networkPolicy.addExternalClientAccess` | Allow access from pods with client label set to "true". Ignored if `networkPolicy.allowExternal` is true. | `true` | +| `networkPolicy.extraIngress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `networkPolicy.extraEgress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `networkPolicy.ingressPodMatchLabels` | Labels to match to allow traffic from other pods. Ignored if `networkPolicy.allowExternal` is true. | `{}` | +| `networkPolicy.ingressNSMatchLabels` | Labels to match to allow traffic from other namespaces. Ignored if `networkPolicy.allowExternal` is true. | `{}` | +| `networkPolicy.ingressNSPodMatchLabels` | Pod labels to match to allow traffic from other namespaces. Ignored if `networkPolicy.allowExternal` is true. | `{}` | +| `persistence.enabled` | Enable MongoDB(®) data persistence using PVC | `true` | +| `persistence.name` | Name of the PVC and mounted volume | `datadir` | +| `persistence.medium` | Provide a medium for `emptyDir` volumes. | `""` | +| `persistence.existingClaim` | Provide an existing `PersistentVolumeClaim` (only when `architecture=standalone`) | `""` | +| `persistence.resourcePolicy` | Setting it to "keep" to avoid removing PVCs during a helm delete operation. Leaving it empty will delete PVCs after the chart deleted | `""` | +| `persistence.storageClass` | PVC Storage Class for MongoDB(®) data volume | `""` | +| `persistence.accessModes` | PV Access Mode | `["ReadWriteOnce"]` | +| `persistence.size` | PVC Storage Request for MongoDB(®) data volume | `8Gi` | +| `persistence.annotations` | PVC annotations | `{}` | +| `persistence.labels` | PVC labels | `{}` | +| `persistence.mountPath` | Path to mount the volume at | `/bitnami/mongodb` | +| `persistence.subPath` | Subdirectory of the volume to mount at | `""` | +| `persistence.volumeClaimTemplates.selector` | A label query over volumes to consider for binding (e.g. when using local volumes) | `{}` | +| `persistence.volumeClaimTemplates.requests` | Custom PVC requests attributes | `{}` | +| `persistence.volumeClaimTemplates.dataSource` | Add dataSource to the VolumeClaimTemplate | `{}` | +| `persistentVolumeClaimRetentionPolicy.enabled` | Enable Persistent volume retention policy for MongoDB(®) Statefulset | `false` | +| `persistentVolumeClaimRetentionPolicy.whenScaled` | Volume retention behavior when the replica count of the StatefulSet is reduced | `Retain` | +| `persistentVolumeClaimRetentionPolicy.whenDeleted` | Volume retention behavior that applies when the StatefulSet is deleted | `Retain` | + +### Backup parameters + +| Name | Description | Value | +| ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | +| `backup.enabled` | Enable the logical dump of the database "regularly" | `false` | +| `backup.cronjob.schedule` | Set the cronjob parameter schedule | `@daily` | +| `backup.cronjob.concurrencyPolicy` | Set the cronjob parameter concurrencyPolicy | `Allow` | +| `backup.cronjob.failedJobsHistoryLimit` | Set the cronjob parameter failedJobsHistoryLimit | `1` | +| `backup.cronjob.successfulJobsHistoryLimit` | Set the cronjob parameter successfulJobsHistoryLimit | `3` | +| `backup.cronjob.startingDeadlineSeconds` | Set the cronjob parameter startingDeadlineSeconds | `""` | +| `backup.cronjob.ttlSecondsAfterFinished` | Set the cronjob parameter ttlSecondsAfterFinished | `""` | +| `backup.cronjob.restartPolicy` | Set the cronjob parameter restartPolicy | `OnFailure` | +| `backup.cronjob.backoffLimit` | Set the cronjob parameter backoffLimit | `6` | +| `backup.cronjob.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `backup.cronjob.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `backup.cronjob.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `backup.cronjob.containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `backup.cronjob.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `backup.cronjob.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `backup.cronjob.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `backup.cronjob.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `backup.cronjob.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `backup.cronjob.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `backup.cronjob.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `none` | +| `backup.cronjob.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `backup.cronjob.command` | Set backup container's command to run | `[]` | +| `backup.cronjob.labels` | Set the cronjob labels | `{}` | +| `backup.cronjob.annotations` | Set the cronjob annotations | `{}` | +| `backup.cronjob.storage.existingClaim` | Provide an existing `PersistentVolumeClaim` (only when `architecture=standalone`) | `""` | +| `backup.cronjob.storage.resourcePolicy` | Setting it to "keep" to avoid removing PVCs during a helm delete operation. Leaving it empty will delete PVCs after the chart deleted | `""` | +| `backup.cronjob.storage.storageClass` | PVC Storage Class for the backup data volume | `""` | +| `backup.cronjob.storage.accessModes` | PV Access Mode | `["ReadWriteOnce"]` | +| `backup.cronjob.storage.size` | PVC Storage Request for the backup data volume | `8Gi` | +| `backup.cronjob.storage.annotations` | PVC annotations | `{}` | +| `backup.cronjob.storage.mountPath` | Path to mount the volume at | `/backup/mongodb` | +| `backup.cronjob.storage.subPath` | Subdirectory of the volume to mount at | `""` | +| `backup.cronjob.storage.volumeClaimTemplates.selector` | A label query over volumes to consider for binding (e.g. when using local volumes) | `{}` | + +### RBAC parameters + +| Name | Description | Value | +| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `serviceAccount.create` | Enable creation of ServiceAccount for MongoDB(®) pods | `true` | +| `serviceAccount.name` | Name of the created serviceAccount | `""` | +| `serviceAccount.annotations` | Additional Service Account annotations | `{}` | +| `serviceAccount.automountServiceAccountToken` | Allows auto mount of ServiceAccountToken on the serviceAccount created | `false` | +| `rbac.create` | Whether to create & use RBAC resources or not | `false` | +| `rbac.rules` | Custom rules to create following the role specification | `[]` | +| `podSecurityPolicy.create` | Whether to create a PodSecurityPolicy. WARNING: PodSecurityPolicy is deprecated in Kubernetes v1.21 or later, unavailable in v1.25 or later | `false` | +| `podSecurityPolicy.allowPrivilegeEscalation` | Enable privilege escalation | `false` | +| `podSecurityPolicy.privileged` | Allow privileged | `false` | +| `podSecurityPolicy.spec` | Specify the full spec to use for Pod Security Policy | `{}` | + +### Volume Permissions parameters + +| Name | Description | Value | +| -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | +| `volumePermissions.enabled` | Enable init container that changes the owner and group of the persistent volume(s) mountpoint to `runAsUser:fsGroup` | `false` | +| `volumePermissions.image.registry` | Init container volume-permissions image registry | `REGISTRY_NAME` | +| `volumePermissions.image.repository` | Init container volume-permissions image repository | `REPOSITORY_NAME/os-shell` | +| `volumePermissions.image.digest` | Init container volume-permissions image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `volumePermissions.image.pullPolicy` | Init container volume-permissions image pull policy | `IfNotPresent` | +| `volumePermissions.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `volumePermissions.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if volumePermissions.resources is set (volumePermissions.resources is recommended for production). | `nano` | +| `volumePermissions.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `volumePermissions.securityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `volumePermissions.securityContext.runAsUser` | User ID for the volumePermissions container | `0` | + +### Arbiter parameters + +| Name | Description | Value | +| ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | +| `arbiter.enabled` | Enable deploying the arbiter | `true` | +| `arbiter.automountServiceAccountToken` | Mount Service Account token in pod | `false` | +| `arbiter.hostAliases` | Add deployment host aliases | `[]` | +| `arbiter.configuration` | Arbiter configuration file to be used | `""` | +| `arbiter.existingConfigmap` | Name of existing ConfigMap with Arbiter configuration | `""` | +| `arbiter.command` | Override default container command (useful when using custom images) | `[]` | +| `arbiter.args` | Override default container args (useful when using custom images) | `[]` | +| `arbiter.extraFlags` | Arbiter additional command line flags | `[]` | +| `arbiter.extraEnvVars` | Extra environment variables to add to Arbiter pods | `[]` | +| `arbiter.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars | `""` | +| `arbiter.extraEnvVarsSecret` | Name of existing Secret containing extra env vars (in case of sensitive data) | `""` | +| `arbiter.annotations` | Additional labels to be added to the Arbiter statefulset | `{}` | +| `arbiter.labels` | Annotations to be added to the Arbiter statefulset | `{}` | +| `arbiter.topologySpreadConstraints` | MongoDB(®) Spread Constraints for arbiter Pods | `[]` | +| `arbiter.lifecycleHooks` | LifecycleHook for the Arbiter container to automate configuration before or after startup | `{}` | +| `arbiter.terminationGracePeriodSeconds` | Arbiter Termination Grace Period | `""` | +| `arbiter.updateStrategy.type` | Strategy that will be employed to update Pods in the StatefulSet | `RollingUpdate` | +| `arbiter.podManagementPolicy` | Pod management policy for MongoDB(®) | `OrderedReady` | +| `arbiter.schedulerName` | Name of the scheduler (other than default) to dispatch pods | `""` | +| `arbiter.podAffinityPreset` | Arbiter Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `arbiter.podAntiAffinityPreset` | Arbiter Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `arbiter.nodeAffinityPreset.type` | Arbiter Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `arbiter.nodeAffinityPreset.key` | Arbiter Node label key to match Ignored if `affinity` is set. | `""` | +| `arbiter.nodeAffinityPreset.values` | Arbiter Node label values to match. Ignored if `affinity` is set. | `[]` | +| `arbiter.affinity` | Arbiter Affinity for pod assignment | `{}` | +| `arbiter.nodeSelector` | Arbiter Node labels for pod assignment | `{}` | +| `arbiter.tolerations` | Arbiter Tolerations for pod assignment | `[]` | +| `arbiter.podLabels` | Arbiter pod labels | `{}` | +| `arbiter.podAnnotations` | Arbiter Pod annotations | `{}` | +| `arbiter.priorityClassName` | Name of the existing priority class to be used by Arbiter pod(s) | `""` | +| `arbiter.runtimeClassName` | Name of the runtime class to be used by Arbiter pod(s) | `""` | +| `arbiter.podSecurityContext.enabled` | Enable Arbiter pod(s)' Security Context | `true` | +| `arbiter.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `arbiter.podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `arbiter.podSecurityContext.fsGroup` | Group ID for the volumes of the Arbiter pod(s) | `1001` | +| `arbiter.podSecurityContext.sysctls` | sysctl settings of the Arbiter pod(s)' | `[]` | +| `arbiter.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `arbiter.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `arbiter.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `arbiter.containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `arbiter.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `arbiter.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `arbiter.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `arbiter.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `arbiter.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `arbiter.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `arbiter.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if arbiter.resources is set (arbiter.resources is recommended for production). | `small` | +| `arbiter.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `arbiter.containerPorts.mongodb` | MongoDB(®) arbiter container port | `27017` | +| `arbiter.livenessProbe.enabled` | Enable livenessProbe | `true` | +| `arbiter.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `30` | +| `arbiter.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `20` | +| `arbiter.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `10` | +| `arbiter.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `arbiter.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `arbiter.readinessProbe.enabled` | Enable readinessProbe | `true` | +| `arbiter.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `arbiter.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `20` | +| `arbiter.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `10` | +| `arbiter.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `arbiter.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `arbiter.startupProbe.enabled` | Enable startupProbe | `false` | +| `arbiter.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `5` | +| `arbiter.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `arbiter.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `arbiter.startupProbe.failureThreshold` | Failure threshold for startupProbe | `30` | +| `arbiter.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `arbiter.customLivenessProbe` | Override default liveness probe for Arbiter containers | `{}` | +| `arbiter.customReadinessProbe` | Override default readiness probe for Arbiter containers | `{}` | +| `arbiter.customStartupProbe` | Override default startup probe for Arbiter containers | `{}` | +| `arbiter.initContainers` | Add additional init containers for the Arbiter pod(s) | `[]` | +| `arbiter.sidecars` | Add additional sidecar containers for the Arbiter pod(s) | `[]` | +| `arbiter.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the Arbiter container(s) | `[]` | +| `arbiter.extraVolumes` | Optionally specify extra list of additional volumes to the Arbiter statefulset | `[]` | +| `arbiter.pdb.create` | Enable/disable a Pod Disruption Budget creation for Arbiter pod(s) | `true` | +| `arbiter.pdb.minAvailable` | Minimum number/percentage of Arbiter pods that should remain scheduled | `""` | +| `arbiter.pdb.maxUnavailable` | Maximum number/percentage of Arbiter pods that may be made unavailable. Defaults to `1` if both `arbiter.pdb.minAvailable` and `arbiter.pdb.maxUnavailable` are empty. | `""` | +| `arbiter.service.nameOverride` | The arbiter service name | `""` | +| `arbiter.service.ports.mongodb` | MongoDB(®) service port | `27017` | +| `arbiter.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `arbiter.service.annotations` | Provide any additional annotations that may be required | `{}` | +| `arbiter.service.headless.annotations` | Annotations for the headless service. | `{}` | + +### Hidden Node parameters + +| Name | Description | Value | +| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | +| `hidden.enabled` | Enable deploying the hidden nodes | `false` | +| `hidden.automountServiceAccountToken` | Mount Service Account token in pod | `false` | +| `hidden.hostAliases` | Add deployment host aliases | `[]` | +| `hidden.configuration` | Hidden node configuration file to be used | `""` | +| `hidden.existingConfigmap` | Name of existing ConfigMap with Hidden node configuration | `""` | +| `hidden.command` | Override default container command (useful when using custom images) | `[]` | +| `hidden.args` | Override default container args (useful when using custom images) | `[]` | +| `hidden.extraFlags` | Hidden node additional command line flags | `[]` | +| `hidden.extraEnvVars` | Extra environment variables to add to Hidden node pods | `[]` | +| `hidden.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars | `""` | +| `hidden.extraEnvVarsSecret` | Name of existing Secret containing extra env vars (in case of sensitive data) | `""` | +| `hidden.annotations` | Additional labels to be added to thehidden node statefulset | `{}` | +| `hidden.labels` | Annotations to be added to the hidden node statefulset | `{}` | +| `hidden.topologySpreadConstraints` | MongoDB(®) Spread Constraints for hidden Pods | `[]` | +| `hidden.lifecycleHooks` | LifecycleHook for the Hidden container to automate configuration before or after startup | `{}` | +| `hidden.replicaCount` | Number of hidden nodes (only when `architecture=replicaset`) | `1` | +| `hidden.terminationGracePeriodSeconds` | Hidden Termination Grace Period | `""` | +| `hidden.updateStrategy.type` | Strategy that will be employed to update Pods in the StatefulSet | `RollingUpdate` | +| `hidden.podManagementPolicy` | Pod management policy for hidden node | `OrderedReady` | +| `hidden.schedulerName` | Name of the scheduler (other than default) to dispatch pods | `""` | +| `hidden.podAffinityPreset` | Hidden node Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `hidden.podAntiAffinityPreset` | Hidden node Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `hidden.nodeAffinityPreset.type` | Hidden Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `hidden.nodeAffinityPreset.key` | Hidden Node label key to match Ignored if `affinity` is set. | `""` | +| `hidden.nodeAffinityPreset.values` | Hidden Node label values to match. Ignored if `affinity` is set. | `[]` | +| `hidden.affinity` | Hidden node Affinity for pod assignment | `{}` | +| `hidden.nodeSelector` | Hidden node Node labels for pod assignment | `{}` | +| `hidden.tolerations` | Hidden node Tolerations for pod assignment | `[]` | +| `hidden.podLabels` | Hidden node pod labels | `{}` | +| `hidden.podAnnotations` | Hidden node Pod annotations | `{}` | +| `hidden.priorityClassName` | Name of the existing priority class to be used by hidden node pod(s) | `""` | +| `hidden.runtimeClassName` | Name of the runtime class to be used by hidden node pod(s) | `""` | +| `hidden.podSecurityContext.enabled` | Enable Hidden pod(s)' Security Context | `true` | +| `hidden.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `hidden.podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `hidden.podSecurityContext.fsGroup` | Group ID for the volumes of the Hidden pod(s) | `1001` | +| `hidden.podSecurityContext.sysctls` | sysctl settings of the Hidden pod(s)' | `[]` | +| `hidden.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `hidden.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `hidden.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `hidden.containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `hidden.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `hidden.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `hidden.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `hidden.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `hidden.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `hidden.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `hidden.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if hidden.resources is set (hidden.resources is recommended for production). | `micro` | +| `hidden.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `hidden.containerPorts.mongodb` | MongoDB(®) hidden container port | `27017` | +| `hidden.livenessProbe.enabled` | Enable livenessProbe | `true` | +| `hidden.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `30` | +| `hidden.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `20` | +| `hidden.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `10` | +| `hidden.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `hidden.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `hidden.readinessProbe.enabled` | Enable readinessProbe | `true` | +| `hidden.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `hidden.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `20` | +| `hidden.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `10` | +| `hidden.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `hidden.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `hidden.startupProbe.enabled` | Enable startupProbe | `false` | +| `hidden.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `5` | +| `hidden.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `hidden.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `hidden.startupProbe.failureThreshold` | Failure threshold for startupProbe | `30` | +| `hidden.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `hidden.customLivenessProbe` | Override default liveness probe for hidden node containers | `{}` | +| `hidden.customReadinessProbe` | Override default readiness probe for hidden node containers | `{}` | +| `hidden.customStartupProbe` | Override default startup probe for MongoDB(®) containers | `{}` | +| `hidden.initContainers` | Add init containers to the MongoDB(®) Hidden pods. | `[]` | +| `hidden.sidecars` | Add additional sidecar containers for the hidden node pod(s) | `[]` | +| `hidden.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the hidden node container(s) | `[]` | +| `hidden.extraVolumes` | Optionally specify extra list of additional volumes to the hidden node statefulset | `[]` | +| `hidden.pdb.create` | Enable/disable a Pod Disruption Budget creation for hidden node pod(s) | `true` | +| `hidden.pdb.minAvailable` | Minimum number/percentage of hidden node pods that should remain scheduled | `""` | +| `hidden.pdb.maxUnavailable` | Maximum number/percentage of hidden node pods that may be made unavailable. Defaults to `1` if both `hidden.pdb.minAvailable` and `hidden.pdb.maxUnavailable` are empty. | `""` | +| `hidden.persistence.enabled` | Enable hidden node data persistence using PVC | `true` | +| `hidden.persistence.medium` | Provide a medium for `emptyDir` volumes. | `""` | +| `hidden.persistence.storageClass` | PVC Storage Class for hidden node data volume | `""` | +| `hidden.persistence.accessModes` | PV Access Mode | `["ReadWriteOnce"]` | +| `hidden.persistence.size` | PVC Storage Request for hidden node data volume | `8Gi` | +| `hidden.persistence.annotations` | PVC annotations | `{}` | +| `hidden.persistence.mountPath` | The path the volume will be mounted at, useful when using different MongoDB(®) images. | `/bitnami/mongodb` | +| `hidden.persistence.subPath` | The subdirectory of the volume to mount to, useful in dev environments | `""` | +| `hidden.persistence.volumeClaimTemplates.selector` | A label query over volumes to consider for binding (e.g. when using local volumes) | `{}` | +| `hidden.persistence.volumeClaimTemplates.requests` | Custom PVC requests attributes | `{}` | +| `hidden.persistence.volumeClaimTemplates.dataSource` | Set volumeClaimTemplate dataSource | `{}` | +| `hidden.service.nameOverride` | The hidden service name | `""` | +| `hidden.service.portName` | MongoDB(®) service port name | `mongodb` | +| `hidden.service.ports.mongodb` | MongoDB(®) service port | `27017` | +| `hidden.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `hidden.service.annotations` | Provide any additional annotations that may be required | `{}` | +| `hidden.service.headless.annotations` | Annotations for the headless service. | `{}` | + +### Metrics parameters + +| Name | Description | Value | +| -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- | +| `metrics.enabled` | Enable using a sidecar Prometheus exporter | `false` | +| `metrics.image.registry` | MongoDB(®) Prometheus exporter image registry | `REGISTRY_NAME` | +| `metrics.image.repository` | MongoDB(®) Prometheus exporter image repository | `REPOSITORY_NAME/mongodb-exporter` | +| `metrics.image.digest` | MongoDB(®) image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `metrics.image.pullPolicy` | MongoDB(®) Prometheus exporter image pull policy | `IfNotPresent` | +| `metrics.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `metrics.username` | String with username for the metrics exporter | `""` | +| `metrics.password` | String with password for the metrics exporter | `""` | +| `metrics.compatibleMode` | Enables old style mongodb-exporter metrics | `true` | +| `metrics.collector.all` | Enable all collectors. Same as enabling all individual metrics | `false` | +| `metrics.collector.diagnosticdata` | Boolean Enable collecting metrics from getDiagnosticData | `true` | +| `metrics.collector.replicasetstatus` | Boolean Enable collecting metrics from replSetGetStatus | `true` | +| `metrics.collector.dbstats` | Boolean Enable collecting metrics from dbStats | `false` | +| `metrics.collector.topmetrics` | Boolean Enable collecting metrics from top admin command | `false` | +| `metrics.collector.indexstats` | Boolean Enable collecting metrics from $indexStats | `false` | +| `metrics.collector.collstats` | Boolean Enable collecting metrics from $collStats | `false` | +| `metrics.collector.collstatsColls` | List of \.\ to get $collStats | `[]` | +| `metrics.collector.indexstatsColls` | List - List of \.\ to get $indexStats | `[]` | +| `metrics.collector.collstatsLimit` | Number - Disable collstats, dbstats, topmetrics and indexstats collector if there are more than \ collections. 0=No limit | `0` | +| `metrics.extraFlags` | String with extra flags to the metrics exporter | `""` | +| `metrics.command` | Override default container command (useful when using custom images) | `[]` | +| `metrics.args` | Override default container args (useful when using custom images) | `[]` | +| `metrics.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if metrics.resources is set (metrics.resources is recommended for production). | `nano` | +| `metrics.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `metrics.containerPort` | Port of the Prometheus metrics container | `9216` | +| `metrics.service.annotations` | Annotations for Prometheus Exporter pods. Evaluated as a template. | `{}` | +| `metrics.service.type` | Type of the Prometheus metrics service | `ClusterIP` | +| `metrics.service.ports.metrics` | Port of the Prometheus metrics service | `9216` | +| `metrics.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `metrics.livenessProbe.enabled` | Enable livenessProbe | `true` | +| `metrics.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `15` | +| `metrics.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `5` | +| `metrics.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `10` | +| `metrics.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `3` | +| `metrics.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `metrics.readinessProbe.enabled` | Enable readinessProbe | `true` | +| `metrics.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `metrics.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `5` | +| `metrics.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `10` | +| `metrics.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `3` | +| `metrics.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `metrics.startupProbe.enabled` | Enable startupProbe | `false` | +| `metrics.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `5` | +| `metrics.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `metrics.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `metrics.startupProbe.failureThreshold` | Failure threshold for startupProbe | `30` | +| `metrics.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `metrics.customLivenessProbe` | Override default liveness probe for MongoDB(®) containers | `{}` | +| `metrics.customReadinessProbe` | Override default readiness probe for MongoDB(®) containers | `{}` | +| `metrics.customStartupProbe` | Override default startup probe for MongoDB(®) containers | `{}` | +| `metrics.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the metrics container(s) | `[]` | +| `metrics.serviceMonitor.enabled` | Create ServiceMonitor Resource for scraping metrics using Prometheus Operator | `false` | +| `metrics.serviceMonitor.namespace` | Namespace which Prometheus is running in | `""` | +| `metrics.serviceMonitor.interval` | Interval at which metrics should be scraped | `30s` | +| `metrics.serviceMonitor.scrapeTimeout` | Specify the timeout after which the scrape is ended | `""` | +| `metrics.serviceMonitor.relabelings` | RelabelConfigs to apply to samples before scraping. | `[]` | +| `metrics.serviceMonitor.metricRelabelings` | MetricsRelabelConfigs to apply to samples before ingestion. | `[]` | +| `metrics.serviceMonitor.labels` | Used to pass Labels that are used by the Prometheus installed in your cluster to select Service Monitors to work with | `{}` | +| `metrics.serviceMonitor.selector` | Prometheus instance selector labels | `{}` | +| `metrics.serviceMonitor.honorLabels` | Specify honorLabels parameter to add the scrape endpoint | `false` | +| `metrics.serviceMonitor.jobLabel` | The name of the label on the target service to use as the job name in prometheus. | `""` | +| `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 | `""` | +| `metrics.prometheusRule.rules` | Rules to be created, check values for an example | `[]` | + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +helm install my-release \ + --set auth.rootPassword=secretpassword,auth.username=my-user,auth.password=my-password,auth.database=my-database \ + oci://REGISTRY_NAME/REPOSITORY_NAME/mongodb +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The above command sets the MongoDB(®) `root` account password to `secretpassword`. Additionally, it creates a standard database user named `my-user`, with the password `my-password`, who has access to a database named `my-database`. + +> NOTE: Once this chart is deployed, it is not possible to change the application's access credentials, such as usernames or passwords, using Helm. To change these application credentials after deployment, delete any persistent volumes (PVs) used by the chart and re-deploy it, or use the application's built-in administrative tools if available. + +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 oci://REGISTRY_NAME/REPOSITORY_NAME/mongodb +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> **Tip**: You can use the default [values.yaml](https://github.com/bitnami/charts/tree/main/bitnami/mongodb/values.yaml) + +## Troubleshooting + +Find more information about how to deal with common errors related to Bitnami's Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues). + +## Upgrading + +If authentication is enabled, it's necessary to set the `auth.rootPassword` (also `auth.replicaSetKey` when using a replicaset architecture) when upgrading for readiness/liveness probes to work properly. When you install this chart for the first time, some notes will be displayed providing the credentials you must use under the 'Credentials' section. Please note down the password, and run the command below to upgrade your chart: + +```console +helm upgrade my-release oci://REGISTRY_NAME/REPOSITORY_NAME/mongodb --set auth.rootPassword=[PASSWORD] (--set auth.replicaSetKey=[REPLICASETKEY]) +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> Note: you need to substitute the placeholders [PASSWORD] and [REPLICASETKEY] with the values obtained in the installation notes. + +### To 16.0.0 + +To upgrade to MongoDB `8.0` from a `7.0` deployment, the `7.0` deployment must have `featureCompatibilityVersion` set to `7.0`. Please refer to the [official documentation](https://www.mongodb.com/docs/manual/release-notes/8.0/#upgrade-procedures). + +### To 15.0.0 + +This major bump changes the following security defaults: + +- `runAsGroup` is changed from `0` to `1001` +- `readOnlyRootFilesystem` is set to `true` +- `resourcesPreset` is changed from `none` to the minimum size working in our test suites (NOTE: `resourcesPreset` is not meant for production usage, but `resources` adapted to your use case). +- `global.compatibility.openshift.adaptSecurityContext` is changed from `disabled` to `auto`. + +This could potentially break any customization or init scripts used in your deployment. If this is the case, change the default values to the previous ones. + +### To 12.0.0 + +This major release renames several values in this chart and adds missing features, in order to be inline with the rest of assets in the Bitnami charts repository. + +Affected values: + +- `strategyType` is replaced by `updateStrategy` +- `service.port` is renamed to `service.ports.mongodb` +- `service.nodePort` is renamed to `service.nodePorts.mongodb` +- `externalAccess.service.port` is renamed to `externalAccess.hidden.service.ports.mongodb` +- `rbac.role.rules` is renamed to `rbac.rules` +- `externalAccess.hidden.service.port` is renamed ot `externalAccess.hidden.service.ports.mongodb` +- `hidden.strategyType` is replaced by `hidden.updateStrategy` +- `metrics.serviceMonitor.relabellings` is renamed to `metrics.serviceMonitor.relabelings`(typo fixed) +- `metrics.serviceMonitor.additionalLabels` is renamed to `metrics.serviceMonitor.labels` + +Additionally also updates the MongoDB image dependency to it newest major, 5.0 + +### To 11.0.0 + +In this version, the mongodb-exporter bundled as part of this Helm chart was updated to a new version which, even it is not a major change, can contain breaking changes (from `0.11.X` to `0.30.X`). +Please visit the release notes from the upstream project at + +### To 10.0.0 + +[On November 13, 2020, Helm v2 support formally ended](https://github.com/helm/charts#status-of-the-project). This major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +### To 9.0.0 + +MongoDB(®) container images were updated to `4.4.x` and it can affect compatibility with older versions of MongoDB(®). Refer to the following guides to upgrade your applications: + +- [Standalone](https://docs.mongodb.com/manual/release-notes/4.4-upgrade-standalone/) +- [Replica Set](https://docs.mongodb.com/manual/release-notes/4.4-upgrade-replica-set/) + +### To 8.0.0 + +- Architecture used to configure MongoDB(®) as a replicaset was completely refactored. Now, both primary and secondary nodes are part of the same statefulset. +- Chart labels were adapted to follow the Helm charts best practices. +- This version introduces `bitnami/common`, a [library chart](https://helm.sh/docs/topics/library_charts/#helm) as a dependency. More documentation about this new utility could be found [here](https://github.com/bitnami/charts/tree/main/bitnami/common#bitnami-common-library-chart). Please, make sure that you have updated the chart dependencies before executing any upgrade. +- Several parameters were renamed or disappeared in favor of new ones on this major version. These are the most important ones: + - `replicas` is renamed to `replicaCount`. + - Authentication parameters are reorganized under the `auth.*` parameter: + - `usePassword` is renamed to `auth.enabled`. + - `mongodbRootPassword`, `mongodbUsername`, `mongodbPassword`, `mongodbDatabase`, and `replicaSet.key` are now `auth.rootPassword`, `auth.username`, `auth.password`, `auth.database`, and `auth.replicaSetKey` respectively. + - `securityContext.*` is deprecated in favor of `podSecurityContext` and `containerSecurityContext`. + - Parameters prefixed with `mongodb` are renamed removing the prefix. E.g. `mongodbEnableIPv6` is renamed to `enableIPv6`. + - Parameters affecting Arbiter nodes are reorganized under the `arbiter.*` parameter. + +Consequences: + +- Backwards compatibility is not guaranteed. To upgrade to `8.0.0`, install a new release of the MongoDB(®) chart, and migrate your data by creating a backup of the database, and restoring it on the new release. + +### To 7.0.0 + +From this version, the way of setting the ingress rules has changed. Instead of using `ingress.paths` and `ingress.hosts` as separate objects, you should now define the rules as objects inside the `ingress.hosts` value, for example: + +```yaml +ingress: + hosts: + - name: mongodb.local + path: / +``` + +### To 6.0.0 + +From this version, `mongodbEnableIPv6` is set to `false` by default in order to work properly in most k8s clusters, if you want to use IPv6 support, you need to set this variable to `true` by adding `--set mongodbEnableIPv6=true` to your `helm` command. +You can find more information in the [`bitnami/mongodb` image README](https://github.com/bitnami/containers/tree/main/bitnami/mongodb#readme). + +### To 5.0.0 + +When enabling replicaset configuration, backwards compatibility is not guaranteed unless you modify the labels used on the chart's statefulsets. +Use the workaround below to upgrade from versions previous to 5.0.0. The following example assumes that the release name is `my-release`: + +```console +kubectl delete statefulset my-release-mongodb-arbiter my-release-mongodb-primary my-release-mongodb-secondary --cascade=false +``` + +### Add extra deployment options + +To add extra deployments (useful for advanced features like sidecars), use the `extraDeploy` property. + +In the example below, you can find how to use a example here for a [MongoDB replica set pod labeler sidecar](https://github.com/combor/k8s-mongo-labeler-sidecar) to identify the primary pod and dynamically label it as the primary node: + +```yaml +extraDeploy: + - apiVersion: v1 + kind: Service + metadata: + name: mongodb-primary + namespace: default + labels: + app.kubernetes.io/component: mongodb + app.kubernetes.io/instance: mongodb + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: mongodb + spec: + type: NodePort + externalTrafficPolicy: Cluster + ports: + - name: mongodb-primary + port: 30001 + nodePort: 30001 + protocol: TCP + targetPort: mongodb + selector: + app.kubernetes.io/component: mongodb + app.kubernetes.io/instance: mongodb + app.kubernetes.io/name: mongodb + primary: "true" +``` + +## License + +Copyright © 2024 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/backing-services/mongodb/auction-onsite-alpha.values.yaml b/backing-services/mongodb/auction-onsite-alpha.values.yaml new file mode 100644 index 0000000..f9d38c6 --- /dev/null +++ b/backing-services/mongodb/auction-onsite-alpha.values.yaml @@ -0,0 +1,11 @@ +auth: + enabled: true + rootUser: root + rootPassword: "Auction12" + +serviceAccount: + create: false + +service: + nameOverride: "" + type: NodePort \ No newline at end of file diff --git a/backing-services/mongodb/auction-stage-eks.values.yaml b/backing-services/mongodb/auction-stage-eks.values.yaml new file mode 100644 index 0000000..41e1dc1 --- /dev/null +++ b/backing-services/mongodb/auction-stage-eks.values.yaml @@ -0,0 +1,70 @@ +global: + storageClass: "efs-sc" + +# persistence: +# enabled: true +# storageClass: "efs-sc" + +livenessProbe: + enabled: true + initialDelaySeconds: 60 + periodSeconds: 15 + timeoutSeconds: 10 + failureThreshold: 20 +readinessProbe: + enabled: true + initialDelaySeconds: 60 + periodSeconds: 15 + timeoutSeconds: 10 + failureThreshold: 20 +persistence: + enabled: true + storageClass: efs-sc + accessModes: + - ReadWriteOnce + size: 100M + +backup: + cronjob: + storage: + storageClass: "efs-sc" + +hidden: + persistence: + storageClass: "efs-sc" + +auth: + enabled: true + rootUser: root + rootPassword: "secret123" + +serviceAccount: + create: true + name: "mongodbservcieaccount" + annotations: + eks.amazonaws.com/role-arn: "arn:aws:iam::667294666490:role/auction-cluster-20241126163757775000000001" + +service: + nameOverride: "" + type: LoadBalancer + annotations: + service.beta.kubernetes.io/aws-load-balancer-type: "nlb" + service.beta.kubernetes.io/aws-load-balancer-type: external + service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing + service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: instance + +podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + supplementalGroups: [] + fsGroup: 1000 + +containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1000 + runAsGroup: 1000 + + +volumePermissions: + enabled: true diff --git a/backing-services/mongodb/bugx.values.yaml b/backing-services/mongodb/bugx.values.yaml new file mode 100644 index 0000000..cbb0e1b --- /dev/null +++ b/backing-services/mongodb/bugx.values.yaml @@ -0,0 +1,37 @@ +image: + registry: localhost:30516 + repository: bitnami/mongodb + tag: latest + +replicaCount: 1 + +metrics: + enabled: false + image: + registry: localhost:30516 + repository: bitnami/mongodb-exporter + tag: latest + pullPolicy: IfNotPresent + +auth: + enabled: true + rootUser: root + rootPassword: "secret123" + +serviceAccount: + create: false + +service: + nameOverride: "" + type: NodePort + +nodeSelector: + node.name: node-1 + +resources: + requests: + cpu: 1000m + memory: 1G + limits: + cpu: 1000m + memory: 1G \ No newline at end of file diff --git a/backing-services/mongodb/charts/common/.helmignore b/backing-services/mongodb/charts/common/.helmignore new file mode 100644 index 0000000..d0e1084 --- /dev/null +++ b/backing-services/mongodb/charts/common/.helmignore @@ -0,0 +1,26 @@ +# 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 +.vscode/ +# img folder +img/ +# Changelog +CHANGELOG.md diff --git a/backing-services/mongodb/charts/common/Chart.yaml b/backing-services/mongodb/charts/common/Chart.yaml new file mode 100644 index 0000000..0d437c4 --- /dev/null +++ b/backing-services/mongodb/charts/common/Chart.yaml @@ -0,0 +1,23 @@ +annotations: + category: Infrastructure + licenses: Apache-2.0 +apiVersion: v2 +appVersion: 2.26.0 +description: A Library Helm Chart for grouping common logic between bitnami charts. + This chart is not deployable by itself. +home: https://bitnami.com +icon: https://bitnami.com/downloads/logos/bitnami-mark.png +keywords: +- common +- helper +- template +- function +- bitnami +maintainers: +- name: Broadcom, Inc. All Rights Reserved. + url: https://github.com/bitnami/charts +name: common +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/common +type: library +version: 2.26.0 diff --git a/backing-services/mongodb/charts/common/README.md b/backing-services/mongodb/charts/common/README.md new file mode 100644 index 0000000..fee26c9 --- /dev/null +++ b/backing-services/mongodb/charts/common/README.md @@ -0,0 +1,235 @@ +# Bitnami Common Library Chart + +A [Helm Library Chart](https://helm.sh/docs/topics/library_charts/#helm) for grouping common logic between Bitnami charts. + +## TL;DR + +```yaml +dependencies: + - name: common + version: 2.x.x + repository: oci://registry-1.docker.io/bitnamicharts +``` + +```console +helm dependency update +``` + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "common.names.fullname" . }} +data: + myvalue: "Hello World" +``` + +Looking to use our applications in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the commercial edition of the Bitnami catalog. + +## Introduction + +This chart provides a common template helpers which can be used to develop new charts using [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ + +## Parameters + +## Special input schemas + +### ImageRoot + +```yaml +registry: + type: string + description: Docker registry where the image is located + example: docker.io + +repository: + type: string + description: Repository and image name + example: bitnami/nginx + +tag: + type: string + description: image tag + example: 1.16.1-debian-10-r63 + +pullPolicy: + type: string + description: Specify a imagePullPolicy. Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + +pullSecrets: + type: array + items: + type: string + description: Optionally specify an array of imagePullSecrets (evaluated as templates). + +debug: + type: boolean + description: Set to true if you would like to see extra information on logs + example: false + +## An instance would be: +# registry: docker.io +# repository: bitnami/nginx +# tag: 1.16.1-debian-10-r63 +# pullPolicy: IfNotPresent +# debug: false +``` + +### Persistence + +```yaml +enabled: + type: boolean + description: Whether enable persistence. + example: true + +storageClass: + type: string + description: Ghost data Persistent Volume Storage Class, If set to "-", storageClassName: "" which disables dynamic provisioning. + example: "-" + +accessMode: + type: string + description: Access mode for the Persistent Volume Storage. + example: ReadWriteOnce + +size: + type: string + description: Size the Persistent Volume Storage. + example: 8Gi + +path: + type: string + description: Path to be persisted. + example: /bitnami + +## An instance would be: +# enabled: true +# storageClass: "-" +# accessMode: ReadWriteOnce +# size: 8Gi +# path: /bitnami +``` + +### ExistingSecret + +```yaml +name: + type: string + description: Name of the existing secret. + example: mySecret +keyMapping: + description: Mapping between the expected key name and the name of the key in the existing secret. + type: object + +## An instance would be: +# name: mySecret +# keyMapping: +# password: myPasswordKey +``` + +#### Example of use + +When we store sensitive data for a deployment in a secret, some times we want to give to users the possibility of using theirs existing secrets. + +```yaml +# templates/secret.yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }} + labels: + app: {{ include "common.names.fullname" . }} +type: Opaque +data: + password: {{ .Values.password | b64enc | quote }} + +# templates/dpl.yaml +--- +... + env: + - name: PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "common.secrets.name" (dict "existingSecret" .Values.existingSecret "context" $) }} + key: {{ include "common.secrets.key" (dict "existingSecret" .Values.existingSecret "key" "password") }} +... + +# values.yaml +--- +name: mySecret +keyMapping: + password: myPasswordKey +``` + +### ValidateValue + +#### NOTES.txt + +```console +{{- $validateValueConf00 := (dict "valueKey" "path.to.value00" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value01" "secret" "secretName" "field" "password-01") -}} + +{{ include "common.validations.values.multiple.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} +``` + +If we force those values to be empty we will see some alerts + +```console +helm install test mychart --set path.to.value00="",path.to.value01="" + 'path.to.value00' must not be empty, please add '--set path.to.value00=$PASSWORD_00' to the command. To get the current value: + + export PASSWORD_00=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-00}" | base64 -d) + + 'path.to.value01' must not be empty, please add '--set path.to.value01=$PASSWORD_01' to the command. To get the current value: + + export PASSWORD_01=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-01}" | base64 -d) +``` + +## Upgrading + +### To 1.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +#### What changes were introduced in this major version? + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- Use `type: library`. [Here](https://v3.helm.sh/docs/faq/#library-chart-support) you can find more information. +- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts + +#### Considerations when upgrading to this version + +- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues +- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore +- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 + +#### Useful links + +- +- +- + +## License + +Copyright © 2024 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/backing-services/mongodb/charts/common/templates/_affinities.tpl b/backing-services/mongodb/charts/common/templates/_affinities.tpl new file mode 100644 index 0000000..d387dbe --- /dev/null +++ b/backing-services/mongodb/charts/common/templates/_affinities.tpl @@ -0,0 +1,155 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a soft nodeAffinity definition +{{ include "common.affinities.nodes.soft" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.soft" -}} +preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} + weight: 1 +{{- end -}} + +{{/* +Return a hard nodeAffinity definition +{{ include "common.affinities.nodes.hard" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.hard" -}} +requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} +{{- end -}} + +{{/* +Return a nodeAffinity definition +{{ include "common.affinities.nodes" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.nodes.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.nodes.hard" . -}} + {{- end -}} +{{- end -}} + +{{/* +Return a topologyKey definition +{{ include "common.affinities.topologyKey" (dict "topologyKey" "BAR") -}} +*/}} +{{- define "common.affinities.topologyKey" -}} +{{ .topologyKey | default "kubernetes.io/hostname" -}} +{{- end -}} + +{{/* +Return a soft podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.soft" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "extraNamespaces" (list "namespace1" "namespace2") "context" $) -}} +*/}} +{{- define "common.affinities.pods.soft" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +{{- $extraNamespaces := default (list) .extraNamespaces -}} +preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if $extraNamespaces }} + namespaces: + - {{ .context.Release.Namespace }} + {{- with $extraNamespaces }} + {{ include "common.tplvalues.render" (dict "value" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: 1 + {{- range $extraPodAffinityTerms }} + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: {{ .weight | default 1 -}} + {{- end -}} +{{- end -}} + +{{/* +Return a hard podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.hard" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "extraNamespaces" (list "namespace1" "namespace2") "context" $) -}} +*/}} +{{- define "common.affinities.pods.hard" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +{{- $extraNamespaces := default (list) .extraNamespaces -}} +requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if $extraNamespaces }} + namespaces: + - {{ .context.Release.Namespace }} + {{- with $extraNamespaces }} + {{ include "common.tplvalues.render" (dict "value" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- range $extraPodAffinityTerms }} + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- end -}} +{{- end -}} + +{{/* +Return a podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.pods" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.pods.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.pods.hard" . -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/mongodb/charts/common/templates/_capabilities.tpl b/backing-services/mongodb/charts/common/templates/_capabilities.tpl new file mode 100644 index 0000000..2fe81d3 --- /dev/null +++ b/backing-services/mongodb/charts/common/templates/_capabilities.tpl @@ -0,0 +1,229 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the target Kubernetes version +*/}} +{{- define "common.capabilities.kubeVersion" -}} +{{- default (default .Capabilities.KubeVersion.Version .Values.kubeVersion) ((.Values.global).kubeVersion) -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for poddisruptionbudget. +*/}} +{{- define "common.capabilities.policy.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.21-0" $kubeVersion) -}} +{{- print "policy/v1beta1" -}} +{{- else -}} +{{- print "policy/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "common.capabilities.networkPolicy.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.7-0" $kubeVersion) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for cronjob. +*/}} +{{- define "common.capabilities.cronjob.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.21-0" $kubeVersion) -}} +{{- print "batch/v1beta1" -}} +{{- else -}} +{{- print "batch/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for daemonset. +*/}} +{{- define "common.capabilities.daemonset.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.14-0" $kubeVersion) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for deployment. +*/}} +{{- define "common.capabilities.deployment.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.14-0" $kubeVersion) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for statefulset. +*/}} +{{- define "common.capabilities.statefulset.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.14-0" $kubeVersion) -}} +{{- print "apps/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "common.capabilities.ingress.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if (.Values.ingress).apiVersion -}} +{{- .Values.ingress.apiVersion -}} +{{- else if and (not (empty $kubeVersion)) (semverCompare "<1.14-0" $kubeVersion) -}} +{{- print "extensions/v1beta1" -}} +{{- else if and (not (empty $kubeVersion)) (semverCompare "<1.19-0" $kubeVersion) -}} +{{- print "networking.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end }} +{{- end -}} + +{{/* +Return the appropriate apiVersion for RBAC resources. +*/}} +{{- define "common.capabilities.rbac.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.17-0" $kubeVersion) -}} +{{- print "rbac.authorization.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "rbac.authorization.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for CRDs. +*/}} +{{- define "common.capabilities.crd.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.19-0" $kubeVersion) -}} +{{- print "apiextensions.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiextensions.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for APIService. +*/}} +{{- define "common.capabilities.apiService.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.10-0" $kubeVersion) -}} +{{- print "apiregistration.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiregistration.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Horizontal Pod Autoscaler. +*/}} +{{- define "common.capabilities.hpa.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" .context -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.23-0" $kubeVersion) -}} +{{- if .beta2 -}} +{{- print "autoscaling/v2beta2" -}} +{{- else -}} +{{- print "autoscaling/v2beta1" -}} +{{- end -}} +{{- else -}} +{{- print "autoscaling/v2" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Vertical Pod Autoscaler. +*/}} +{{- define "common.capabilities.vpa.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" .context -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.23-0" $kubeVersion) -}} +{{- if .beta2 -}} +{{- print "autoscaling/v2beta2" -}} +{{- else -}} +{{- print "autoscaling/v2beta1" -}} +{{- end -}} +{{- else -}} +{{- print "autoscaling/v2" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if PodSecurityPolicy is supported +*/}} +{{- define "common.capabilities.psp.supported" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if or (empty $kubeVersion) (semverCompare "<1.25-0" $kubeVersion) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if AdmissionConfiguration is supported +*/}} +{{- define "common.capabilities.admissionConfiguration.supported" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if or (empty $kubeVersion) (not (semverCompare "<1.23-0" $kubeVersion)) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for AdmissionConfiguration. +*/}} +{{- define "common.capabilities.admissionConfiguration.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.23-0" $kubeVersion) -}} +{{- print "apiserver.config.k8s.io/v1alpha1" -}} +{{- else if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "apiserver.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiserver.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for PodSecurityConfiguration. +*/}} +{{- define "common.capabilities.podSecurityConfiguration.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.23-0" $kubeVersion) -}} +{{- print "pod-security.admission.config.k8s.io/v1alpha1" -}} +{{- else if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "pod-security.admission.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "pod-security.admission.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the used Helm version is 3.3+. +A way to check the used Helm version was not introduced until version 3.3.0 with .Capabilities.HelmVersion, which contains an additional "{}}" structure. +This check is introduced as a regexMatch instead of {{ if .Capabilities.HelmVersion }} because checking for the key HelmVersion in <3.3 results in a "interface not found" error. +**To be removed when the catalog's minimun Helm version is 3.3** +*/}} +{{- define "common.capabilities.supportsHelmVersion" -}} +{{- if regexMatch "{(v[0-9])*[^}]*}}$" (.Capabilities | toString ) }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/mongodb/charts/common/templates/_compatibility.tpl b/backing-services/mongodb/charts/common/templates/_compatibility.tpl new file mode 100644 index 0000000..a61588d --- /dev/null +++ b/backing-services/mongodb/charts/common/templates/_compatibility.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return true if the detected platform is Openshift +Usage: +{{- include "common.compatibility.isOpenshift" . -}} +*/}} +{{- define "common.compatibility.isOpenshift" -}} +{{- if .Capabilities.APIVersions.Has "security.openshift.io/v1" -}} +{{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Render a compatible securityContext depending on the platform. By default it is maintained as it is. In other platforms like Openshift we remove default user/group values that do not work out of the box with the restricted-v1 SCC +Usage: +{{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) -}} +*/}} +{{- define "common.compatibility.renderSecurityContext" -}} +{{- $adaptedContext := .secContext -}} + +{{- if (((.context.Values.global).compatibility).openshift) -}} + {{- if or (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "force") (and (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "auto") (include "common.compatibility.isOpenshift" .context)) -}} + {{/* Remove incompatible user/group values that do not work in Openshift out of the box */}} + {{- $adaptedContext = omit $adaptedContext "fsGroup" "runAsUser" "runAsGroup" -}} + {{- if not .secContext.seLinuxOptions -}} + {{/* If it is an empty object, we remove it from the resulting context because it causes validation issues */}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{/* Remove empty seLinuxOptions object if global.compatibility.omitEmptySeLinuxOptions is set to true */}} +{{- if and (((.context.Values.global).compatibility).omitEmptySeLinuxOptions) (not .secContext.seLinuxOptions) -}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} +{{- end -}} +{{/* Remove fields that are disregarded when running the container in privileged mode */}} +{{- if $adaptedContext.privileged -}} + {{- $adaptedContext = omit $adaptedContext "capabilities" "seLinuxOptions" -}} +{{- end -}} +{{- omit $adaptedContext "enabled" | toYaml -}} +{{- end -}} diff --git a/backing-services/mongodb/charts/common/templates/_errors.tpl b/backing-services/mongodb/charts/common/templates/_errors.tpl new file mode 100644 index 0000000..e965365 --- /dev/null +++ b/backing-services/mongodb/charts/common/templates/_errors.tpl @@ -0,0 +1,28 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Through error when upgrading using empty passwords values that must not be empty. + +Usage: +{{- $validationError00 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password00" "secret" "secretName" "field" "password-00") -}} +{{- $validationError01 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password01" "secret" "secretName" "field" "password-01") -}} +{{ include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $validationError00 $validationError01) "context" $) }} + +Required password params: + - validationErrors - String - Required. List of validation strings to be return, if it is empty it won't throw error. + - context - Context - Required. Parent context. +*/}} +{{- define "common.errors.upgrade.passwords.empty" -}} + {{- $validationErrors := join "" .validationErrors -}} + {{- if and $validationErrors .context.Release.IsUpgrade -}} + {{- $errorString := "\nPASSWORDS ERROR: You must provide your current passwords when upgrading the release." -}} + {{- $errorString = print $errorString "\n Note that even after reinstallation, old credentials may be needed as they may be kept in persistent volume claims." -}} + {{- $errorString = print $errorString "\n Further information can be obtained at https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues/#credential-errors-while-upgrading-chart-releases" -}} + {{- $errorString = print $errorString "\n%s" -}} + {{- printf $errorString $validationErrors | fail -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/mongodb/charts/common/templates/_images.tpl b/backing-services/mongodb/charts/common/templates/_images.tpl new file mode 100644 index 0000000..76bb7ce --- /dev/null +++ b/backing-services/mongodb/charts/common/templates/_images.tpl @@ -0,0 +1,115 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Return the proper image name. +If image tag and digest are not defined, termination fallbacks to chart appVersion. +{{ include "common.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" .Values.global "chart" .Chart ) }} +*/}} +{{- define "common.images.image" -}} +{{- $registryName := default .imageRoot.registry ((.global).imageRegistry) -}} +{{- $repositoryName := .imageRoot.repository -}} +{{- $separator := ":" -}} +{{- $termination := .imageRoot.tag | toString -}} + +{{- if not .imageRoot.tag }} + {{- if .chart }} + {{- $termination = .chart.AppVersion | toString -}} + {{- end -}} +{{- end -}} +{{- if .imageRoot.digest }} + {{- $separator = "@" -}} + {{- $termination = .imageRoot.digest | toString -}} +{{- end -}} +{{- if $registryName }} + {{- printf "%s/%s%s%s" $registryName $repositoryName $separator $termination -}} +{{- else -}} + {{- printf "%s%s%s" $repositoryName $separator $termination -}} +{{- end -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead) +{{ include "common.images.pullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global) }} +*/}} +{{- define "common.images.pullSecrets" -}} + {{- $pullSecrets := list }} + + {{- range ((.global).imagePullSecrets) -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end }} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) -}} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names evaluating values as templates +{{ include "common.images.renderPullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $) }} +*/}} +{{- define "common.images.renderPullSecrets" -}} + {{- $pullSecrets := list }} + {{- $context := .context }} + + {{- range (($context.Values.global).imagePullSecrets) -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) -}} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper image version (ingores image revision/prerelease info & fallbacks to chart appVersion) +{{ include "common.images.version" ( dict "imageRoot" .Values.path.to.the.image "chart" .Chart ) }} +*/}} +{{- define "common.images.version" -}} +{{- $imageTag := .imageRoot.tag | toString -}} +{{/* regexp from https://github.com/Masterminds/semver/blob/23f51de38a0866c5ef0bfc42b3f735c73107b700/version.go#L41-L44 */}} +{{- if regexMatch `^([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?$` $imageTag -}} + {{- $version := semver $imageTag -}} + {{- printf "%d.%d.%d" $version.Major $version.Minor $version.Patch -}} +{{- else -}} + {{- print .chart.AppVersion -}} +{{- end -}} +{{- end -}} + diff --git a/backing-services/mongodb/charts/common/templates/_ingress.tpl b/backing-services/mongodb/charts/common/templates/_ingress.tpl new file mode 100644 index 0000000..7d2b879 --- /dev/null +++ b/backing-services/mongodb/charts/common/templates/_ingress.tpl @@ -0,0 +1,73 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Generate backend entry that is compatible with all Kubernetes API versions. + +Usage: +{{ include "common.ingress.backend" (dict "serviceName" "backendName" "servicePort" "backendPort" "context" $) }} + +Params: + - serviceName - String. Name of an existing service backend + - servicePort - String/Int. Port name (or number) of the service. It will be translated to different yaml depending if it is a string or an integer. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.ingress.backend" -}} +{{- $apiVersion := (include "common.capabilities.ingress.apiVersion" .context) -}} +{{- if or (eq $apiVersion "extensions/v1beta1") (eq $apiVersion "networking.k8s.io/v1beta1") -}} +serviceName: {{ .serviceName }} +servicePort: {{ .servicePort }} +{{- else -}} +service: + name: {{ .serviceName }} + port: + {{- if typeIs "string" .servicePort }} + name: {{ .servicePort }} + {{- else if or (typeIs "int" .servicePort) (typeIs "float64" .servicePort) }} + number: {{ .servicePort | int }} + {{- end }} +{{- end -}} +{{- end -}} + +{{/* +Print "true" if the API pathType field is supported +Usage: +{{ include "common.ingress.supportsPathType" . }} +*/}} +{{- define "common.ingress.supportsPathType" -}} +{{- if (semverCompare "<1.18-0" (include "common.capabilities.kubeVersion" .)) -}} +{{- print "false" -}} +{{- else -}} +{{- print "true" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the ingressClassname field is supported +Usage: +{{ include "common.ingress.supportsIngressClassname" . }} +*/}} +{{- define "common.ingress.supportsIngressClassname" -}} +{{- if semverCompare "<1.18-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "false" -}} +{{- else -}} +{{- print "true" -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if cert-manager required annotations for TLS signed +certificates are set in the Ingress annotations +Ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations +Usage: +{{ include "common.ingress.certManagerRequest" ( dict "annotations" .Values.path.to.the.ingress.annotations ) }} +*/}} +{{- define "common.ingress.certManagerRequest" -}} +{{ if or (hasKey .annotations "cert-manager.io/cluster-issuer") (hasKey .annotations "cert-manager.io/issuer") (hasKey .annotations "kubernetes.io/tls-acme") }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/mongodb/charts/common/templates/_labels.tpl b/backing-services/mongodb/charts/common/templates/_labels.tpl new file mode 100644 index 0000000..0a0cc54 --- /dev/null +++ b/backing-services/mongodb/charts/common/templates/_labels.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Kubernetes standard labels +{{ include "common.labels.standard" (dict "customLabels" .Values.commonLabels "context" $) -}} +*/}} +{{- define "common.labels.standard" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{- $default := dict "app.kubernetes.io/name" (include "common.names.name" .context) "helm.sh/chart" (include "common.names.chart" .context) "app.kubernetes.io/instance" .context.Release.Name "app.kubernetes.io/managed-by" .context.Release.Service -}} +{{- with .context.Chart.AppVersion -}} +{{- $_ := set $default "app.kubernetes.io/version" . -}} +{{- end -}} +{{ template "common.tplvalues.merge" (dict "values" (list .customLabels $default) "context" .context) }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +helm.sh/chart: {{ include "common.names.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Chart.AppVersion }} +app.kubernetes.io/version: {{ . | quote }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Labels used on immutable fields such as deploy.spec.selector.matchLabels or svc.spec.selector +{{ include "common.labels.matchLabels" (dict "customLabels" .Values.podLabels "context" $) -}} + +We don't want to loop over custom labels appending them to the selector +since it's very likely that it will break deployments, services, etc. +However, it's important to overwrite the standard labels if the user +overwrote them on metadata.labels fields. +*/}} +{{- define "common.labels.matchLabels" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{ merge (pick (include "common.tplvalues.render" (dict "value" .customLabels "context" .context) | fromYaml) "app.kubernetes.io/name" "app.kubernetes.io/instance") (dict "app.kubernetes.io/name" (include "common.names.name" .context) "app.kubernetes.io/instance" .context.Release.Name ) | toYaml }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} +{{- end -}} diff --git a/backing-services/mongodb/charts/common/templates/_names.tpl b/backing-services/mongodb/charts/common/templates/_names.tpl new file mode 100644 index 0000000..ba83956 --- /dev/null +++ b/backing-services/mongodb/charts/common/templates/_names.tpl @@ -0,0 +1,71 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "common.names.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "common.names.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "common.names.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 dependency name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +Usage: +{{ include "common.names.dependency.fullname" (dict "chartName" "dependency-chart-name" "chartValues" .Values.dependency-chart "context" $) }} +*/}} +{{- define "common.names.dependency.fullname" -}} +{{- if .chartValues.fullnameOverride -}} +{{- .chartValues.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .chartName .chartValues.nameOverride -}} +{{- if contains $name .context.Release.Name -}} +{{- .context.Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .context.Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts. +*/}} +{{- define "common.names.namespace" -}} +{{- default .Release.Namespace .Values.namespaceOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a fully qualified app name adding the installation's namespace. +*/}} +{{- define "common.names.fullname.namespace" -}} +{{- printf "%s-%s" (include "common.names.fullname" .) (include "common.names.namespace" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/backing-services/mongodb/charts/common/templates/_resources.tpl b/backing-services/mongodb/charts/common/templates/_resources.tpl new file mode 100644 index 0000000..d8a43e1 --- /dev/null +++ b/backing-services/mongodb/charts/common/templates/_resources.tpl @@ -0,0 +1,50 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a resource request/limit object based on a given preset. +These presets are for basic testing and not meant to be used in production +{{ include "common.resources.preset" (dict "type" "nano") -}} +*/}} +{{- define "common.resources.preset" -}} +{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} +{{- $presets := dict + "nano" (dict + "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "2Gi") + ) + "micro" (dict + "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "2Gi") + ) + "small" (dict + "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "2Gi") + ) + "medium" (dict + "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "2Gi") + ) + "large" (dict + "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "2Gi") + ) + "xlarge" (dict + "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "2Gi") + ) + "2xlarge" (dict + "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "2Gi") + ) + }} +{{- if hasKey $presets .type -}} +{{- index $presets .type | toYaml -}} +{{- else -}} +{{- printf "ERROR: Preset key '%s' invalid. Allowed values are %s" .type (join "," (keys $presets)) | fail -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/mongodb/charts/common/templates/_secrets.tpl b/backing-services/mongodb/charts/common/templates/_secrets.tpl new file mode 100644 index 0000000..801918c --- /dev/null +++ b/backing-services/mongodb/charts/common/templates/_secrets.tpl @@ -0,0 +1,185 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Generate secret name. + +Usage: +{{ include "common.secrets.name" (dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $) }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - defaultNameSuffix - String - Optional. It is used only if we have several secrets in the same deployment. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.secrets.name" -}} +{{- $name := (include "common.names.fullname" .context) -}} + +{{- if .defaultNameSuffix -}} +{{- $name = printf "%s-%s" $name .defaultNameSuffix | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- with .existingSecret -}} +{{- if not (typeIs "string" .) -}} +{{- with .name -}} +{{- $name = . -}} +{{- end -}} +{{- else -}} +{{- $name = . -}} +{{- end -}} +{{- end -}} + +{{- printf "%s" $name -}} +{{- end -}} + +{{/* +Generate secret key. + +Usage: +{{ include "common.secrets.key" (dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName") }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - key - String - Required. Name of the key in the secret. +*/}} +{{- define "common.secrets.key" -}} +{{- $key := .key -}} + +{{- if .existingSecret -}} + {{- if not (typeIs "string" .existingSecret) -}} + {{- if .existingSecret.keyMapping -}} + {{- $key = index .existingSecret.keyMapping $.key -}} + {{- end -}} + {{- end }} +{{- end -}} + +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Generate secret password or retrieve one if already created. + +Usage: +{{ include "common.secrets.passwords.manage" (dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - providedValues - List - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - length - int - Optional - Length of the generated random password. + - strong - Boolean - Optional - Whether to add symbols to the generated random password. + - chartName - String - Optional - Name of the chart used when said chart is deployed as a subchart. + - context - Context - Required - Parent context. + - failOnNew - Boolean - Optional - Default to true. If set to false, skip errors adding new keys to existing secrets. + - skipB64enc - Boolean - Optional - Default to false. If set to true, no the secret will not be base64 encrypted. + - skipQuote - Boolean - Optional - Default to false. If set to true, no quotes will be added around the secret. +The order in which this function returns a secret password: + 1. Already existing 'Secret' resource + (If a 'Secret' resource is found under the name provided to the 'secret' parameter to this function and that 'Secret' resource contains a key with the name passed as the 'key' parameter to this function then the value of this existing secret password will be returned) + 2. Password provided via the values.yaml + (If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned) + 3. Randomly generated secret password + (A new random secret password with the length specified in the 'length' parameter will be generated and returned) + +*/}} +{{- define "common.secrets.passwords.manage" -}} + +{{- $password := "" }} +{{- $subchart := "" }} +{{- $chartName := default "" .chartName }} +{{- $passwordLength := default 10 .length }} +{{- $providedPasswordKey := include "common.utils.getKeyFromList" (dict "keys" .providedValues "context" $.context) }} +{{- $providedPasswordValue := include "common.utils.getValueFromKey" (dict "key" $providedPasswordKey "context" $.context) }} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data }} +{{- if $secretData }} + {{- if hasKey $secretData .key }} + {{- $password = index $secretData .key | b64dec }} + {{- else if not (eq .failOnNew false) }} + {{- printf "\nPASSWORDS ERROR: The secret \"%s\" does not contain the key \"%s\"\n" .secret .key | fail -}} + {{- end -}} +{{- end }} + +{{- if not $password }} + {{- if $providedPasswordValue }} + {{- $password = $providedPasswordValue | toString }} + {{- else }} + {{- if .context.Values.enabled }} + {{- $subchart = $chartName }} + {{- end -}} + + {{- if not (eq .failOnNew false) }} + {{- $requiredPassword := dict "valueKey" $providedPasswordKey "secret" .secret "field" .key "subchart" $subchart "context" $.context -}} + {{- $requiredPasswordError := include "common.validations.values.single.empty" $requiredPassword -}} + {{- $passwordValidationErrors := list $requiredPasswordError -}} + {{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" $passwordValidationErrors "context" $.context) -}} + {{- end }} + + {{- if .strong }} + {{- $subStr := list (lower (randAlpha 1)) (randNumeric 1) (upper (randAlpha 1)) | join "_" }} + {{- $password = randAscii $passwordLength }} + {{- $password = regexReplaceAllLiteral "\\W" $password "@" | substr 5 $passwordLength }} + {{- $password = printf "%s%s" $subStr $password | toString | shuffle }} + {{- else }} + {{- $password = randAlphaNum $passwordLength }} + {{- end }} + {{- end -}} +{{- end -}} +{{- if not .skipB64enc }} +{{- $password = $password | b64enc }} +{{- end -}} +{{- if .skipQuote -}} +{{- printf "%s" $password -}} +{{- else -}} +{{- printf "%s" $password | quote -}} +{{- end -}} +{{- end -}} + +{{/* +Reuses the value from an existing secret, otherwise sets its value to a default value. + +Usage: +{{ include "common.secrets.lookup" (dict "secret" "secret-name" "key" "keyName" "defaultValue" .Values.myValue "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - defaultValue - String - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - context - Context - Required - Parent context. + +*/}} +{{- define "common.secrets.lookup" -}} +{{- $value := "" -}} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data -}} +{{- if and $secretData (hasKey $secretData .key) -}} + {{- $value = index $secretData .key -}} +{{- else if .defaultValue -}} + {{- $value = .defaultValue | toString | b64enc -}} +{{- end -}} +{{- if $value -}} +{{- printf "%s" $value -}} +{{- end -}} +{{- end -}} + +{{/* +Returns whether a previous generated secret already exists + +Usage: +{{ include "common.secrets.exists" (dict "secret" "secret-name" "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - context - Context - Required - Parent context. +*/}} +{{- define "common.secrets.exists" -}} +{{- $secret := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret) }} +{{- if $secret }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/mongodb/charts/common/templates/_storage.tpl b/backing-services/mongodb/charts/common/templates/_storage.tpl new file mode 100644 index 0000000..aa75856 --- /dev/null +++ b/backing-services/mongodb/charts/common/templates/_storage.tpl @@ -0,0 +1,21 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the proper Storage Class +{{ include "common.storage.class" ( dict "persistence" .Values.path.to.the.persistence "global" $) }} +*/}} +{{- define "common.storage.class" -}} +{{- $storageClass := (.global).storageClass | default .persistence.storageClass | default (.global).defaultStorageClass | default "" -}} +{{- if $storageClass -}} + {{- if (eq "-" $storageClass) -}} + {{- printf "storageClassName: \"\"" -}} + {{- else -}} + {{- printf "storageClassName: %s" $storageClass -}} + {{- end -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/mongodb/charts/common/templates/_tplvalues.tpl b/backing-services/mongodb/charts/common/templates/_tplvalues.tpl new file mode 100644 index 0000000..a04f4c1 --- /dev/null +++ b/backing-services/mongodb/charts/common/templates/_tplvalues.tpl @@ -0,0 +1,52 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Renders a value that contains template perhaps with scope if the scope is present. +Usage: +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ ) }} +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ "scope" $app ) }} +*/}} +{{- define "common.tplvalues.render" -}} +{{- $value := typeIs "string" .value | ternary .value (.value | toYaml) }} +{{- if contains "{{" (toJson .value) }} + {{- if .scope }} + {{- tpl (cat "{{- with $.RelativeScope -}}" $value "{{- end }}") (merge (dict "RelativeScope" .scope) .context) }} + {{- else }} + {{- tpl $value .context }} + {{- end }} +{{- else }} + {{- $value }} +{{- end }} +{{- end -}} + +{{/* +Merge a list of values that contains template after rendering them. +Merge precedence is consistent with http://masterminds.github.io/sprig/dicts.html#merge-mustmerge +Usage: +{{ include "common.tplvalues.merge" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }} +*/}} +{{- define "common.tplvalues.merge" -}} +{{- $dst := dict -}} +{{- range .values -}} +{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | merge $dst -}} +{{- end -}} +{{ $dst | toYaml }} +{{- end -}} + +{{/* +Merge a list of values that contains template after rendering them. +Merge precedence is consistent with https://masterminds.github.io/sprig/dicts.html#mergeoverwrite-mustmergeoverwrite +Usage: +{{ include "common.tplvalues.merge-overwrite" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }} +*/}} +{{- define "common.tplvalues.merge-overwrite" -}} +{{- $dst := dict -}} +{{- range .values -}} +{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | mergeOverwrite $dst -}} +{{- end -}} +{{ $dst | toYaml }} +{{- end -}} diff --git a/backing-services/mongodb/charts/common/templates/_utils.tpl b/backing-services/mongodb/charts/common/templates/_utils.tpl new file mode 100644 index 0000000..d53c74a --- /dev/null +++ b/backing-services/mongodb/charts/common/templates/_utils.tpl @@ -0,0 +1,77 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Print instructions to get a secret value. +Usage: +{{ include "common.utils.secret.getvalue" (dict "secret" "secret-name" "field" "secret-value-field" "context" $) }} +*/}} +{{- define "common.utils.secret.getvalue" -}} +{{- $varname := include "common.utils.fieldToEnvVar" . -}} +export {{ $varname }}=$(kubectl get secret --namespace {{ include "common.names.namespace" .context | quote }} {{ .secret }} -o jsonpath="{.data.{{ .field }}}" | base64 -d) +{{- end -}} + +{{/* +Build env var name given a field +Usage: +{{ include "common.utils.fieldToEnvVar" dict "field" "my-password" }} +*/}} +{{- define "common.utils.fieldToEnvVar" -}} + {{- $fieldNameSplit := splitList "-" .field -}} + {{- $upperCaseFieldNameSplit := list -}} + + {{- range $fieldNameSplit -}} + {{- $upperCaseFieldNameSplit = append $upperCaseFieldNameSplit ( upper . ) -}} + {{- end -}} + + {{ join "_" $upperCaseFieldNameSplit }} +{{- end -}} + +{{/* +Gets a value from .Values given +Usage: +{{ include "common.utils.getValueFromKey" (dict "key" "path.to.key" "context" $) }} +*/}} +{{- define "common.utils.getValueFromKey" -}} +{{- $splitKey := splitList "." .key -}} +{{- $value := "" -}} +{{- $latestObj := $.context.Values -}} +{{- range $splitKey -}} + {{- if not $latestObj -}} + {{- printf "please review the entire path of '%s' exists in values" $.key | fail -}} + {{- end -}} + {{- $value = ( index $latestObj . ) -}} + {{- $latestObj = $value -}} +{{- end -}} +{{- printf "%v" (default "" $value) -}} +{{- end -}} + +{{/* +Returns first .Values key with a defined value or first of the list if all non-defined +Usage: +{{ include "common.utils.getKeyFromList" (dict "keys" (list "path.to.key1" "path.to.key2") "context" $) }} +*/}} +{{- define "common.utils.getKeyFromList" -}} +{{- $key := first .keys -}} +{{- $reverseKeys := reverse .keys }} +{{- range $reverseKeys }} + {{- $value := include "common.utils.getValueFromKey" (dict "key" . "context" $.context ) }} + {{- if $value -}} + {{- $key = . }} + {{- end -}} +{{- end -}} +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Checksum a template at "path" containing a *single* resource (ConfigMap,Secret) for use in pod annotations, excluding the metadata (see #18376). +Usage: +{{ include "common.utils.checksumTemplate" (dict "path" "/configmap.yaml" "context" $) }} +*/}} +{{- define "common.utils.checksumTemplate" -}} +{{- $obj := include (print .context.Template.BasePath .path) .context | fromYaml -}} +{{ omit $obj "apiVersion" "kind" "metadata" | toYaml | sha256sum }} +{{- end -}} diff --git a/backing-services/mongodb/charts/common/templates/_warnings.tpl b/backing-services/mongodb/charts/common/templates/_warnings.tpl new file mode 100644 index 0000000..e4dbecd --- /dev/null +++ b/backing-services/mongodb/charts/common/templates/_warnings.tpl @@ -0,0 +1,109 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Warning about using rolling tag. +Usage: +{{ include "common.warnings.rollingTag" .Values.path.to.the.imageRoot }} +*/}} +{{- define "common.warnings.rollingTag" -}} + +{{- if and (contains "bitnami/" .repository) (not (.tag | toString | regexFind "-r\\d+$|sha256:")) }} +WARNING: Rolling tag detected ({{ .repository }}:{{ .tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. ++info https://docs.vmware.com/en/VMware-Tanzu-Application-Catalog/services/tutorials/GUID-understand-rolling-tags-containers-index.html +{{- end }} +{{- end -}} + +{{/* +Warning about replaced images from the original. +Usage: +{{ include "common.warnings.modifiedImages" (dict "images" (list .Values.path.to.the.imageRoot) "context" $) }} +*/}} +{{- define "common.warnings.modifiedImages" -}} +{{- $affectedImages := list -}} +{{- $printMessage := false -}} +{{- $originalImages := .context.Chart.Annotations.images -}} +{{- range .images -}} + {{- $fullImageName := printf (printf "%s/%s:%s" .registry .repository .tag) -}} + {{- if not (contains $fullImageName $originalImages) }} + {{- $affectedImages = append $affectedImages (printf "%s/%s:%s" .registry .repository .tag) -}} + {{- $printMessage = true -}} + {{- end -}} +{{- end -}} +{{- if $printMessage }} + +⚠ SECURITY WARNING: Original containers have been substituted. This Helm chart was designed, tested, and validated on multiple platforms using a specific set of Bitnami and Tanzu Application Catalog containers. Substituting other containers is likely to cause degraded security and performance, broken chart features, and missing environment variables. + +Substituted images detected: +{{- range $affectedImages }} + - {{ . }} +{{- end }} +{{- end -}} +{{- end -}} + +{{/* +Warning about not setting the resource object in all deployments. +Usage: +{{ include "common.warnings.resources" (dict "sections" (list "path1" "path2") context $) }} +Example: +{{- include "common.warnings.resources" (dict "sections" (list "csiProvider.provider" "server" "volumePermissions" "") "context" $) }} +The list in the example assumes that the following values exist: + - csiProvider.provider.resources + - server.resources + - volumePermissions.resources + - resources +*/}} +{{- define "common.warnings.resources" -}} +{{- $values := .context.Values -}} +{{- $printMessage := false -}} +{{ $affectedSections := list -}} +{{- range .sections -}} + {{- if eq . "" -}} + {{/* Case where the resources section is at the root (one main deployment in the chart) */}} + {{- if not (index $values "resources") -}} + {{- $affectedSections = append $affectedSections "resources" -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Case where the are multiple resources sections (more than one main deployment in the chart) */}} + {{- $keys := split "." . -}} + {{/* We iterate through the different levels until arriving to the resource section. Example: a.b.c.resources */}} + {{- $section := $values -}} + {{- range $keys -}} + {{- $section = index $section . -}} + {{- end -}} + {{- if not (index $section "resources") -}} + {{/* If the section has enabled=false or replicaCount=0, do not include it */}} + {{- if and (hasKey $section "enabled") -}} + {{- if index $section "enabled" -}} + {{/* enabled=true */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else if and (hasKey $section "replicaCount") -}} + {{/* We need a casting to int because number 0 is not treated as an int by default */}} + {{- if (gt (index $section "replicaCount" | int) 0) -}} + {{/* replicaCount > 0 */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Default case, add it to the affected sections */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- if $printMessage }} + +WARNING: There are "resources" sections in the chart not set. Using "resourcesPreset" is not recommended for production. For production installations, please set the following values according to your workload needs: +{{- range $affectedSections }} + - {{ . }} +{{- end }} ++info https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +{{- end -}} +{{- end -}} diff --git a/backing-services/mongodb/charts/common/templates/validations/_cassandra.tpl b/backing-services/mongodb/charts/common/templates/validations/_cassandra.tpl new file mode 100644 index 0000000..f8fd213 --- /dev/null +++ b/backing-services/mongodb/charts/common/templates/validations/_cassandra.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.cassandra.values.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.cassandra.dbUser.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.dbUser.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled cassandra. + +Usage: +{{ include "common.cassandra.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.cassandra.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.cassandra.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key dbUser + +Usage: +{{ include "common.cassandra.values.key.dbUser" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.key.dbUser" -}} + {{- if .subchart -}} + cassandra.dbUser + {{- else -}} + dbUser + {{- end -}} +{{- end -}} diff --git a/backing-services/mongodb/charts/common/templates/validations/_mariadb.tpl b/backing-services/mongodb/charts/common/templates/validations/_mariadb.tpl new file mode 100644 index 0000000..6ea8c0f --- /dev/null +++ b/backing-services/mongodb/charts/common/templates/validations/_mariadb.tpl @@ -0,0 +1,108 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MariaDB required passwords are not empty. + +Usage: +{{ include "common.validations.values.mariadb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MariaDB values are stored, e.g: "mysql-passwords-secret" + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mariadb.passwords" -}} + {{- $existingSecret := include "common.mariadb.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mariadb.values.enabled" . -}} + {{- $architecture := include "common.mariadb.values.architecture" . -}} + {{- $authPrefix := include "common.mariadb.values.key.auth" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mariadb-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- if not (empty $valueUsername) -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mariadb-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replication") -}} + {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mariadb-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mariadb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mariadb. + +Usage: +{{ include "common.mariadb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mariadb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mariadb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mariadb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mariadb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.key.auth" -}} + {{- if .subchart -}} + mariadb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/backing-services/mongodb/charts/common/templates/validations/_mongodb.tpl b/backing-services/mongodb/charts/common/templates/validations/_mongodb.tpl new file mode 100644 index 0000000..e678a6d --- /dev/null +++ b/backing-services/mongodb/charts/common/templates/validations/_mongodb.tpl @@ -0,0 +1,67 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mongodb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDb is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mongodb. + +Usage: +{{ include "common.mongodb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mongodb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mongodb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mongodb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.key.auth" -}} + {{- if .subchart -}} + mongodb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mongodb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/mongodb/charts/common/templates/validations/_mysql.tpl b/backing-services/mongodb/charts/common/templates/validations/_mysql.tpl new file mode 100644 index 0000000..fbb65c3 --- /dev/null +++ b/backing-services/mongodb/charts/common/templates/validations/_mysql.tpl @@ -0,0 +1,67 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mysql.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mysql. + +Usage: +{{ include "common.mysql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mysql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mysql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mysql.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mysql.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.key.auth" -}} + {{- if .subchart -}} + mysql.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/backing-services/mongodb/charts/common/templates/validations/_postgresql.tpl b/backing-services/mongodb/charts/common/templates/validations/_postgresql.tpl new file mode 100644 index 0000000..51d4716 --- /dev/null +++ b/backing-services/mongodb/charts/common/templates/validations/_postgresql.tpl @@ -0,0 +1,105 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to decide whether evaluate global values. + +Usage: +{{ include "common.postgresql.values.use.global" (dict "key" "key-of-global" "context" $) }} +Params: + - key - String - Required. Field to be evaluated within global, e.g: "existingSecret" +*/}} +{{- define "common.postgresql.values.use.global" -}} + {{- if .context.Values.global -}} + {{- if .context.Values.global.postgresql -}} + {{- index .context.Values.global.postgresql .key | quote -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.postgresql.values.existingSecret" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.existingSecret" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "existingSecret" "context" .context) -}} + + {{- if .subchart -}} + {{- default (.context.Values.postgresql.existingSecret | quote) $globalValue -}} + {{- else -}} + {{- default (.context.Values.existingSecret | quote) $globalValue -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled postgresql. + +Usage: +{{ include "common.postgresql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key postgressPassword. + +Usage: +{{ include "common.postgresql.values.key.postgressPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.postgressPassword" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "postgresqlUsername" "context" .context) -}} + + {{- if not $globalValue -}} + {{- if .subchart -}} + postgresql.postgresqlPassword + {{- else -}} + postgresqlPassword + {{- end -}} + {{- else -}} + global.postgresql.postgresqlPassword + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled.replication. + +Usage: +{{ include "common.postgresql.values.enabled.replication" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.enabled.replication" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.replication.enabled -}} + {{- else -}} + {{- printf "%v" .context.Values.replication.enabled -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key replication.password. + +Usage: +{{ include "common.postgresql.values.key.replicationPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.replicationPassword" -}} + {{- if .subchart -}} + postgresql.replication.password + {{- else -}} + replication.password + {{- end -}} +{{- end -}} diff --git a/backing-services/mongodb/charts/common/templates/validations/_redis.tpl b/backing-services/mongodb/charts/common/templates/validations/_redis.tpl new file mode 100644 index 0000000..9fedfef --- /dev/null +++ b/backing-services/mongodb/charts/common/templates/validations/_redis.tpl @@ -0,0 +1,48 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for enabled redis. + +Usage: +{{ include "common.redis.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.redis.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.redis.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right prefix path for the values + +Usage: +{{ include "common.redis.values.key.prefix" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false +*/}} +{{- define "common.redis.values.keys.prefix" -}} + {{- if .subchart -}}redis.{{- else -}}{{- end -}} +{{- end -}} + +{{/* +Checks whether the redis chart's includes the standarizations (version >= 14) + +Usage: +{{ include "common.redis.values.standarized.version" (dict "context" $) }} +*/}} +{{- define "common.redis.values.standarized.version" -}} + + {{- $standarizedAuth := printf "%s%s" (include "common.redis.values.keys.prefix" .) "auth" -}} + {{- $standarizedAuthValues := include "common.utils.getValueFromKey" (dict "key" $standarizedAuth "context" .context) }} + + {{- if $standarizedAuthValues -}} + {{- true -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/mongodb/charts/common/templates/validations/_validations.tpl b/backing-services/mongodb/charts/common/templates/validations/_validations.tpl new file mode 100644 index 0000000..7cdee61 --- /dev/null +++ b/backing-services/mongodb/charts/common/templates/validations/_validations.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate values must not be empty. + +Usage: +{{- $validateValueConf00 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-01") -}} +{{ include "common.validations.values.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" +*/}} +{{- define "common.validations.values.multiple.empty" -}} + {{- range .required -}} + {{- include "common.validations.values.single.empty" (dict "valueKey" .valueKey "secret" .secret "field" .field "context" $.context) -}} + {{- end -}} +{{- end -}} + +{{/* +Validate a value must not be empty. + +Usage: +{{ include "common.validations.value.empty" (dict "valueKey" "mariadb.password" "secret" "secretName" "field" "my-password" "subchart" "subchart" "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" + - subchart - String - Optional - Name of the subchart that the validated password is part of. +*/}} +{{- define "common.validations.values.single.empty" -}} + {{- $value := include "common.utils.getValueFromKey" (dict "key" .valueKey "context" .context) }} + {{- $subchart := ternary "" (printf "%s." .subchart) (empty .subchart) }} + + {{- if not $value -}} + {{- $varname := "my-value" -}} + {{- $getCurrentValue := "" -}} + {{- if and .secret .field -}} + {{- $varname = include "common.utils.fieldToEnvVar" . -}} + {{- $getCurrentValue = printf " To get the current value:\n\n %s\n" (include "common.utils.secret.getvalue" .) -}} + {{- end -}} + {{- printf "\n '%s' must not be empty, please add '--set %s%s=$%s' to the command.%s" .valueKey $subchart .valueKey $varname $getCurrentValue -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/mongodb/charts/common/values.yaml b/backing-services/mongodb/charts/common/values.yaml new file mode 100644 index 0000000..de2cac5 --- /dev/null +++ b/backing-services/mongodb/charts/common/values.yaml @@ -0,0 +1,8 @@ +# Copyright Broadcom, Inc. All Rights Reserved. +# SPDX-License-Identifier: APACHE-2.0 + +## bitnami/common +## It is required by CI/CD tools and processes. +## @skip exampleValue +## +exampleValue: common-chart diff --git a/backing-services/mongodb/schoobus-onsite.values.yaml b/backing-services/mongodb/schoobus-onsite.values.yaml new file mode 100644 index 0000000..bdecb3a --- /dev/null +++ b/backing-services/mongodb/schoobus-onsite.values.yaml @@ -0,0 +1,11 @@ +auth: + enabled: true + rootUser: root + rootPassword: "secret123" + +serviceAccount: + create: false + +service: + nameOverride: "" + type: NodePort \ No newline at end of file diff --git a/backing-services/mongodb/school-stage-eks.values.yaml b/backing-services/mongodb/school-stage-eks.values.yaml new file mode 100644 index 0000000..6ef2843 --- /dev/null +++ b/backing-services/mongodb/school-stage-eks.values.yaml @@ -0,0 +1,61 @@ +global: + storageClass: "efs-sc" + +# persistence: +# enabled: true +# storageClass: "efs-sc" + +livenessProbe: + enabled: true + initialDelaySeconds: 60 + periodSeconds: 15 + timeoutSeconds: 10 + failureThreshold: 20 +readinessProbe: + enabled: true + initialDelaySeconds: 60 + periodSeconds: 15 + timeoutSeconds: 10 + failureThreshold: 20 +persistence: + enabled: true + storageClass: efs-sc + accessModes: + - ReadWriteOnce + size: 100M + +backup: + cronjob: + storage: + storageClass: "efs-sc" + +hidden: + persistence: + storageClass: "efs-sc" + +auth: + enabled: true + rootUser: root + rootPassword: "secret123" + +serviceAccount: + create: true + name: "mongodbservcieaccount" + annotations: + eks.amazonaws.com/role-arn: "arn:aws:iam::889565812003:role/schoolbuses-cluster-20241110104436981500000002" + +service: + nameOverride: "" + type: LoadBalancer + annotations: + service.beta.kubernetes.io/aws-load-balancer-type: "nlb" + service.beta.kubernetes.io/aws-load-balancer-type: external + service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing + service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: instance + +securityContext: + fsGroup: 1001 + + +volumePermissions: + enabled: true diff --git a/backing-services/mongodb/school-stage-tavana.values.yaml b/backing-services/mongodb/school-stage-tavana.values.yaml new file mode 100644 index 0000000..0eebf77 --- /dev/null +++ b/backing-services/mongodb/school-stage-tavana.values.yaml @@ -0,0 +1,27 @@ +image: + registry: 172.16.16.1:30516 + repository: bitnami/mongodb + tag: 8.0.3-debian-12-r0 + +metrics: + enabled: false + image: + registry: 172.16.16.1:30516 + repository: bitnami/mongodb-exporter + tag: 0.41.2-debian-12-r1 + pullPolicy: IfNotPresent + +auth: + enabled: true + rootUser: root + rootPassword: "secret123" + +serviceAccount: + create: false + +service: + nameOverride: "" + type: NodePort + +nodeSelector: + node.name: node-01 \ No newline at end of file diff --git a/backing-services/mongodb/schoolbus-demo.values.yaml b/backing-services/mongodb/schoolbus-demo.values.yaml new file mode 100644 index 0000000..6250bb4 --- /dev/null +++ b/backing-services/mongodb/schoolbus-demo.values.yaml @@ -0,0 +1,37 @@ +image: + registry: 172.16.16.2:30516 + repository: bitnami/mongodb + tag: 8.0.3-debian-12-r0 + +replicaCount: 1 + +metrics: + enabled: false + image: + registry: 172.16.16.2:30516 + repository: bitnami/mongodb-exporter + tag: 0.41.2-debian-12-r1 + pullPolicy: IfNotPresent + +auth: + enabled: true + rootUser: root + rootPassword: "secret123" + +serviceAccount: + create: false + +service: + nameOverride: "" + type: NodePort + +nodeSelector: + node.name: node-1 + +resources: + requests: + cpu: 1000m + memory: 1G + limits: + cpu: 1000m + memory: 1G \ No newline at end of file diff --git a/backing-services/mongodb/symbon-stage-tavana.values.yaml b/backing-services/mongodb/symbon-stage-tavana.values.yaml new file mode 100644 index 0000000..975bd55 --- /dev/null +++ b/backing-services/mongodb/symbon-stage-tavana.values.yaml @@ -0,0 +1,19 @@ +image: + registry: 172.16.16.1:30516 + repository: bitnami/mongodb + tag: 8.0.3-debian-12-r0 + debug: true + +auth: + enabled: true + rootUser: root + rootPassword: "Auction12" + +serviceAccount: + create: false + +service: + nameOverride: "" + type: NodePort + ports: + mongodb: 27018 \ No newline at end of file diff --git a/backing-services/mongodb/templates/NOTES.txt b/backing-services/mongodb/templates/NOTES.txt new file mode 100644 index 0000000..a69eb9c --- /dev/null +++ b/backing-services/mongodb/templates/NOTES.txt @@ -0,0 +1,171 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +{{- if .Values.diagnosticMode.enabled }} +The chart has been deployed in diagnostic mode. All probes have been disabled and the command has been overwritten with: + + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 4 }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 4 }} + +Get the list of pods by executing: + + kubectl get pods --namespace {{ .Release.Namespace }} -l app.kubernetes.io/instance={{ .Release.Name }} + +Access the pod you want to debug by executing + + kubectl exec --namespace {{ .Release.Namespace }} -ti -- bash + +In order to replicate the container startup scripts execute this command: + + /opt/bitnami/scripts/mongodb/entrypoint.sh /opt/bitnami/scripts/mongodb/run.sh + +{{- else }} + +{{- $replicaCount := int .Values.replicaCount }} +{{- $portNumber := int .Values.service.ports.mongodb }} +{{- $fullname := include "mongodb.fullname" . }} +{{- $releaseNamespace := include "mongodb.namespace" . }} +{{- $clusterDomain := .Values.clusterDomain }} +{{- $loadBalancerIPListLength := len .Values.externalAccess.service.loadBalancerIPs }} +{{- $mongoList := list }} +{{- range $e, $i := until $replicaCount }} +{{- $mongoList = append $mongoList (printf "%s-%d.%s-headless.%s.svc.%s:%d" $fullname $i $fullname $releaseNamespace $clusterDomain $portNumber) }} +{{- end }} + +{{- if and (or (and (eq .Values.architecture "standalone") (or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort"))) (and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled)) (not .Values.auth.enabled) }} +------------------------------------------------------------------------------- + WARNING + + By not enabling "mongodb.auth.enabled" you have most likely exposed the + MongoDB® service externally without any authentication mechanism. + + For security reasons, we strongly suggest that you enable authentication + setting the "mongodb.auth.enabled" parameter to "true". + +------------------------------------------------------------------------------- +{{- end }} + +** Please be patient while the chart is being deployed ** + +MongoDB® can be accessed on the following DNS name(s) and ports from within your cluster: + +{{- if eq .Values.architecture "replicaset" }} +{{ join "\n" $mongoList | nindent 4 }} +{{- else }} + + {{ $fullname }}.{{ $releaseNamespace }}.svc.{{ .Values.clusterDomain }} + +{{- end }} + +{{- if .Values.auth.enabled }} + +To get the root password run: + + export MONGODB_ROOT_PASSWORD=$(kubectl get secret --namespace {{ template "mongodb.namespace" . }} {{ template "mongodb.secretName" . }} -o jsonpath="{.data.mongodb-root-password}" | base64 -d) + +{{- end }} +{{- $customUsers := include "mongodb.customUsers" . -}} +{{- $customDatabases := include "mongodb.customDatabases" . -}} +{{- if and (not (empty $customUsers)) (not (empty $customDatabases)) }} +{{- $customUsersList := splitList "," $customUsers }} +{{- range $index, $user := $customUsersList }} + +To get the password for "{{ $user }}" run: + + export MONGODB_PASSWORD=$(kubectl get secret --namespace {{ include "mongodb.namespace" $ }} {{ include "mongodb.secretName" $ }} -o jsonpath="{.data.mongodb-passwords}" | base64 -d | awk -F',' '{print ${{ add 1 $index }}}') + +{{- end }} +{{- end }} + +To connect to your database, create a MongoDB® client container: + + kubectl run --namespace {{ template "mongodb.namespace" . }} {{ template "mongodb.fullname" . }}-client --rm --tty -i --restart='Never' --env="MONGODB_ROOT_PASSWORD=$MONGODB_ROOT_PASSWORD" --image {{ template "mongodb.image" . }} --command -- bash + +Then, run the following command: + + {{- if eq .Values.architecture "replicaset" }} + mongosh admin --host "{{ join "," $mongoList }}" {{- if .Values.auth.enabled }} --authenticationDatabase admin -u $MONGODB_ROOT_USER -p $MONGODB_ROOT_PASSWORD{{- end }} + {{- else }} + mongosh admin --host "{{ template "mongodb.service.nameOverride" . }}" {{- if .Values.auth.enabled }} --authenticationDatabase admin -u $MONGODB_ROOT_USER -p $MONGODB_ROOT_PASSWORD{{- end }} + {{- end }} + +{{- if and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled }} + +To connect to your database nodes from outside, you need to add both primary and secondary nodes hostnames/IPs to your Mongo client. To obtain them, follow the instructions below: + +{{- if eq "NodePort" .Values.externalAccess.service.type }} +{{- if .Values.externalAccess.service.domain }} + + MongoDB® nodes domain: Use your provided hostname to reach MongoDB® nodes, {{ .Values.externalAccess.service.domain }} + +{{- else }} + + MongoDB® nodes domain: you can reach MongoDB® nodes on any of the K8s nodes external IPs. + + kubectl get nodes -o wide + +{{- end }} + + MongoDB® nodes port: You will have a different node port for each MongoDB® node. You can get the list of configured node ports using the command below: + + echo "$(kubectl get svc --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ template "mongodb.name" . }},app.kubernetes.io/instance={{ .Release.Name }},app.kubernetes.io/component=mongodb,pod" -o jsonpath='{.items[*].spec.ports[0].nodePort}' | tr ' ' '\n')" + +{{- else if contains "LoadBalancer" .Values.externalAccess.service.type }} + + NOTE: It may take a few minutes for the LoadBalancer IPs to be available. + Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ template "mongodb.name" . }},app.kubernetes.io/instance={{ .Release.Name }},app.kubernetes.io/component=mongodb,pod" -w' + + MongoDB® nodes domain: You will have a different external IP for each MongoDB® node. You can get the list of external IPs using the command below: + + echo "$(kubectl get svc --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ template "mongodb.name" . }},app.kubernetes.io/instance={{ .Release.Name }},app.kubernetes.io/component=mongodb,pod" -o jsonpath='{.items[*].status.loadBalancer.ingress[0].ip}' | tr ' ' '\n')" + + MongoDB® nodes port: {{ .Values.externalAccess.service.ports.mongodb }} + +{{- end }} + +{{- else if eq .Values.architecture "standalone" }} + +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 {{ template "mongodb.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get --namespace {{ template "mongodb.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "mongodb.service.nameOverride" . }}) + mongo --host $NODE_IP --port $NODE_PORT {{- if .Values.auth.enabled }} --authenticationDatabase admin -p $MONGODB_ROOT_PASSWORD{{- 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 {{ template "mongodb.namespace" . }} -w {{ template "mongodb.service.nameOverride" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ template "mongodb.namespace" . }} {{ template "mongodb.service.nameOverride" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") + mongosh --host $SERVICE_IP --port {{ $portNumber }} {{- if .Values.auth.enabled }} --authenticationDatabase admin -p $MONGODB_ROOT_PASSWORD{{- end }} + +{{- else if contains "ClusterIP" .Values.service.type }} + + kubectl port-forward --namespace {{ template "mongodb.namespace" . }} svc/{{ template "mongodb.service.nameOverride" . }} {{ $portNumber }}:{{ $portNumber }} & + mongosh --host 127.0.0.1 {{- if .Values.auth.enabled }} --authenticationDatabase admin -p $MONGODB_ROOT_PASSWORD{{- end }} + +{{- end }} +{{- end }} + +{{- if .Values.metrics.enabled }} + +To access the MongoDB® Prometheus metrics, get the MongoDB® Prometheus URL by running: + + kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ printf "%s-metrics" (include "mongodb.fullname" .) }} {{ .Values.metrics.service.ports.metrics }}:{{ .Values.metrics.service.ports.metrics }} & + echo "Prometheus Metrics URL: http://127.0.0.1:{{ .Values.metrics.service.ports.metrics }}/metrics" + +Then, open the obtained URL in a browser. + +{{- end }} +{{- end }} +{{- include "common.warnings.rollingTag" .Values.image }} +{{- include "common.warnings.rollingTag" .Values.metrics.image }} +{{- include "common.warnings.rollingTag" .Values.externalAccess.autoDiscovery.image }} +{{- include "common.warnings.rollingTag" .Values.volumePermissions.image }} +{{- include "common.warnings.rollingTag" .Values.tls.image }} +{{- include "mongodb.validateValues" . }} +{{- include "common.warnings.resources" (dict "sections" (list "arbiter" "externalAccess.autoDiscovery" "hidden" "metrics" "" "tls" "volumePermissions") "context" $) }} +{{- include "common.warnings.modifiedImages" (dict "images" (list .Values.image .Values.tls.image .Values.externalAccess.autoDiscovery.image .Values.externalAccess.dnsCheck.image .Values.volumePermissions.image .Values.metrics.image) "context" $) }} \ No newline at end of file diff --git a/backing-services/mongodb/templates/_helpers.tpl b/backing-services/mongodb/templates/_helpers.tpl new file mode 100644 index 0000000..26baf66 --- /dev/null +++ b/backing-services/mongodb/templates/_helpers.tpl @@ -0,0 +1,686 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "mongodb.name" -}} +{{- include "common.names.name" . -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "mongodb.fullname" -}} +{{- include "common.names.fullname" . -}} +{{- end -}} + +{{/* +Create a default mongo service name which can be overridden. +*/}} +{{- define "mongodb.service.nameOverride" -}} + {{- if and .Values.service .Values.service.nameOverride -}} + {{- print .Values.service.nameOverride -}} + {{- else -}} + {{- if eq .Values.architecture "replicaset" -}} + {{- printf "%s-headless" (include "mongodb.fullname" .) -}} + {{- else -}} + {{- printf "%s" (include "mongodb.fullname" .) -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Create a default mongo arbiter service name which can be overridden. +*/}} +{{- define "mongodb.arbiter.service.nameOverride" -}} + {{- if and .Values.arbiter.service .Values.arbiter.service.nameOverride -}} + {{- print .Values.arbiter.service.nameOverride -}} + {{- else -}} + {{- printf "%s-arbiter-headless" (include "mongodb.fullname" .) -}} + {{- end }} +{{- end }} + +{{/* +Create a default mongo hidden service name which can be overridden. +*/}} +{{- define "mongodb.hidden.service.nameOverride" -}} + {{- if and .Values.hidden.service .Values.hidden.service.nameOverride -}} + {{- print .Values.hidden.service.nameOverride -}} + {{- else -}} + {{- printf "%s-hidden-headless" (include "mongodb.fullname" .) -}} + {{- end }} +{{- end }} + +{{/* +Return the proper MongoDB® image name +*/}} +{{- define "mongodb.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper image name (for the metrics image) +*/}} +{{- define "mongodb.metrics.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.metrics.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper image name (for the init container volume-permissions image) +*/}} +{{- define "mongodb.volumePermissions.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.volumePermissions.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper image name (for the init container auto-discovery image) +*/}} +{{- define "mongodb.externalAccess.autoDiscovery.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.externalAccess.autoDiscovery.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper image name (for the init container dns-check image) +*/}} +{{- define "mongodb.externalAccess.dnsCheck.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.externalAccess.dnsCheck.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper image name (for the TLS Certs image) +*/}} +{{- define "mongodb.tls.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.tls.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "mongodb.imagePullSecrets" -}} +{{- include "common.images.renderPullSecrets" (dict "images" (list .Values.image .Values.metrics.image .Values.volumePermissions.image .Values.tls.image .Values.externalAccess.dnsCheck.image .Values.externalAccess.autoDiscovery.image) "context" $) -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts. +*/}} +{{- define "mongodb.namespace" -}} + {{- if and .Values.global .Values.global.namespaceOverride -}} + {{- print .Values.global.namespaceOverride -}} + {{- else -}} + {{- print .Release.Namespace -}} + {{- end }} +{{- end -}} +{{- define "mongodb.serviceMonitor.namespace" -}} + {{- if .Values.metrics.serviceMonitor.namespace -}} + {{- print .Values.metrics.serviceMonitor.namespace -}} + {{- else -}} + {{- include "mongodb.namespace" . -}} + {{- end }} +{{- end -}} +{{- define "mongodb.prometheusRule.namespace" -}} + {{- if .Values.metrics.prometheusRule.namespace -}} + {{- print .Values.metrics.prometheusRule.namespace -}} + {{- else -}} + {{- include "mongodb.namespace" . -}} + {{- end }} +{{- end -}} + +{{/* +Returns the proper service account name depending if an explicit service account name is set +in the values file. If the name is not set it will default to either mongodb.fullname if serviceAccount.create +is true or default otherwise. +*/}} +{{- define "mongodb.serviceAccountName" -}} + {{- if .Values.serviceAccount.create -}} + {{- default (include "mongodb.fullname" .) (print .Values.serviceAccount.name) -}} + {{- else -}} + {{- default "default" (print .Values.serviceAccount.name) -}} + {{- end -}} +{{- end -}} + +{{/* +Return the list of custom users to create during the initialization (string format) +*/}} +{{- define "mongodb.customUsers" -}} + {{- $customUsers := list -}} + {{- if .Values.auth.username -}} + {{- $customUsers = append $customUsers .Values.auth.username }} + {{- end }} + {{- range .Values.auth.usernames }} + {{- $customUsers = append $customUsers . }} + {{- end }} + {{- printf "%s" (default "" (join "," $customUsers)) -}} +{{- end -}} + +{{/* +Return the list of passwords for the custom users (string format) +*/}} +{{- define "mongodb.customPasswords" -}} + {{- $customPasswords := list -}} + {{- if .Values.auth.password -}} + {{- $customPasswords = append $customPasswords .Values.auth.password }} + {{- end }} + {{- range .Values.auth.passwords }} + {{- $customPasswords = append $customPasswords . }} + {{- end }} + {{- printf "%s" (default "" (join "," $customPasswords)) -}} +{{- end -}} + +{{/* +Return the list of custom databases to create during the initialization (string format) +*/}} +{{- define "mongodb.customDatabases" -}} + {{- $customDatabases := list -}} + {{- if .Values.auth.database -}} + {{- $customDatabases = append $customDatabases .Values.auth.database }} + {{- end }} + {{- range .Values.auth.databases }} + {{- $customDatabases = append $customDatabases . }} + {{- end }} + {{- printf "%s" (default "" (join "," $customDatabases)) -}} +{{- end -}} + +{{/* +Return the configmap with the MongoDB® configuration +*/}} +{{- define "mongodb.configmapName" -}} +{{- if .Values.existingConfigmap -}} + {{- printf "%s" (tpl .Values.existingConfigmap $) -}} +{{- else -}} + {{- printf "%s" (include "mongodb.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a configmap object should be created for MongoDB® +*/}} +{{- define "mongodb.createConfigmap" -}} +{{- if and .Values.configuration (not .Values.existingConfigmap) }} + {{- true -}} +{{- else -}} +{{- end -}} +{{- end -}} + +{{/* +Return the secret with MongoDB® credentials +*/}} +{{- define "mongodb.secretName" -}} + {{- if .Values.auth.existingSecret -}} + {{- printf "%s" (tpl .Values.auth.existingSecret $) -}} + {{- else -}} + {{- printf "%s" (include "mongodb.fullname" .) -}} + {{- end -}} +{{- end -}} + +{{/* +Return true if a secret object should be created for MongoDB® +*/}} +{{- define "mongodb.createSecret" -}} +{{- if and .Values.auth.enabled (not .Values.auth.existingSecret) }} + {{- true -}} +{{- else -}} +{{- end -}} +{{- end -}} + +{{/* +Get the initialization scripts ConfigMap name. +*/}} +{{- define "mongodb.initdbScriptsCM" -}} +{{- if .Values.initdbScriptsConfigMap -}} +{{- printf "%s" (tpl .Values.initdbScriptsConfigMap $) -}} +{{- else -}} +{{- printf "%s-init-scripts" (include "mongodb.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Get initial primary host to configure MongoDB cluster. +*/}} +{{- define "mongodb.initialPrimaryHost" -}} +{{ ternary ( printf "%s-0.%s.$(MY_POD_NAMESPACE).svc.%s" (include "mongodb.fullname" .) (include "mongodb.service.nameOverride" .) .Values.clusterDomain ) ( first .Values.externalAccess.service.publicNames ) ( empty .Values.externalAccess.service.publicNames ) }} +{{- end -}} + +{{/* +Init container definition to change/establish volume permissions. +*/}} +{{- define "mongodb.initContainer.volumePermissions" }} +- name: volume-permissions + image: {{ include "mongodb.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + args: + - -ec + - | + mkdir -p {{ printf "%s/%s" .Values.persistence.mountPath (default "" .Values.persistence.subPath) }} + chown {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }} {{ printf "%s/%s" .Values.persistence.mountPath (default "" .Values.persistence.subPath) }} + find {{ printf "%s/%s" .Values.persistence.mountPath (default "" .Values.persistence.subPath) }} -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | xargs -r chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }} + {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.securityContext "runAsUser" | toYaml | nindent 12 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.securityContext | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.volumePermissions.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.volumePermissions.resources "context" $) | nindent 12 }} + {{- else if ne .Values.volumePermissions.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.volumePermissions.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: {{ .Values.persistence.name | default "datadir" }} + mountPath: {{ .Values.persistence.mountPath }} +{{- end -}} + +{{/* +Init container definition to recover log dir. +*/}} +{{- define "mongodb.initContainer.prepareLogDir" }} +- name: log-dir + image: {{ include "mongodb.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + command: + - /bin/bash + args: + - -ec + - | + ln -sf /dev/stdout "/opt/bitnami/mongodb/logs/mongodb.log" + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.resources "context" $) | nindent 12 }} + {{- else if ne .Values.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /opt/bitnami/mongodb/logs + subPath: app-logs-dir +{{- end -}} + +{{/* +Init container definition to get external IP addresses. +*/}} +{{- define "mongodb.initContainers.autoDiscovery" -}} +- name: auto-discovery + image: {{ include "mongodb.externalAccess.autoDiscovery.image" . }} + imagePullPolicy: {{ .Values.externalAccess.autoDiscovery.image.pullPolicy | quote }} + # We need the service account token for contacting the k8s API + command: + - /scripts/auto-discovery.sh + env: + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: SHARED_FILE + value: "/shared/info.txt" + {{- if .Values.externalAccess.autoDiscovery.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.externalAccess.autoDiscovery.resources "context" $) | nindent 12 }} + {{- else if ne .Values.externalAccess.autoDiscovery.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.externalAccess.autoDiscovery.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: shared + mountPath: /shared + - name: scripts + mountPath: /scripts/auto-discovery.sh + subPath: auto-discovery.sh + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir +{{- end -}} + +{{/* +Init container definition to wait external DNS names. +*/}} +{{- define "mongodb.initContainers.dnsCheck" -}} +- name: dns-check + image: {{ include "mongodb.externalAccess.dnsCheck.image" . }} + imagePullPolicy: {{ .Values.externalAccess.dnsCheck.image.pullPolicy | quote }} + command: + - /bin/bash + args: + - -ec + - | + # MONGODB_INITIAL_PRIMARY_HOST should be resolvable + while ! (getent ahosts "{{ include "mongodb.initialPrimaryHost" . }}" | grep STREAM); do + sleep 10 + done + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.externalAccess.dnsCheck.resources }} + resources: {{- toYaml .Values.externalAccess.dnsCheck.resources | nindent 12 }} + {{- else if ne .Values.externalAccess.dnsCheck.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.externalAccess.dnsCheck.resourcesPreset) | nindent 12 }} + {{- end }} +{{- end -}} + +{{/* +Return true if the Arbiter should be deployed +*/}} +{{- define "mongodb.arbiter.enabled" -}} +{{- if and (eq .Values.architecture "replicaset") .Values.arbiter.enabled }} + {{- true -}} +{{- else -}} +{{- end -}} +{{- end -}} + +{{/* +Return the configmap with the MongoDB® configuration for the Arbiter +*/}} +{{- define "mongodb.arbiter.configmapName" -}} +{{- if .Values.arbiter.existingConfigmap -}} + {{- printf "%s" (tpl .Values.arbiter.existingConfigmap $) -}} +{{- else -}} + {{- printf "%s-arbiter" (include "mongodb.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a configmap object should be created for MongoDB® Arbiter +*/}} +{{- define "mongodb.arbiter.createConfigmap" -}} +{{- if and (eq .Values.architecture "replicaset") .Values.arbiter.enabled .Values.arbiter.configuration (not .Values.arbiter.existingConfigmap) }} + {{- true -}} +{{- else -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if the Hidden should be deployed +*/}} +{{- define "mongodb.hidden.enabled" -}} +{{- if and (eq .Values.architecture "replicaset") .Values.hidden.enabled }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the configmap with the MongoDB® configuration for the Hidden +*/}} +{{- define "mongodb.hidden.configmapName" -}} +{{- if .Values.hidden.existingConfigmap -}} + {{- printf "%s" (tpl .Values.hidden.existingConfigmap $) -}} +{{- else -}} + {{- printf "%s-hidden" (include "mongodb.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a configmap object should be created for MongoDB® Hidden +*/}} +{{- define "mongodb.hidden.createConfigmap" -}} +{{- if and (include "mongodb.hidden.enabled" .) .Values.hidden.enabled .Values.hidden.configuration (not .Values.hidden.existingConfigmap) }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Compile all warnings into a single message, and call fail. +*/}} +{{- define "mongodb.validateValues" -}} +{{- $messages := list -}} +{{- $messages := append $messages (include "mongodb.validateValues.pspAndRBAC" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.architecture" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.customUsersDBs" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.customUsersDBsLength" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.externalAccessServiceType" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.loadBalancerIPsListLength" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.nodePortListLength" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.externalAccessAutoDiscoveryRBAC" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.externalAccessAutoDiscoverySA" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.replicaset.existingSecrets" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.hidden.existingSecrets" .) -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}} +{{- end -}} +{{- end -}} + +{{/* Validate RBAC is created when using PSP */}} +{{- define "mongodb.validateValues.pspAndRBAC" -}} +{{- if and (.Values.podSecurityPolicy.create) (not .Values.rbac.create) -}} +mongodb: podSecurityPolicy.create, rbac.create + Both podSecurityPolicy.create and rbac.create must be true, if you want + to create podSecurityPolicy +{{- end -}} +{{- end -}} + +{{/* Validate values of MongoDB® - must provide a valid architecture */}} +{{- define "mongodb.validateValues.architecture" -}} +{{- if and (ne .Values.architecture "standalone") (ne .Values.architecture "replicaset") -}} +mongodb: architecture + Invalid architecture selected. Valid values are "standalone" and + "replicaset". Please set a valid architecture (--set mongodb.architecture="xxxx") +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - both auth.usernames and auth.databases are necessary +to create a custom user and database during 1st initialization +*/}} +{{- define "mongodb.validateValues.customUsersDBs" -}} +{{- $customUsers := include "mongodb.customUsers" . -}} +{{- $customDatabases := include "mongodb.customDatabases" . -}} +{{- if or (and (empty $customUsers) (not (empty $customDatabases))) (and (not (empty $customUsers)) (empty $customDatabases)) }} +mongodb: auth.usernames, auth.databases + Both auth.usernames and auth.databases must be provided to create + custom users and databases during 1st initialization. + Please set both of them (--set auth.usernames[0]="xxxx",auth.databases[0]="yyyy") +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - both auth.usernames and auth.databases arrays should have the same length +to create a custom user and database during 1st initialization +*/}} +{{- define "mongodb.validateValues.customUsersDBsLength" -}} +{{- if ne (len .Values.auth.usernames) (len .Values.auth.databases) }} +mongodb: auth.usernames, auth.databases + Both auth.usernames and auth.databases arrays should have the same length +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - service type for external access +*/}} +{{- define "mongodb.validateValues.externalAccessServiceType" -}} +{{- if and (eq .Values.architecture "replicaset") (not (eq .Values.externalAccess.service.type "NodePort")) (not (eq .Values.externalAccess.service.type "LoadBalancer")) (not (eq .Values.externalAccess.service.type "ClusterIP")) -}} +mongodb: externalAccess.service.type + Available service type for external access are NodePort, LoadBalancer or ClusterIP. +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - number of replicas must be the same than LoadBalancer IPs list +*/}} +{{- define "mongodb.validateValues.loadBalancerIPsListLength" -}} +{{- $replicaCount := int .Values.replicaCount }} +{{- $loadBalancerListLength := len .Values.externalAccess.service.loadBalancerIPs }} +{{- $publicNamesListLength := len .Values.externalAccess.service.publicNames }} +{{- if and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled (eq .Values.externalAccess.service.type "LoadBalancer") -}} +{{- if and (not .Values.externalAccess.autoDiscovery.enabled) (eq $loadBalancerListLength 0) (eq $publicNamesListLength 0) -}} +mongodb: .Values.externalAccess.service.loadBalancerIPs, .Values.externalAccess.service.publicNames + externalAccess.service.loadBalancerIPs, externalAccess.service.publicNames or externalAccess.autoDiscovery.enabled are required when externalAccess is enabled. +{{- else if and (not .Values.externalAccess.autoDiscovery.enabled) (not (eq $replicaCount $loadBalancerListLength )) (not (eq $loadBalancerListLength 0)) -}} +mongodb: .Values.externalAccess.service.loadBalancerIPs + Number of replicas ({{ $replicaCount }}) and loadBalancerIPs array length ({{ $loadBalancerListLength }}) must be the same. +{{- else if and (not .Values.externalAccess.autoDiscovery.enabled) (not (eq $replicaCount $publicNamesListLength )) (not (eq $publicNamesListLength 0)) -}} +mongodb: .Values.externalAccess.service.publicNames + Number of replicas ({{ $replicaCount }}) and publicNames array length ({{ $publicNamesListLength }}) must be the same. +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - number of replicas must be the same than NodePort list +*/}} +{{- define "mongodb.validateValues.nodePortListLength" -}} +{{- $replicaCount := int .Values.replicaCount }} +{{- $nodePortListLength := len .Values.externalAccess.service.nodePorts }} +{{- if and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled (eq .Values.externalAccess.service.type "NodePort") -}} +{{- if and (not .Values.externalAccess.autoDiscovery.enabled) (eq $nodePortListLength 0) -}} +mongodb: .Values.externalAccess.service.nodePorts + externalAccess.service.nodePorts or externalAccess.autoDiscovery.enabled are required when externalAccess is enabled. +{{- else if and (not .Values.externalAccess.autoDiscovery.enabled) (not (eq $replicaCount $nodePortListLength )) -}} +mongodb: .Values.externalAccess.service.nodePorts + Number of replicas ({{ $replicaCount }}) and nodePorts ({{ $nodePortListLength }}) array length must be the same. +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - RBAC should be enabled when autoDiscovery is enabled +*/}} +{{- define "mongodb.validateValues.externalAccessAutoDiscoveryRBAC" -}} +{{- if and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled (not .Values.rbac.create ) }} +mongodb: rbac.create + By specifying "externalAccess.enabled=true" and "externalAccess.autoDiscovery.enabled=true" + an initContainer will be used to autodetect the external IPs/ports by querying the + K8s API. Please note this initContainer requires specific RBAC resources. You can create them + by specifying "--set rbac.create=true". +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - automountServiceAccountToken should be enabled when autoDiscovery is enabled +*/}} +{{- define "mongodb.validateValues.externalAccessAutoDiscoverySA" -}} +{{- if and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled (not .Values.automountServiceAccountToken ) }} +mongodb: automountServiceAccountToken + By specifying "externalAccess.enabled=true" and "externalAccess.autoDiscovery.enabled=true" + an initContainer will be used to autodetect the external IPs/ports by querying the + K8s API. Please note this initContainer requires a service account to access K8S API. + You can attach it to the pod by specifying "--set automountServiceAccountToken=true". +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - Number of replicaset secrets must be the same than number of replicaset nodes. +*/}} +{{- define "mongodb.validateValues.replicaset.existingSecrets" -}} +{{- if and .Values.tls.enabled (eq .Values.architecture "replicaset") (not (empty .Values.tls.replicaset.existingSecrets)) }} +{{- $nbSecrets := len .Values.tls.replicaset.existingSecrets -}} +{{- if not (eq $nbSecrets (int .Values.replicaCount)) }} +mongodb: tls.replicaset.existingSecrets + tls.replicaset.existingSecrets Number of secrets and number of replicaset nodes must be the same. +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - Number of hidden secrets must be the same than number of hidden nodes. +*/}} +{{- define "mongodb.validateValues.hidden.existingSecrets" -}} +{{- if and .Values.tls.enabled (include "mongodb.hidden.enabled" .) (not (empty .Values.tls.hidden.existingSecrets)) }} +{{- $nbSecrets := len .Values.tls.hidden.existingSecrets -}} +{{- if not (eq $nbSecrets (int .Values.hidden.replicaCount)) }} +mongodb: tls.hidden.existingSecrets + tls.hidden.existingSecrets Number of secrets and number of hidden nodes must be the same. +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® exporter URI string - auth.enabled and/or tls.enabled must be enabled or it defaults +*/}} +{{- define "mongodb.mongodb_exporter.uri" -}} + {{- $tlsEnabled := .Values.tls.enabled -}} + {{- $mTlsEnabled := and $tlsEnabled .Values.tls.mTLS.enabled -}} + {{- $tlsArgs := "" -}} + {{- if $tlsEnabled -}} + {{- $tlsCertKeyFile := ternary "&tlsCertificateKeyFile=/certs/mongodb.pem" "" $mTlsEnabled -}} + {{- $tlsArgs = printf "tls=true%s&tlsCAFile=/certs/mongodb-ca-cert" $tlsCertKeyFile -}} + {{- end -}} + {{- if .Values.metrics.username -}} + {{- $uriAuth := ternary "$(echo $MONGODB_METRICS_USERNAME | sed -r \"s/@/%40/g;s/:/%3A/g\"):$(echo $MONGODB_METRICS_PASSWORD | sed -r \"s/@/%40/g;s/:/%3A/g\")@" "" .Values.auth.enabled -}} + {{- printf "mongodb://%slocalhost:%d/admin?%s" $uriAuth (int .Values.containerPorts.mongodb) $tlsArgs -}} + {{- else -}} + {{- $uriAuth := ternary "$MONGODB_ROOT_USER:$(echo $MONGODB_ROOT_PASSWORD | sed -r \"s/@/%40/g;s/:/%3A/g\")@" "" .Values.auth.enabled -}} + {{- printf "mongodb://%slocalhost:%d/admin?%s" $uriAuth (int .Values.containerPorts.mongodb) $tlsArgs -}} + {{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiGroup for PodSecurityPolicy. +*/}} +{{- define "podSecurityPolicy.apiGroup" -}} +{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "policy" -}} +{{- else -}} +{{- print "extensions" -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a TLS secret object should be created +*/}} +{{- define "mongodb.createTlsSecret" -}} +{{- if and .Values.tls.enabled (not .Values.tls.existingSecret) (include "mongodb.autoGenerateCerts" .) }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the secret containing MongoDB® TLS certificates +*/}} +{{- define "mongodb.tlsSecretName" -}} +{{- $secretName := .Values.tls.existingSecret -}} +{{- if $secretName -}} + {{- printf "%s" (tpl $secretName $) -}} +{{- else -}} + {{- printf "%s-ca" (include "mongodb.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if certificates must be auto generated +*/}} +{{- define "mongodb.autoGenerateCerts" -}} +{{- $standalone := (eq .Values.architecture "standalone") | ternary (not .Values.tls.standalone.existingSecret) true -}} +{{- $replicaset := (eq .Values.architecture "replicaset") | ternary (empty .Values.tls.replicaset.existingSecrets) true -}} +{{- $arbiter := (eq (include "mongodb.arbiter.enabled" .) "true") | ternary (not .Values.tls.arbiter.existingSecret) true -}} +{{- $hidden := (eq (include "mongodb.hidden.enabled" .) "true") | ternary (empty .Values.tls.hidden.existingSecrets) true -}} +{{- if and $standalone $replicaset $arbiter $hidden -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Generate argument list for mongodb-exporter +reference: https://github.com/percona/mongodb_exporter/blob/main/REFERENCE.md +*/}} +{{- define "mongodb.exporterArgs" -}} +{{- with .Values.metrics.collector -}} +{{- ternary " --collect-all" "" .all -}} +{{- ternary " --collector.diagnosticdata" "" .diagnosticdata -}} +{{- ternary " --collector.replicasetstatus" "" .replicasetstatus -}} +{{- ternary " --collector.dbstats" "" .dbstats -}} +{{- ternary " --collector.topmetrics" "" .topmetrics -}} +{{- ternary " --collector.indexstats" "" .indexstats -}} +{{- ternary " --collector.collstats" "" .collstats -}} +{{- if .collstatsColls -}} +{{- " --mongodb.collstats-colls=" -}} +{{- join "," .collstatsColls -}} +{{- end -}} +{{- if .indexstatsColls -}} +{{- " --mongodb.indexstats-colls=" -}} +{{- join "," .indexstatsColls -}} +{{- end -}} +{{- $limitArg := print " --collector.collstats-limit=" .collstatsLimit -}} +{{- ne (print .collstatsLimit) "0" | ternary $limitArg "" -}} +{{- end -}} +{{- ternary " --compatible-mode" "" .Values.metrics.compatibleMode -}} +{{- end -}} diff --git a/backing-services/mongodb/templates/arbiter/configmap.yaml b/backing-services/mongodb/templates/arbiter/configmap.yaml new file mode 100644 index 0000000..a3b3f4c --- /dev/null +++ b/backing-services/mongodb/templates/arbiter/configmap.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.arbiter.createConfigmap" .) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-arbiter" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: arbiter + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + mongodb.conf: |- + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.configuration "context" $) | nindent 4 }} +{{- end }} diff --git a/backing-services/mongodb/templates/arbiter/headless-svc.yaml b/backing-services/mongodb/templates/arbiter/headless-svc.yaml new file mode 100644 index 0000000..088eaf4 --- /dev/null +++ b/backing-services/mongodb/templates/arbiter/headless-svc.yaml @@ -0,0 +1,31 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.arbiter.enabled" .) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mongodb.arbiter.service.nameOverride" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: arbiter + {{- if or .Values.arbiter.service.headless.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.arbiter.service.headless.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + ports: + - name: tcp-mongodb + port: {{ .Values.arbiter.service.ports.mongodb }} + targetPort: mongodb + {{- if .Values.arbiter.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.arbiter.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: arbiter +{{- end }} diff --git a/backing-services/mongodb/templates/arbiter/pdb.yaml b/backing-services/mongodb/templates/arbiter/pdb.yaml new file mode 100644 index 0000000..0799eea --- /dev/null +++ b/backing-services/mongodb/templates/arbiter/pdb.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (include "mongodb.arbiter.enabled" .) .Values.arbiter.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ printf "%s-arbiter" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: arbiter + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.arbiter.pdb.minAvailable }} + minAvailable: {{ .Values.arbiter.pdb.minAvailable }} + {{- end }} + {{- if or .Values.arbiter.pdb.maxUnavailable (not .Values.arbiter.pdb.minAvailable) }} + maxUnavailable: {{ .Values.arbiter.pdb.maxUnavailable | default 1 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.arbiter.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: arbiter +{{- end }} diff --git a/backing-services/mongodb/templates/arbiter/statefulset.yaml b/backing-services/mongodb/templates/arbiter/statefulset.yaml new file mode 100644 index 0000000..9ab8f76 --- /dev/null +++ b/backing-services/mongodb/templates/arbiter/statefulset.yaml @@ -0,0 +1,318 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.arbiter.enabled" .) }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ printf "%s-arbiter" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.arbiter.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: arbiter + {{- if or .Values.arbiter.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.arbiter.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + serviceName: {{ include "mongodb.arbiter.service.nameOverride" . }} + podManagementPolicy: {{ .Values.arbiter.podManagementPolicy }} + replicas: 1 + {{- if .Values.arbiter.updateStrategy }} + updateStrategy: {{- toYaml .Values.arbiter.updateStrategy | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.arbiter.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: arbiter + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: arbiter + {{- if or (include "mongodb.arbiter.createConfigmap" .) .Values.arbiter.podAnnotations }} + annotations: + {{- if (include "mongodb.arbiter.createConfigmap" .) }} + checksum/configuration: {{ include (print $.Template.BasePath "/arbiter/configmap.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.arbiter.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.podAnnotations "context" $) | nindent 8 }} + {{- end }} + {{- end }} + spec: + {{- include "mongodb.imagePullSecrets" . | nindent 6 }} + {{- if .Values.arbiter.schedulerName }} + schedulerName: {{ .Values.arbiter.schedulerName | quote }} + {{- end }} + serviceAccountName: {{ template "mongodb.serviceAccountName" . }} + {{- if .Values.arbiter.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.arbiter.podAffinityPreset "component" "mongodb" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.arbiter.podAntiAffinityPreset "component" "mongodb" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.arbiter.nodeAffinityPreset.type "key" .Values.arbiter.nodeAffinityPreset.key "values" .Values.arbiter.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.arbiter.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.nodeSelector "context" $) | nindent 8 }} + {{- end }} + automountServiceAccountToken: {{ .Values.arbiter.automountServiceAccountToken }} + {{- if .Values.arbiter.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.arbiter.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.arbiter.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.topologySpreadConstraints "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.arbiter.priorityClassName }} + priorityClassName: {{ .Values.arbiter.priorityClassName }} + {{- end }} + {{- if .Values.arbiter.runtimeClassName }} + runtimeClassName: {{ .Values.arbiter.runtimeClassName }} + {{- end }} + {{- if .Values.arbiter.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.arbiter.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + {{ if .Values.arbiter.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.arbiter.terminationGracePeriodSeconds }} + {{- end }} + enableServiceLinks: {{ .Values.enableServiceLinks }} + initContainers: + {{- if .Values.arbiter.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.externalAccess.enabled ( or .Values.externalAccess.service.publicNames .Values.externalAccess.service.domain ) }} + {{- include "mongodb.initContainers.dnsCheck" . | nindent 8 }} + {{- end }} + {{- if and .Values.tls.enabled .Values.arbiter.enabled }} + - name: generate-tls-certs + image: {{ include "mongodb.tls.image" . }} + imagePullPolicy: {{ .Values.tls.image.pullPolicy | quote }} + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + mountPath: /certs/CAs + {{- else }} + - name: mongodb-certs-0 + mountPath: /certs-0 + {{- end }} + - name: certs + mountPath: /certs + - name: common-scripts + mountPath: /bitnami/scripts + command: + - /bitnami/scripts/generate-certs.sh + args: + - -s {{ include "mongodb.arbiter.service.nameOverride" . }} + {{- end }} + containers: + - name: mongodb-arbiter + image: {{ include "mongodb.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.arbiter.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.arbiter.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.arbiter.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.arbiter.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.args "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.arbiter.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MONGODB_REPLICA_SET_MODE + value: "arbiter" + - name: MONGODB_INITIAL_PRIMARY_HOST + value: {{ include "mongodb.initialPrimaryHost" . | quote }} + - name: MONGODB_REPLICA_SET_NAME + value: {{ .Values.replicaSetName | quote }} + - name: MONGODB_ADVERTISED_HOSTNAME + value: "$(MY_POD_NAME).{{ include "mongodb.arbiter.service.nameOverride" . }}.$(MY_POD_NAMESPACE).svc.{{ .Values.clusterDomain }}" + - name: MONGODB_PORT_NUMBER + value: {{ .Values.arbiter.containerPorts.mongodb | quote }} + - name: MONGODB_ENABLE_IPV6 + value: {{ ternary "yes" "no" .Values.enableIPv6 | quote }} + {{- if .Values.auth.enabled }} + - name: MONGODB_INITIAL_PRIMARY_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + - name: MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + - name: MONGODB_REPLICA_SET_KEY + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-replica-set-key + {{- end }} + - name: ALLOW_EMPTY_PASSWORD + value: {{ ternary "no" "yes" .Values.auth.enabled | quote }} + {{- $extraFlags := .Values.arbiter.extraFlags | join " " -}} + {{- if and .Values.tls.enabled .Values.arbiter.enabled }} + {{- if .Values.tls.mTLS.enabled }} + {{- $extraFlags = printf "--tlsCAFile=/certs/mongodb-ca-cert %s" $extraFlags }} + {{- end }} + {{- $extraFlags = printf "--tlsMode=%s --tlsCertificateKeyFile=/certs/mongodb.pem %s" .Values.tls.mode $extraFlags }} + {{- end }} + {{- if ne $extraFlags "" }} + - name: MONGODB_EXTRA_FLAGS + value: {{ $extraFlags | quote }} + {{- end }} + {{- if and .Values.tls.enabled .Values.arbiter.enabled }} + - name: MONGODB_CLIENT_EXTRA_FLAGS + value: --tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert + {{- end }} + {{- if .Values.arbiter.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.arbiter.extraEnvVarsCM .Values.arbiter.extraEnvVarsSecret }} + envFrom: + {{- if .Values.arbiter.extraEnvVarsCM }} + - configMapRef: + name: {{ tpl .Values.arbiter.extraEnvVarsCM . | quote }} + {{- end }} + {{- if .Values.arbiter.extraEnvVarsSecret }} + - secretRef: + name: {{ tpl .Values.arbiter.extraEnvVarsSecret . | quote }} + {{- end }} + {{- end }} + ports: + - containerPort: {{ .Values.arbiter.containerPorts.mongodb }} + name: mongodb + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.arbiter.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.arbiter.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.arbiter.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - pgrep + - mongod + {{- end }} + {{- if .Values.arbiter.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.arbiter.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.arbiter.readinessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: mongodb + {{- end }} + {{- if .Values.arbiter.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.arbiter.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.arbiter.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/startup-probe.sh + {{- end }} + {{- end }} + {{- if .Values.arbiter.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.resources "context" $) | nindent 12 }} + {{- else if ne .Values.arbiter.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.arbiter.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/conf + subPath: app-conf-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/tmp + subPath: app-tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/logs + subPath: app-logs-dir + - name: empty-dir + mountPath: /bitnami/mongodb + subPath: app-volume-dir + {{- if or .Values.arbiter.configuration .Values.arbiter.existingConfigmap }} + - name: config + mountPath: /opt/bitnami/mongodb/conf/mongodb.conf + subPath: mongodb.conf + {{- end }} + {{- if and .Values.tls.enabled .Values.arbiter.enabled }} + - name: certs + mountPath: /certs + {{- end }} + {{- if .Values.arbiter.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.arbiter.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: empty-dir + emptyDir: {} + {{- if or .Values.arbiter.configuration .Values.arbiter.existingConfigmap .Values.arbiter.extraVolumes .Values.tls.enabled }} + - name: common-scripts + configMap: + name: {{ printf "%s-common-scripts" (include "mongodb.fullname" .) }} + defaultMode: 0555 + {{- if or .Values.arbiter.configuration .Values.arbiter.existingConfigmap }} + - name: config + configMap: + name: {{ include "mongodb.arbiter.configmapName" . }} + {{- end }} + {{- if and .Values.tls.enabled .Values.arbiter.enabled }} + - name: certs + emptyDir: {} + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + secret: + secretName: {{ template "mongodb.tlsSecretName" . }} + items: + - key: mongodb-ca-cert + path: mongodb-ca-cert + mode: 0600 + - key: mongodb-ca-key + path: mongodb-ca-key + mode: 0600 + {{- else }} + - name: mongodb-certs-0 + secret: + secretName: {{ include "common.tplvalues.render" ( dict "value" .Values.tls.arbiter.existingSecret "context" $) }} + defaultMode: 256 + {{- end }} + {{- end }} + {{- if .Values.arbiter.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.extraVolumes "context" $) | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/mongodb/templates/backup/cronjob.yaml b/backing-services/mongodb/templates/backup/cronjob.yaml new file mode 100644 index 0000000..8ab2d1b --- /dev/null +++ b/backing-services/mongodb/templates/backup/cronjob.yaml @@ -0,0 +1,212 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.backup.enabled }} +apiVersion: batch/v1 +kind: CronJob +metadata: + name: {{ include "mongodb.fullname" . }}-mongodump + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: mongodump + {{- if .Values.backup.cronjob.labels }} + {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.labels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if or .Values.backup.cronjob.annotations .Values.commonAnnotations }} + annotations: + {{- if .Values.backup.cronjob.annotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.backup.cronjob.annotations "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} +spec: + schedule: {{ quote .Values.backup.cronjob.schedule }} + concurrencyPolicy: {{ .Values.backup.cronjob.concurrencyPolicy }} + failedJobsHistoryLimit: {{ .Values.backup.cronjob.failedJobsHistoryLimit }} + successfulJobsHistoryLimit: {{ .Values.backup.cronjob.successfulJobsHistoryLimit }} + {{- if .Values.backup.cronjob.startingDeadlineSeconds }} + startingDeadlineSeconds: {{ .Values.backup.cronjob.startingDeadlineSeconds }} + {{- end }} + jobTemplate: + spec: + {{- if .Values.backup.cronjob.backoffLimit }} + backoffLimit: {{ .Values.backup.cronjob.backoffLimit }} + {{- end }} + {{- if .Values.backup.cronjob.ttlSecondsAfterFinished }} + ttlSecondsAfterFinished: {{ .Values.backup.cronjob.ttlSecondsAfterFinished }} + {{- end }} + template: + metadata: + labels: {{- include "common.labels.standard" . | nindent 12 }} + app.kubernetes.io/component: mongodump + {{- if .Values.backup.cronjob.labels }} + {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.labels "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 12 }} + {{- end }} + {{- if or .Values.backup.cronjob.annotations .Values.commonAnnotations }} + annotations: + {{- if .Values.backup.cronjob.annotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.backup.cronjob.annotations "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 12 }} + {{- end }} + {{- end }} + spec: + {{- include "mongodb.imagePullSecrets" . | nindent 10 }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.podSecurityContext "context" $) | nindent 12 }} + {{- end }} + enableServiceLinks: {{ .Values.enableServiceLinks }} + {{- if .Values.tls.enabled }} + initContainers: + - name: generate-tls-certs + image: {{ include "mongodb.tls.image" . }} + imagePullPolicy: {{ .Values.tls.image.pullPolicy | quote }} + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + mountPath: /certs/CAs + {{- else }} + - name: mongodb-certs-0 + mountPath: /certs-0 + {{- end }} + - name: certs + mountPath: /certs + - name: common-scripts + mountPath: /bitnami/scripts + command: + - /bitnami/scripts/generate-certs.sh + args: + - -s {{ include "mongodb.service.nameOverride" . }} + {{- if .Values.externalAccess.service.loadBalancerIPs }} + - -i {{ join "," .Values.externalAccess.service.loadBalancerIPs }} + {{- end }} + {{- if or .Values.tls.extraDnsNames .Values.externalAccess.service.publicNames }} + - -n {{ join "," ( concat .Values.tls.extraDnsNames .Values.externalAccess.service.publicNames ) }} + {{- end }} + {{- if .Values.tls.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.tls.resources "context" $) | nindent 12 }} + {{- else if ne .Values.tls.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.tls.resourcesPreset) | nindent 16 }} + {{- end }} + {{- end }} + containers: + - name: {{ include "mongodb.fullname" . }}-mongodump + image: {{ include "mongodb.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + env: + {{- if .Values.auth.enabled }} + - name: MONGODB_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + - name: MONGODB_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + {{- end }} + - name: MONGODB_SERVICE_NAME + value: {{ include "mongodb.service.nameOverride" . }} + - name: MONGODB_PORT_NUMBER + value: {{ .Values.containerPorts.mongodb | quote }} + - name: MONGODUMP_DIR + value: {{ .Values.backup.cronjob.storage.mountPath }} + {{- if .Values.tls.enabled }} + - name: MONGODB_CLIENT_EXTRA_FLAGS + value: --ssl --sslPEMKeyFile=/certs/mongodb.pem --sslCAFile=/certs/mongodb-ca-cert + {{- end }} + {{- if .Values.backup.cronjob.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.command "context" $) | nindent 14 }} + {{- else }} + command: + - /bin/sh + - -c + - "mongodump {{- if .Values.auth.enabled }} --username=${MONGODB_ROOT_USER} --password=${MONGODB_ROOT_PASSWORD} --authenticationDatabase=admin {{- end }} --host=${MONGODB_SERVICE_NAME} --port=${MONGODB_PORT_NUMBER} ${MONGODB_CLIENT_EXTRA_FLAGS} {{- if (eq $.Values.architecture "replicaset") }}--oplog{{- end }} --gzip --archive=${MONGODUMP_DIR}/mongodump-$(date '+%Y-%m-%d-%H-%M').gz" + {{- end }} + {{- if .Values.backup.cronjob.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.resources "context" $) | nindent 14 }} + {{- else if ne .Values.backup.cronjob.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.backup.cronjob.resourcesPreset) | nindent 14 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if .Values.tls.enabled }} + - name: certs + mountPath: /certs + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + mountPath: /certs/CAs + {{- else }} + - name: mongodb-certs-0 + mountPath: /certs-0 + {{- end }} + {{- end }} + - name: datadir + mountPath: {{ .Values.backup.cronjob.storage.mountPath }} + subPath: {{ .Values.backup.cronjob.storage.subPath }} + {{- if .Values.backup.cronjob.containerSecurityContext.enabled }} + securityContext: + {{- include "common.tplvalues.render" ( dict "value" ( omit .Values.backup.cronjob.containerSecurityContext "enabled" ) "context" $) | nindent 14 }} + {{- end }} + restartPolicy: {{ .Values.backup.cronjob.restartPolicy }} + volumes: + - name: empty-dir + emptyDir: {} + - name: common-scripts + configMap: + name: {{ printf "%s-common-scripts" (include "mongodb.fullname" .) }} + defaultMode: 0550 + {{- if .Values.tls.enabled }} + - name: certs + emptyDir: {} + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + secret: + secretName: {{ template "mongodb.tlsSecretName" . }} + items: + - key: mongodb-ca-cert + path: mongodb-ca-cert + mode: 0600 + - key: mongodb-ca-key + path: mongodb-ca-key + mode: 0600 + {{- else }} + - name: mongodb-certs-0 + secret: + secretName: {{ include "common.tplvalues.render" ( dict "value" .Values.tls.standalone.existingSecret "context" $) }} + defaultMode: 256 + {{- end }} + {{- end }} + {{- if .Values.backup.cronjob.storage.existingClaim }} + - name: datadir + persistentVolumeClaim: + claimName: {{ printf "%s" (tpl .Values.backup.cronjob.storage.existingClaim .) }} + {{- else }} + - name: datadir + persistentVolumeClaim: + claimName: {{ include "mongodb.fullname" . }}-mongodump + {{- end }} +{{- end }} diff --git a/backing-services/mongodb/templates/backup/pvc.yaml b/backing-services/mongodb/templates/backup/pvc.yaml new file mode 100644 index 0000000..583ea41 --- /dev/null +++ b/backing-services/mongodb/templates/backup/pvc.yaml @@ -0,0 +1,41 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.backup.enabled (not .Values.backup.cronjob.storage.existingClaim) -}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "mongodb.fullname" . }}-mongodump + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: mongodump + {{- if .Values.backup.cronjob.labels }} + {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.labels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if or .Values.backup.cronjob.annotations .Values.commonAnnotations .Values.backup.cronjob.storage.resourcePolicy}} + annotations: + {{- if .Values.backup.cronjob.annotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.backup.cronjob.annotations "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.backup.cronjob.storage.resourcePolicy }} + helm.sh/resource-policy: {{ .Values.backup.cronjob.storage.resourcePolicy | quote }} + {{- end }} + {{- end }} +spec: + accessModes: + {{- range .Values.backup.cronjob.storage.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.backup.cronjob.storage.size | quote }} + {{ include "common.storage.class" (dict "persistence" .Values.backup.cronjob.storage "global" .Values.global) | nindent 2 }} +{{- end }} diff --git a/backing-services/mongodb/templates/common-scripts-cm.yaml b/backing-services/mongodb/templates/common-scripts-cm.yaml new file mode 100644 index 0000000..6f65de4 --- /dev/null +++ b/backing-services/mongodb/templates/common-scripts-cm.yaml @@ -0,0 +1,143 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-common-scripts" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + {{- $fullname := include "mongodb.fullname" . }} + startup-probe.sh: | + #!/bin/bash + {{- if .Values.tls.enabled }} + # Probes are using localhost/127.0.0.1 to tests if the service is up, ready or healthy. If TLS is enabled, we shouldn't validate the certificate hostname. + TLS_OPTIONS='--tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert --tlsAllowInvalidHostnames' + {{- end }} + exec mongosh $TLS_OPTIONS --port $MONGODB_PORT_NUMBER --eval 'if (!(db.hello().isWritablePrimary || db.hello().secondary)) { throw new Error("Not ready") }' + readiness-probe.sh: | + #!/bin/bash + {{- if .Values.tls.enabled }} + # Probes are using localhost/127.0.0.1 to tests if the service is up, ready or healthy. If TLS is enabled, we shouldn't validate the certificate hostname. + TLS_OPTIONS='--tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert --tlsAllowInvalidHostnames' + {{- end }} + # Run the proper check depending on the version + [[ $(mongod -version | grep "db version") =~ ([0-9]+\.[0-9]+\.[0-9]+) ]] && VERSION=${BASH_REMATCH[1]} + . /opt/bitnami/scripts/libversion.sh + VERSION_MAJOR="$(get_sematic_version "$VERSION" 1)" + VERSION_MINOR="$(get_sematic_version "$VERSION" 2)" + VERSION_PATCH="$(get_sematic_version "$VERSION" 3)" + readiness_test='db.isMaster().ismaster || db.isMaster().secondary' + if [[ ( "$VERSION_MAJOR" -ge 5 ) || ( "$VERSION_MAJOR" -ge 4 && "$VERSION_MINOR" -ge 4 && "$VERSION_PATCH" -ge 2 ) ]]; then + readiness_test='db.hello().isWritablePrimary || db.hello().secondary' + fi + exec mongosh $TLS_OPTIONS --port $MONGODB_PORT_NUMBER --eval "if (!(${readiness_test})) { throw new Error(\"Not ready\") }" + ping-mongodb.sh: | + #!/bin/bash + {{- if .Values.tls.enabled }} + # Probes are using localhost/127.0.0.1 to tests if the service is up, ready or healthy. If TLS is enabled, we shouldn't validate the certificate hostname. + TLS_OPTIONS='--tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert --tlsAllowInvalidHostnames' + {{- end }} + exec mongosh $TLS_OPTIONS --port $MONGODB_PORT_NUMBER --eval "db.adminCommand('ping')" + {{- if .Values.tls.enabled }} + generate-certs.sh: | + #!/bin/bash + {{- if (include "mongodb.autoGenerateCerts" .) }} + additional_ips=() + additional_names=() + while getopts "i:n:s:" flag + do + case "${flag}" in + i) read -a additional_ips <<< ${OPTARG//,/ } ;; + n) read -a additional_names <<< ${OPTARG//,/ } ;; + s) svc=${OPTARG// /} ;; + \?) exit 1 ;; + esac + done + + my_hostname=$(hostname) + cp /certs/CAs/* /certs/ + cat >/certs/openssl.cnf <>/certs/openssl.cnf <>/certs/openssl.cnf < /certs/mongodb.pem + cd /certs/ + shopt -s extglob + rm -rf !(mongodb-ca-cert|mongodb.pem|CAs|openssl.cnf) + chmod 0600 mongodb-ca-cert mongodb.pem + {{- else }} + {{- if eq .Values.architecture "standalone" }} + ID="0" + {{- else }} + if [[ "$MY_POD_NAME" =~ "arbiter-0"$ ]]; then + ID="0" + elif [[ "$MY_POD_NAME" =~ "hidden-"[0-9]{1,}$ ]]; then + ID="${MY_POD_NAME#"{{ printf "%s-hidden-" $fullname }}"}" + else + ID="${MY_POD_NAME#"{{ $fullname }}-"}" + fi + {{- end }} + + {{- if .Values.tls.pemChainIncluded }} + #Split the pem chain by the END CERTIFICATE string and store in files /certs/xx00, /certs/xx01 etc. + cat /certs-${ID}/tls.crt | csplit - -s -z '/\-*END CERTIFICATE\-*/+1' '{*}' -f /certs/xx + + #Use first certificate as leaf node and combine with key to store in pem file + cat "/certs/xx00" "/certs-${ID}/tls.key" > "/certs/mongodb.pem" + + #Use remaining intermediate certificates for ca.crt + echo $(find /certs/ -not -name 'xx00' -name 'xx*') | sort | xargs cat > "/certs/mongodb-ca-cert" + + rm -rf /certs/xx* + {{- else }} + cat "/certs-${ID}/tls.crt" "/certs-${ID}/tls.key" > "/certs/mongodb.pem" + cp "/certs-${ID}/ca.crt" "/certs/mongodb-ca-cert" + {{- end }} + + chmod 0600 /certs/mongodb-ca-cert /certs/mongodb.pem + {{- end }} + {{- end }} diff --git a/backing-services/mongodb/templates/configmap.yaml b/backing-services/mongodb/templates/configmap.yaml new file mode 100644 index 0000000..0110445 --- /dev/null +++ b/backing-services/mongodb/templates/configmap.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.createConfigmap" .) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + mongodb.conf: |- + {{- include "common.tplvalues.render" (dict "value" .Values.configuration "context" $) | nindent 4 }} +{{- end }} diff --git a/backing-services/mongodb/templates/extra-list.yaml b/backing-services/mongodb/templates/extra-list.yaml new file mode 100644 index 0000000..329f5c6 --- /dev/null +++ b/backing-services/mongodb/templates/extra-list.yaml @@ -0,0 +1,9 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/backing-services/mongodb/templates/hidden/configmap.yaml b/backing-services/mongodb/templates/hidden/configmap.yaml new file mode 100644 index 0000000..fb26bdd --- /dev/null +++ b/backing-services/mongodb/templates/hidden/configmap.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.hidden.createConfigmap" .) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-hidden" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: hidden + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + mongodb.conf: |- + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.configuration "context" $) | nindent 4 }} +{{- end }} diff --git a/backing-services/mongodb/templates/hidden/external-access-svc.yaml b/backing-services/mongodb/templates/hidden/external-access-svc.yaml new file mode 100644 index 0000000..4cfa531 --- /dev/null +++ b/backing-services/mongodb/templates/hidden/external-access-svc.yaml @@ -0,0 +1,69 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (include "mongodb.hidden.enabled" .) .Values.externalAccess.hidden.enabled }} +{{- $fullName := include "mongodb.fullname" . }} +{{- $replicaCount := .Values.hidden.replicaCount | int }} +{{- $root := . }} + +{{- range $i, $e := until $replicaCount }} +{{- $targetPod := printf "%s-hidden-%d" (printf "%s" $fullName) $i }} +{{- $_ := set $ "targetPod" $targetPod }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-hidden-%d-external" $fullName $i }} + namespace: {{ include "mongodb.namespace" $ }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $root.Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: hidden + pod: {{ $targetPod }} + {{- if or $root.Values.externalAccess.hidden.service.annotations $root.Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list $root.Values.externalAccess.hidden.service.annotations $root.Values.commonAnnotations ) "context" $ ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ $root.Values.externalAccess.hidden.service.type }} + {{- if eq $root.Values.externalAccess.hidden.service.type "LoadBalancer" }} + {{- if not (empty $root.Values.externalAccess.hidden.service.loadBalancerIPs) }} + loadBalancerIP: {{ index $root.Values.externalAccess.hidden.service.loadBalancerIPs $i }} + {{- end }} + {{- if $root.Values.externalAccess.hidden.service.loadBalancerClass }} + loadBalancerClass: {{ $root.Values.externalAccess.hidden.service.loadBalancerClass }} + {{- end }} + {{- if $root.Values.externalAccess.hidden.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{- toYaml $root.Values.externalAccess.hidden.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + allocateLoadBalancerNodePorts: {{ $root.Values.externalAccess.hidden.service.allocateLoadBalancerNodePorts }} + {{- end }} + {{- if (or (eq $root.Values.externalAccess.hidden.service.type "LoadBalancer") (eq $root.Values.externalAccess.hidden.service.type "NodePort")) }} + externalTrafficPolicy: {{ $root.Values.externalAccess.hidden.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if $root.Values.externalAccess.hidden.service.sessionAffinity }} + sessionAffinity: {{ $root.Values.externalAccess.hidden.service.sessionAffinity }} + {{- end }} + {{- if $root.Values.externalAccess.hidden.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" $root.Values.externalAccess.hidden.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + publishNotReadyAddresses: true + ports: + - name: {{ $root.Values.externalAccess.hidden.service.portName | quote }} + port: {{ $root.Values.externalAccess.hidden.service.ports.mongodb }} + {{- if not (empty $root.Values.externalAccess.hidden.service.nodePorts) }} + {{- $nodePort := index $root.Values.externalAccess.hidden.service.nodePorts $i }} + nodePort: {{ $nodePort }} + {{- else }} + nodePort: null + {{- end }} + targetPort: mongodb + {{- if $root.Values.externalAccess.hidden.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" $root.Values.externalAccess.hidden.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list $root.Values.hidden.podLabels $root.Values.commonLabels ) "context" $ ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: hidden + statefulset.kubernetes.io/pod-name: {{ $targetPod }} +--- +{{- end }} +{{- end }} diff --git a/backing-services/mongodb/templates/hidden/headless-svc.yaml b/backing-services/mongodb/templates/hidden/headless-svc.yaml new file mode 100644 index 0000000..a2af519 --- /dev/null +++ b/backing-services/mongodb/templates/hidden/headless-svc.yaml @@ -0,0 +1,32 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.hidden.enabled" .) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mongodb.hidden.service.nameOverride" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: hidden + {{- if or .Values.hidden.service.headless.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.hidden.service.headless.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + publishNotReadyAddresses: true + ports: + - name: {{ .Values.hidden.service.portName | quote }} + port: {{ .Values.hidden.service.ports.mongodb }} + targetPort: mongodb + {{- if .Values.hidden.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.hidden.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: hidden +{{- end }} diff --git a/backing-services/mongodb/templates/hidden/pdb.yaml b/backing-services/mongodb/templates/hidden/pdb.yaml new file mode 100644 index 0000000..9125067 --- /dev/null +++ b/backing-services/mongodb/templates/hidden/pdb.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (include "mongodb.hidden.enabled" .) .Values.hidden.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ printf "%s-hidden" (include "mongodb.fullname" . )}} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: hidden + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.hidden.pdb.minAvailable }} + minAvailable: {{ .Values.hidden.pdb.minAvailable }} + {{- end }} + {{- if or .Values.hidden.pdb.maxUnavailable (not .Values.hidden.pdb.minAvailable) }} + maxUnavailable: {{ .Values.hidden.pdb.maxUnavailable | default 1 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.hidden.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: hidden +{{- end }} diff --git a/backing-services/mongodb/templates/hidden/statefulset.yaml b/backing-services/mongodb/templates/hidden/statefulset.yaml new file mode 100644 index 0000000..8a70869 --- /dev/null +++ b/backing-services/mongodb/templates/hidden/statefulset.yaml @@ -0,0 +1,551 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.hidden.enabled" .) }} +{{- $replicaCount := int .Values.hidden.replicaCount }} +{{- $loadBalancerIPListLength := len .Values.externalAccess.hidden.service.loadBalancerIPs }} +{{- if not (and .Values.externalAccess.hidden.enabled (not .Values.externalAccess.autoDiscovery.enabled) (not (eq $replicaCount $loadBalancerIPListLength )) (eq .Values.externalAccess.hidden.service.type "LoadBalancer")) }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ printf "%s-hidden" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.hidden.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: hidden + {{- if or .Values.hidden.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.hidden.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + serviceName: {{ include "mongodb.hidden.service.nameOverride" . }} + podManagementPolicy: {{ .Values.hidden.podManagementPolicy }} + replicas: {{ .Values.hidden.replicaCount }} + {{- if .Values.hidden.updateStrategy }} + updateStrategy: {{- toYaml .Values.hidden.updateStrategy | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.hidden.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: hidden + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: hidden + {{- if or (include "mongodb.hidden.createConfigmap" .) .Values.hidden.podAnnotations }} + annotations: + {{- if (include "mongodb.hidden.createConfigmap" .) }} + checksum/configuration: {{ include (print $.Template.BasePath "/hidden/configmap.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.hidden.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.podAnnotations "context" $) | nindent 8 }} + {{- end }} + {{- end }} + spec: + {{- include "mongodb.imagePullSecrets" . | nindent 6 }} + {{- if .Values.hidden.schedulerName }} + schedulerName: {{ .Values.hidden.schedulerName | quote }} + {{- end }} + serviceAccountName: {{ template "mongodb.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.hidden.automountServiceAccountToken }} + {{- if .Values.hidden.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.hidden.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.hidden.podAffinityPreset "component" "hidden" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.hidden.podAntiAffinityPreset "component" "hidden" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.hidden.nodeAffinityPreset.type "key" .Values.hidden.nodeAffinityPreset.key "values" .Values.hidden.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.hidden.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.hidden.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.hidden.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.topologySpreadConstraints "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.hidden.priorityClassName }} + priorityClassName: {{ .Values.hidden.priorityClassName }} + {{- end }} + {{- if .Values.hidden.runtimeClassName }} + runtimeClassName: {{ .Values.hidden.runtimeClassName }} + {{- end }} + {{- if .Values.hidden.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.hidden.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + {{ if .Values.hidden.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.hidden.terminationGracePeriodSeconds }} + {{- end }} + enableServiceLinks: {{ .Values.enableServiceLinks }} + initContainers: + {{- if .Values.hidden.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.volumePermissions.enabled .Values.hidden.persistence.enabled }} + {{- include "mongodb.initContainer.volumePermissions" . | indent 8 }} + {{- end }} + {{- if and .Values.externalAccess.hidden.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.hidden.service.type "LoadBalancer") }} + {{- include "mongodb.initContainers.autoDiscovery" . | indent 8 }} + {{- end }} + {{- if and .Values.externalAccess.enabled ( or .Values.externalAccess.service.publicNames .Values.externalAccess.service.domain ) }} + {{- include "mongodb.initContainers.dnsCheck" . | indent 8 }} + {{- end }} + {{- include "mongodb.initContainer.prepareLogDir" . | nindent 8 }} + {{- if .Values.tls.enabled }} + - name: generate-tls-certs + image: {{ include "mongodb.tls.image" . }} + imagePullPolicy: {{ .Values.tls.image.pullPolicy | quote }} + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + volumeMounts: + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + mountPath: /certs/CAs + {{- else }} + {{- range $index, $_ := .Values.tls.hidden.existingSecrets }} + - name: mongodb-certs-{{ $index }} + mountPath: /certs-{{ $index }} + {{- end }} + {{- end }} + - name: certs + mountPath: /certs + - name: common-scripts + mountPath: /bitnami/scripts + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + command: + - /bitnami/scripts/generate-certs.sh + args: + - -s {{ include "mongodb.hidden.service.nameOverride" . }} + {{- if .Values.externalAccess.hidden.service.loadBalancerIPs }} + - -i {{ join "," .Values.externalAccess.hidden.service.loadBalancerIPs }} + {{- end }} + {{- if or .Values.tls.extraDnsNames .Values.externalAccess.service.publicNames }} + - -n {{ join "," ( concat .Values.tls.extraDnsNames .Values.externalAccess.service.publicNames ) }} + {{- end }} + {{- if .Values.tls.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.tls.resources "context" $) | nindent 12 }} + {{- else if ne .Values.tls.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.tls.resourcesPreset) | nindent 12 }} + {{- end }} + {{- end }} + containers: + - name: mongodb + image: {{ include "mongodb.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.hidden.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.hidden.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.hidden.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.command "context" $) | nindent 12 }} + {{- else }} + command: + - /scripts/setup-hidden.sh + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.hidden.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.args "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.hidden.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + {{- if and .Values.externalAccess.hidden.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.hidden.service.type "LoadBalancer") }} + - name: SHARED_FILE + value: "/shared/info.txt" + {{- end }} + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: MY_POD_HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MONGODB_REPLICA_SET_MODE + value: "hidden" + - name: MONGODB_INITIAL_PRIMARY_HOST + value: {{ include "mongodb.initialPrimaryHost" . | quote }} + - name: MONGODB_REPLICA_SET_NAME + value: {{ .Values.replicaSetName | quote }} + {{- if and .Values.replicaSetHostnames (not .Values.externalAccess.hidden.enabled) }} + - name: MONGODB_ADVERTISED_HOSTNAME + value: "$(MY_POD_NAME).{{ include "mongodb.hidden.service.nameOverride" . }}.$(MY_POD_NAMESPACE).svc.{{ .Values.clusterDomain }}" + {{- end }} + {{- $customUsers := include "mongodb.customUsers" . -}} + {{- $customDatabases := include "mongodb.customDatabases" . -}} + {{- if not (empty $customUsers) }} + - name: MONGODB_EXTRA_USERNAMES + value: {{ $customUsers | quote }} + {{- end }} + {{- if not (empty $customDatabases) }} + - name: MONGODB_EXTRA_DATABASES + value: {{ $customDatabases | quote }} + {{- end }} + {{- if .Values.auth.enabled }} + {{- if and (not (empty $customUsers)) (not (empty $customDatabases)) }} + - name: MONGODB_EXTRA_PASSWORDS + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-passwords + {{- end }} + - name: MONGODB_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + - name: MONGODB_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + - name: MONGODB_REPLICA_SET_KEY + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-replica-set-key + {{- end }} + {{- if and .Values.metrics.enabled (not (empty .Values.metrics.username)) }} + - name: MONGODB_METRICS_USERNAME + value: {{ .Values.metrics.username | quote }} + {{- if .Values.auth.enabled }} + - name: MONGODB_METRICS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-metrics-password + {{- end }} + {{- end }} + - name: ALLOW_EMPTY_PASSWORD + value: {{ ternary "no" "yes" .Values.auth.enabled | quote }} + - name: MONGODB_SYSTEM_LOG_VERBOSITY + value: {{ .Values.systemLogVerbosity | quote }} + - name: MONGODB_DISABLE_SYSTEM_LOG + value: {{ ternary "yes" "no" .Values.disableSystemLog | quote }} + - name: MONGODB_DISABLE_JAVASCRIPT + value: {{ ternary "yes" "no" .Values.disableJavascript | quote }} + - name: MONGODB_ENABLE_JOURNAL + value: {{ ternary "yes" "no" .Values.enableJournal | quote }} + - name: MONGODB_PORT_NUMBER + value: {{ .Values.hidden.containerPorts.mongodb | quote }} + - name: MONGODB_ENABLE_IPV6 + value: {{ ternary "yes" "no" .Values.enableIPv6 | quote }} + - name: MONGODB_ENABLE_DIRECTORY_PER_DB + value: {{ ternary "yes" "no" .Values.directoryPerDB | quote }} + {{- $extraFlags := .Values.hidden.extraFlags | join " " -}} + {{- if .Values.tls.enabled }} + {{- if .Values.tls.mTLS.enabled }} + {{- $extraFlags = printf "--tlsCAFile=/certs/mongodb-ca-cert %s" $extraFlags }} + {{- end }} + {{- $extraFlags = printf "--tlsMode=%s --tlsCertificateKeyFile=/certs/mongodb.pem %s" .Values.tls.mode $extraFlags }} + {{- end }} + {{- if ne $extraFlags "" }} + - name: MONGODB_EXTRA_FLAGS + value: {{ $extraFlags | quote }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: MONGODB_CLIENT_EXTRA_FLAGS + value: --tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert + {{- end }} + {{- if .Values.hidden.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.hidden.extraEnvVarsCM .Values.hidden.extraEnvVarsSecret }} + envFrom: + {{- if .Values.hidden.extraEnvVarsCM }} + - configMapRef: + name: {{ tpl .Values.hidden.extraEnvVarsCM . | quote }} + {{- end }} + {{- if .Values.hidden.extraEnvVarsSecret }} + - secretRef: + name: {{ tpl .Values.hidden.extraEnvVarsSecret . | quote }} + {{- end }} + {{- end }} + ports: + - containerPort: {{ .Values.hidden.containerPorts.mongodb }} + name: mongodb + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.hidden.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.hidden.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.hidden.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/ping-mongodb.sh + {{- end }} + {{- if .Values.hidden.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.hidden.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.hidden.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/readiness-probe.sh + {{- end }} + {{- if .Values.hidden.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.hidden.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.hidden.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/startup-probe.sh + {{- end }} + {{- end }} + {{- if .Values.hidden.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.resources "context" $) | nindent 12 }} + {{- else if ne .Values.hidden.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.hidden.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: datadir + mountPath: {{ .Values.hidden.persistence.mountPath }} + subPath: {{ .Values.hidden.persistence.subPath }} + - name: common-scripts + mountPath: /bitnami/scripts + {{- if or .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + mountPath: /docker-entrypoint-initdb.d + {{- end }} + {{- if or .Values.hidden.configuration .Values.hidden.existingConfigmap }} + - name: config + mountPath: /opt/bitnami/mongodb/conf/mongodb.conf + subPath: mongodb.conf + {{- end }} + - name: scripts + mountPath: /scripts/setup-hidden.sh + subPath: setup-hidden.sh + {{- if and .Values.externalAccess.hidden.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.hidden.service.type "LoadBalancer") }} + - name: shared + mountPath: /shared + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + mountPath: /certs + {{- end }} + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/conf + subPath: app-conf-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/tmp + subPath: app-tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/logs + subPath: app-logs-dir + - name: empty-dir + mountPath: /.mongodb + subPath: mongosh-home + {{- if .Values.hidden.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ template "mongodb.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.metrics.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -ec + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.metrics.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.args "context" $) | nindent 12 }} + {{- else }} + args: + - | + /bin/mongodb_exporter {{ include "mongodb.exporterArgs" $ }} --mongodb.direct-connect --mongodb.global-conn-pool --mongodb.uri "{{ include "mongodb.mongodb_exporter.uri" . }}" {{ .Values.metrics.extraFlags }} + {{- end }} + env: + {{- if .Values.auth.enabled }} + {{- if not .Values.metrics.username }} + - name: MONGODB_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + - name: MONGODB_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + {{- else }} + - name: MONGODB_METRICS_USERNAME + value: {{ .Values.metrics.username | quote }} + - name: MONGODB_METRICS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-metrics-password + {{- end }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if .Values.tls.enabled }} + - name: certs + mountPath: /certs + {{- end }} + - name: empty-dir + mountPath: /opt/bitnami/redis-cluster/tmp + subPath: app-tmp-dir + {{- if .Values.metrics.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + ports: + - name: metrics + containerPort: 9216 + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.resources "context" $) | nindent 12 }} + {{- else if ne .Values.metrics.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.metrics.resourcesPreset) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.hidden.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: empty-dir + emptyDir: {} + - name: common-scripts + configMap: + name: {{ printf "%s-common-scripts" (include "mongodb.fullname" .) }} + defaultMode: 0555 + {{- if or .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + configMap: + name: {{ template "mongodb.initdbScriptsCM" . }} + {{- end }} + {{- if or .Values.hidden.configuration .Values.hidden.existingConfigmap }} + - name: config + configMap: + name: {{ include "mongodb.hidden.configmapName" . }} + {{- end }} + {{- if and .Values.externalAccess.hidden.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.hidden.service.type "LoadBalancer") }} + - name: shared + emptyDir: {} + {{- end }} + - name: scripts + configMap: + name: {{ printf "%s-scripts" (include "mongodb.fullname" .) }} + defaultMode: 0755 + {{- if .Values.hidden.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.extraVolumes "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + emptyDir: {} + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + secret: + secretName: {{ template "mongodb.tlsSecretName" . }} + items: + - key: mongodb-ca-cert + path: mongodb-ca-cert + mode: 0600 + - key: mongodb-ca-key + path: mongodb-ca-key + mode: 0600 + {{- else }} + {{- range $index, $secret := .Values.tls.hidden.existingSecrets }} + - name: mongodb-certs-{{ $index }} + secret: + secretName: {{ include "common.tplvalues.render" ( dict "value" $secret "context" $) }} + defaultMode: 256 + {{- end }} + {{- end }} + {{- end }} + {{- if not .Values.hidden.persistence.enabled }} + - name: datadir + {{- if .Values.hidden.persistence.medium }} + emptyDir: + medium: {{ .Values.hidden.persistence.medium | quote }} + {{- else }} + emptyDir: {} + {{- end }} + {{- else }} + volumeClaimTemplates: + - metadata: + name: datadir + {{- if .Values.hidden.persistence.annotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.persistence.annotations "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.persistence.labels }} + labels: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.labels "context" $) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.hidden.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.hidden.persistence.size | quote }} + {{- if .Values.hidden.persistence.volumeClaimTemplates.requests }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.persistence.volumeClaimTemplates.requests "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.hidden.persistence.volumeClaimTemplates.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.persistence.volumeClaimTemplates.dataSource "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.hidden.persistence.volumeClaimTemplates.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.persistence.volumeClaimTemplates.selector "context" $) | nindent 10 }} + {{- end }} + {{ include "common.storage.class" (dict "persistence" .Values.hidden.persistence "global" .Values.global) }} + {{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/mongodb/templates/initialization-configmap.yaml b/backing-services/mongodb/templates/initialization-configmap.yaml new file mode 100644 index 0000000..2c1273c --- /dev/null +++ b/backing-services/mongodb/templates/initialization-configmap.yaml @@ -0,0 +1,19 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.initdbScripts (not .Values.initdbScriptsConfigMap) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-init-scripts" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: +{{- include "common.tplvalues.render" (dict "value" .Values.initdbScripts "context" .) | nindent 2 }} +{{- end }} diff --git a/backing-services/mongodb/templates/metrics-svc.yaml b/backing-services/mongodb/templates/metrics-svc.yaml new file mode 100644 index 0000000..b6bd266 --- /dev/null +++ b/backing-services/mongodb/templates/metrics-svc.yaml @@ -0,0 +1,31 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.metrics.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-metrics" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: metrics + {{- if or .Values.metrics.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.metrics.service.type }} + ports: + - port: {{ .Values.metrics.service.ports.metrics }} + targetPort: metrics + protocol: TCP + name: http-metrics + {{- if .Values.metrics.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb +{{- end }} diff --git a/backing-services/mongodb/templates/networkpolicy.yaml b/backing-services/mongodb/templates/networkpolicy.yaml new file mode 100644 index 0000000..4e9f2f2 --- /dev/null +++ b/backing-services/mongodb/templates/networkpolicy.yaml @@ -0,0 +1,98 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ include "common.capabilities.networkPolicy.apiVersion" . }} +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if or .Values.annotations .Values.commonAnnotation }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: mongodb + policyTypes: + - Ingress + - Egress + {{- if .Values.networkPolicy.allowExternalEgress }} + egress: + - {} + {{- else }} + egress: + # Allow dns resolution + - ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + # Allow connection to other cluster pods + - ports: + - port: {{ .Values.containerPorts.mongodb }} + to: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }} + {{- if (and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled) }} + {{- $kubernetesEndpoints := lookup "v1" "Endpoints" (include "common.names.namespace" .) "kubernetes" }} + {{- range $kubernetesEndpoints.subsets }} + # Allow connection to API server, required by auto-discovery containers + - ports: + {{- range .ports }} + - port: {{ .port }} + {{- end }} + to: + {{- range .addresses }} + - ipBlock: + cidr: {{ printf "%s/32" .ip }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.networkPolicy.extraEgress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.rts.networkPolicy.extraEgress "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} + ingress: + - ports: + - port: {{ .Values.containerPorts.mongodb }} + {{- if .Values.metrics.enabled }} + - port: {{ .Values.metrics.containerPort }} + {{- end }} + {{- if not .Values.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }} + app.kubernetes.io/component: mongodb + {{- if .Values.networkPolicy.addExternalClientAccess }} + - podSelector: + matchLabels: + {{ template "common.names.fullname" . }}-client: "true" + {{- end }} + {{- if .Values.networkPolicy.ingressPodMatchLabels }} + - podSelector: + matchLabels: {{- include "common.tplvalues.render" (dict "value" .Values.networkPolicy.ingressPodMatchLabels "context" $ ) | nindent 14 }} + {{- end }} + {{- $ingressNSMatchLabels := coalesce .Values.networkPolicy.ingressNSMatchLabels .Values.networkPolicy.namespaceSelector }} + {{- if $ingressNSMatchLabels }} + - namespaceSelector: + matchLabels: {{- include "common.tplvalues.render" (dict "value" $ingressNSMatchLabels "context" $ ) | nindent 14 }} + {{- $ingressNSPodMatchLabels := coalesce .Values.networkPolicy.ingressNSPodMatchLabels .Values.networkPolicy.podSelector }} + {{- if $ingressNSPodMatchLabels }} + podSelector: + matchLabels: {{- include "common.tplvalues.render" (dict "value" $ingressNSPodMatchLabels "context" $ ) | nindent 14 }} + {{- end }} + {{- end }} + {{- end }} + {{- $extraIngress := coalesce .Values.networkPolicy.extraIngress .Values.networkPolicy.customRules }} + {{- if $extraIngress }} + {{- include "common.tplvalues.render" ( dict "value" $extraIngress "context" $ ) | nindent 4 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/backing-services/mongodb/templates/prometheusrule.yaml b/backing-services/mongodb/templates/prometheusrule.yaml new file mode 100644 index 0000000..e0d0f28 --- /dev/null +++ b/backing-services/mongodb/templates/prometheusrule.yaml @@ -0,0 +1,23 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.prometheusRule.namespace" . }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.metrics.prometheusRule.additionalLabels }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.prometheusRule.additionalLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + groups: + - name: {{ include "mongodb.fullname" . }} + rules: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.prometheusRule.rules "context" $ ) | nindent 8 }} +{{- end }} diff --git a/backing-services/mongodb/templates/psp.yaml b/backing-services/mongodb/templates/psp.yaml new file mode 100644 index 0000000..4b93f4f --- /dev/null +++ b/backing-services/mongodb/templates/psp.yaml @@ -0,0 +1,51 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (include "common.capabilities.psp.supported" .) .Values.podSecurityPolicy.create }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: +{{- if .Values.podSecurityPolicy.spec }} +{{ include "common.tplvalues.render" ( dict "value" .Values.podSecurityPolicy.spec "context" $ ) | nindent 2 }} +{{- else }} + allowPrivilegeEscalation: {{ .Values.podSecurityPolicy.allowPrivilegeEscalation }} + fsGroup: + rule: 'MustRunAs' + ranges: + - min: {{ .Values.podSecurityContext.fsGroup }} + max: {{ .Values.podSecurityContext.fsGroup }} + hostIPC: false + hostNetwork: false + hostPID: false + privileged: {{ .Values.podSecurityPolicy.privileged }} + readOnlyRootFilesystem: false + requiredDropCapabilities: + - ALL + runAsUser: + rule: 'MustRunAs' + ranges: + - min: {{ .Values.containerSecurityContext.runAsUser }} + max: {{ .Values.containerSecurityContext.runAsUser }} + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + - min: {{ .Values.containerSecurityContext.runAsUser }} + max: {{ .Values.containerSecurityContext.runAsUser }} + volumes: + - 'configMap' + - 'secret' + - 'emptyDir' + - 'persistentVolumeClaim' +{{- end }} +{{- end }} diff --git a/backing-services/mongodb/templates/replicaset/external-access-svc.yaml b/backing-services/mongodb/templates/replicaset/external-access-svc.yaml new file mode 100644 index 0000000..400db8e --- /dev/null +++ b/backing-services/mongodb/templates/replicaset/external-access-svc.yaml @@ -0,0 +1,73 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled (not (eq .Values.externalAccess.service.type "ClusterIP")) }} +{{- $fullName := include "mongodb.fullname" . }} +{{- $replicaCount := .Values.replicaCount | int }} +{{- $root := . }} + +{{- range $i, $e := until $replicaCount }} +{{- $targetPod := printf "%s-%d" (printf "%s" $fullName) $i }} +{{- $_ := set $ "targetPod" $targetPod }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-%d-external" $fullName $i }} + namespace: {{ include "mongodb.namespace" $ }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $root.Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + pod: {{ $targetPod }} + {{- if or $root.Values.externalAccess.service.annotations $root.Values.commonAnnotations $root.Values.externalAccess.service.annotationsList }} + {{- $exclusiveAnnotations := dict }} + {{- if gt (len $root.Values.externalAccess.service.annotationsList) $i }} + {{- $exclusiveAnnotations = index $root.Values.externalAccess.service.annotationsList $i }} + {{- end }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list $root.Values.externalAccess.service.annotations $root.Values.commonAnnotations $exclusiveAnnotations ) "context" $ ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ $root.Values.externalAccess.service.type }} + {{- if eq $root.Values.externalAccess.service.type "LoadBalancer" }} + {{- if not (empty $root.Values.externalAccess.service.loadBalancerIPs) }} + loadBalancerIP: {{ index $root.Values.externalAccess.service.loadBalancerIPs $i }} + {{- end }} + {{- if and (eq $root.Values.externalAccess.service.type "LoadBalancer") $root.Values.externalAccess.service.loadBalancerClass }} + loadBalancerClass: {{ $root.Values.externalAccess.service.loadBalancerClass }} + {{- end }} + {{- if $root.Values.externalAccess.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{- toYaml $root.Values.externalAccess.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + allocateLoadBalancerNodePorts: {{ $root.Values.externalAccess.service.allocateLoadBalancerNodePorts }} + {{- end }} + {{- if (or (eq $root.Values.externalAccess.service.type "LoadBalancer") (eq $root.Values.externalAccess.service.type "NodePort")) }} + externalTrafficPolicy: {{ $root.Values.externalAccess.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if $root.Values.externalAccess.service.sessionAffinity }} + sessionAffinity: {{ $root.Values.externalAccess.service.sessionAffinity }} + {{- end }} + {{- if $root.Values.externalAccess.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" $root.Values.externalAccess.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + publishNotReadyAddresses: true + ports: + - name: {{ $root.Values.externalAccess.service.portName | quote }} + port: {{ $root.Values.externalAccess.service.ports.mongodb }} + {{- if not (empty $root.Values.externalAccess.service.nodePorts) }} + {{- $nodePort := index $root.Values.externalAccess.service.nodePorts $i }} + nodePort: {{ $nodePort }} + {{- else }} + nodePort: null + {{- end }} + targetPort: mongodb + {{- if $root.Values.externalAccess.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" $root.Values.externalAccess.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list $root.Values.podLabels $root.Values.commonLabels ) "context" $ ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + statefulset.kubernetes.io/pod-name: {{ $targetPod }} +--- +{{- end }} +{{- end }} diff --git a/backing-services/mongodb/templates/replicaset/headless-svc.yaml b/backing-services/mongodb/templates/replicaset/headless-svc.yaml new file mode 100644 index 0000000..eb6337d --- /dev/null +++ b/backing-services/mongodb/templates/replicaset/headless-svc.yaml @@ -0,0 +1,32 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if eq .Values.architecture "replicaset" }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mongodb.service.nameOverride" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if or .Values.commonAnnotations .Values.service.headless.annotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.service.headless.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + publishNotReadyAddresses: true + ports: + - name: {{ .Values.service.portName | quote }} + port: {{ .Values.service.ports.mongodb }} + targetPort: mongodb + {{- if .Values.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb +{{- end }} diff --git a/backing-services/mongodb/templates/replicaset/pdb.yaml b/backing-services/mongodb/templates/replicaset/pdb.yaml new file mode 100644 index 0000000..a193ed2 --- /dev/null +++ b/backing-services/mongodb/templates/replicaset/pdb.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replicaset") .Values.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.pdb.minAvailable }} + minAvailable: {{ .Values.pdb.minAvailable }} + {{- end }} + {{- if or .Values.pdb.maxUnavailable (not .Values.pdb.minAvailable) }} + maxUnavailable: {{ .Values.pdb.maxUnavailable | default 1 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: mongodb +{{- end }} diff --git a/backing-services/mongodb/templates/replicaset/scripts-configmap.yaml b/backing-services/mongodb/templates/replicaset/scripts-configmap.yaml new file mode 100644 index 0000000..ec70ecb --- /dev/null +++ b/backing-services/mongodb/templates/replicaset/scripts-configmap.yaml @@ -0,0 +1,316 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if eq .Values.architecture "replicaset" }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-scripts" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + {{- $fullname := include "mongodb.fullname" . }} + {{- $releaseNamespace := include "mongodb.namespace" . }} + {{- if and .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.service.type "LoadBalancer") }} + auto-discovery.sh: |- + #!/bin/bash + + SVC_NAME="${MY_POD_NAME}-external" + + # Auxiliary functions + retry_while() { + local -r cmd="${1:?cmd is missing}" + local -r retries="${2:-12}" + local -r sleep_time="${3:-5}" + local return_value=1 + + read -r -a command <<< "$cmd" + for ((i = 1 ; i <= retries ; i+=1 )); do + "${command[@]}" && return_value=0 && break + sleep "$sleep_time" + done + return $return_value + } + k8s_svc_lb_ip() { + local namespace=${1:?namespace is missing} + local service=${2:?service is missing} + local service_ip=$(kubectl get svc "$service" -n "$namespace" -o jsonpath="{.status.loadBalancer.ingress[0].ip}") + local service_hostname=$(kubectl get svc "$service" -n "$namespace" -o jsonpath="{.status.loadBalancer.ingress[0].hostname}") + + if [[ -n ${service_ip} ]]; then + echo "${service_ip}" + else + echo "${service_hostname}" + fi + } + k8s_svc_lb_ip_ready() { + local namespace=${1:?namespace is missing} + local service=${2:?service is missing} + [[ -n "$(k8s_svc_lb_ip "$namespace" "$service")" ]] + } + # Wait until LoadBalancer IP is ready + retry_while "k8s_svc_lb_ip_ready {{ $releaseNamespace }} $SVC_NAME" || exit 1 + # Obtain LoadBalancer external IP + k8s_svc_lb_ip "{{ $releaseNamespace }}" "$SVC_NAME" | tee "$SHARED_FILE" + {{- end }} + setup.sh: |- + #!/bin/bash + + . /opt/bitnami/scripts/mongodb-env.sh + . /opt/bitnami/scripts/libfs.sh + . /opt/bitnami/scripts/liblog.sh + . /opt/bitnami/scripts/libvalidations.sh + + {{- if .Values.externalAccess.enabled }} + {{- if eq .Values.externalAccess.service.type "LoadBalancer" }} + {{- if .Values.externalAccess.autoDiscovery.enabled }} + export MONGODB_ADVERTISED_HOSTNAME="$(<${SHARED_FILE})" + {{- else }} + ID="${MY_POD_NAME#"{{ $fullname }}-"}" + export MONGODB_ADVERTISED_HOSTNAME=$(echo '{{ coalesce .Values.externalAccess.service.publicNames .Values.externalAccess.service.loadBalancerIPs }}' | tr -d '[]' | cut -d ' ' -f "$(($ID + 1))") + {{- end }} + {{- else if eq .Values.externalAccess.service.type "NodePort" }} + ID="${MY_POD_NAME#"{{ $fullname }}-"}" + if is_empty_value "$MONGODB_ADVERTISED_PORT_NUMBER"; then + export MONGODB_ADVERTISED_PORT_NUMBER=$(echo '{{ .Values.externalAccess.service.nodePorts }}' | tr -d '[]' | cut -d ' ' -f "$(($ID + 1))") + fi + {{- if .Values.externalAccess.service.domain }} + export MONGODB_ADVERTISED_HOSTNAME={{ .Values.externalAccess.service.domain }} + {{- else }} + export MONGODB_ADVERTISED_HOSTNAME=$MY_POD_HOST_IP + {{- end }} + {{- end }} + {{- end }} + + {{- if .Values.replicaSetConfigurationSettings.enabled }} + # placed here before root password env is overwritten + # makes no assumption about starting state + # ensures that any stepDown or non-default starting state is handled + /scripts/replicaSetConfigurationSettings.sh & + {{- end }} + + if is_empty_value "$MONGODB_ADVERTISED_PORT_NUMBER"; then + export MONGODB_ADVERTISED_PORT_NUMBER="$MONGODB_PORT_NUMBER" + fi + + info "Advertised Hostname: $MONGODB_ADVERTISED_HOSTNAME" + info "Advertised Port: $MONGODB_ADVERTISED_PORT_NUMBER" + + # Check for existing replica set in case there is no data in the PVC + # This is for cases where the PVC is lost or for MongoDB caches without + # persistence + current_primary="" + if is_dir_empty "${MONGODB_DATA_DIR}/db"; then + info "Data dir empty, checking if the replica set already exists" + {{- $replicaCount := int .Values.replicaCount }} + {{- $portNumber := int .Values.service.ports.mongodb }} + {{- $fullname := include "mongodb.fullname" . }} + {{- $releaseNamespace := include "mongodb.namespace" . }} + {{- $clusterDomain := .Values.clusterDomain }} + {{- $mongoList := list }} + {{- range $e, $i := until $replicaCount }} + {{- $mongoList = append $mongoList (printf "%s-%d.%s-headless.%s.svc.%s:%d" $fullname $i $fullname $releaseNamespace $clusterDomain $portNumber) }} + {{- end }} + + {{- if .Values.externalAccess.externalMaster.enabled }} + current_primary={{ printf "%s:%d" (.Values.externalAccess.externalMaster.host) ( int .Values.externalAccess.externalMaster.port) }} + {{- else }} + current_primary=$(mongosh admin --host "{{ join "," $mongoList }}" {{- if .Values.auth.enabled }} --authenticationDatabase admin -u $MONGODB_ROOT_USER -p $MONGODB_ROOT_PASSWORD{{- end }}{{- if .Values.tls.enabled}} --tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert{{- end }} --eval 'db.runCommand("ismaster")' | awk -F\' '/primary:/ {print $2}') + {{- end }} + if ! is_empty_value "$current_primary"; then + info "Detected existing primary: ${current_primary}" + fi + fi + + if ! is_empty_value "$current_primary" && [[ "$MONGODB_ADVERTISED_HOSTNAME:$MONGODB_ADVERTISED_PORT_NUMBER" == "$current_primary" ]]; then + info "Advertised name matches current primary, configuring node as a primary" + export MONGODB_REPLICA_SET_MODE="primary" + elif ! is_empty_value "$current_primary" && [[ "$MONGODB_ADVERTISED_HOSTNAME:$MONGODB_ADVERTISED_PORT_NUMBER" != "$current_primary" ]]; then + info "Current primary is different from this node. Configuring the node as replica of ${current_primary}" + export MONGODB_REPLICA_SET_MODE="secondary" + export MONGODB_INITIAL_PRIMARY_HOST="${current_primary%:*}" + export MONGODB_INITIAL_PRIMARY_PORT_NUMBER="${current_primary#*:}" + export MONGODB_SET_SECONDARY_OK="yes" + elif [[ "$MY_POD_NAME" = "{{ $fullname }}-0" ]]; then + info "Pod name matches initial primary pod name, configuring node as a primary" + export MONGODB_REPLICA_SET_MODE="primary" + else + info "Pod name doesn't match initial primary pod name, configuring node as a secondary" + export MONGODB_REPLICA_SET_MODE="secondary" + export MONGODB_INITIAL_PRIMARY_PORT_NUMBER="$MONGODB_PORT_NUMBER" + fi + + if [[ "$MONGODB_REPLICA_SET_MODE" == "secondary" ]]; then + export MONGODB_INITIAL_PRIMARY_ROOT_USER="$MONGODB_ROOT_USER" + export MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD="$MONGODB_ROOT_PASSWORD" + export MONGODB_ROOT_PASSWORD="" + export MONGODB_EXTRA_USERNAMES="" + export MONGODB_EXTRA_DATABASES="" + export MONGODB_EXTRA_PASSWORDS="" + export MONGODB_ROOT_PASSWORD_FILE="" + export MONGODB_EXTRA_USERNAMES_FILE="" + export MONGODB_EXTRA_DATABASES_FILE="" + export MONGODB_EXTRA_PASSWORDS_FILE="" + fi + exec /opt/bitnami/scripts/mongodb/entrypoint.sh /opt/bitnami/scripts/mongodb/run.sh + setup-hidden.sh: |- + #!/bin/bash + + . /opt/bitnami/scripts/mongodb-env.sh + + {{- if .Values.externalAccess.hidden.enabled }} + {{- if eq .Values.externalAccess.hidden.service.type "LoadBalancer" }} + {{- if .Values.externalAccess.autoDiscovery.enabled }} + export MONGODB_ADVERTISED_HOSTNAME="$(<${SHARED_FILE})" + {{- else }} + ID="${MY_POD_NAME#"{{ $fullname }}-hidden-"}" + export MONGODB_ADVERTISED_HOSTNAME=$(echo '{{ .Values.externalAccess.hidden.service.loadBalancerIPs }}' | tr -d '[]' | cut -d ' ' -f "$(($ID + 1))") + {{- end }} + {{- else if eq .Values.externalAccess.hidden.service.type "NodePort" }} + ID="${MY_POD_NAME#"{{ $fullname }}-hidden-"}" + if is_empty_value "$MONGODB_ADVERTISED_PORT_NUMBER"; then + export MONGODB_ADVERTISED_PORT_NUMBER=$(echo '{{ .Values.externalAccess.service.nodePorts }}' | tr -d '[]' | cut -d ' ' -f "$(($ID + 1))") + fi + {{- if .Values.externalAccess.hidden.service.domain }} + export MONGODB_ADVERTISED_HOSTNAME={{ .Values.externalAccess.hidden.service.domain }} + {{- else }} + export MONGODB_ADVERTISED_HOSTNAME=$MY_POD_HOST_IP + {{- end }} + {{- end }} + {{- end }} + + {{- if .Values.replicaSetConfigurationSettings.enabled }} + # placed here before root password env is overwritten + # makes no assumption about starting state + # ensures that any stepDown or non-default starting state is handled + /scripts/replicaSetConfigurationSettings.sh & + {{- end }} + + echo "Advertised Hostname: $MONGODB_ADVERTISED_HOSTNAME" + echo "Advertised Port: $MONGODB_ADVERTISED_PORT_NUMBER" + echo "Configuring node as a hidden node" + export MONGODB_REPLICA_SET_MODE="hidden" + export MONGODB_INITIAL_PRIMARY_ROOT_USER="$MONGODB_ROOT_USER" + export MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD="$MONGODB_ROOT_PASSWORD" + export MONGODB_INITIAL_PRIMARY_PORT_NUMBER="$MONGODB_PORT_NUMBER" + export MONGODB_ROOT_PASSWORD="" + export MONGODB_EXTRA_USERNAMES="" + export MONGODB_EXTRA_DATABASES="" + export MONGODB_EXTRA_PASSWORDS="" + export MONGODB_ROOT_PASSWORD_FILE="" + export MONGODB_EXTRA_USERNAMES_FILE="" + export MONGODB_EXTRA_DATABASES_FILE="" + export MONGODB_EXTRA_PASSWORDS_FILE="" + exec /opt/bitnami/scripts/mongodb/entrypoint.sh /opt/bitnami/scripts/mongodb/run.sh + {{- if .Values.replicaSetConfigurationSettings.enabled }} + replicaSetConfigurationSettings.sh: |- + #!/bin/bash + # This script to be called when pod starts. + # This script sets rs settings which can not be applied via conf file + + function logger () + #$1 is the line to be logged + { + echo "replicaSetConfigurationSettings.sh -- ${1}" >&1 + } + + SLEEP_PERIOD=10 + + {{- if and .Values.auth.enabled (or .Values.auth.rootPassword .Values.auth.existingSecret)}} + usernameAndPassword="{{- if .Values.tls.enabled}} --tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert{{- end }} -u ${MONGODB_ROOT_USER} -p ${MONGODB_ROOT_PASSWORD}" + {{- else }} + usernameAndPassword="" + {{- end }} + + # load Values.replicaSetConfigurationSettings.configuration into associtive array which makes iterating and string manipulation easy + declare -A desiredRsConf + {{ range $setting, $value := .Values.replicaSetConfigurationSettings.configuration -}} + {{ printf "desiredRsConf[%s]='%v'" $setting $value }} + {{ end }} + + rsConfWriteAttempts=0 + rs_conf_configured_ok=unknown + + while [[ "${rs_conf_configured_ok}" != "true" ]]; do + + # give the rs setup a chance to succeed before attempting to read or configure + sleep ${SLEEP_PERIOD} + + counter=0 + while ! mongosh ${usernameAndPassword} --eval 'rs.conf()'; do + counter=$((${counter} +1)) + logger "not yet able to read rs.conf settings from the currently running rs (after ${counter} attempts)" + sleep ${SLEEP_PERIOD} + done + counter=$((${counter} +1)) + logger "rs.conf settings have been read from the currently running rs (after ${counter} attempts)" + + # read rs.conf again and store it. settings format is '"" : ,' + currentRsConf=$(mongosh ${usernameAndPassword} --eval 'rs.conf()') + + desiredEqualsactual=unknown + settingsToConfigure="" + for key in ${!desiredRsConf[@]}; do + value=${desiredRsConf[$key]} + if ! $(echo "\"${currentRsConf}"\" | grep -q -e "${key}: ${value},"); then + if [[ $key =~ ^members\[[0-9]+\]\..+ ]]; then + memberIndex=$(echo $key | grep -o -E '[0-9]+') + nodeConfigKey=${key#*.} + settingsToConfigure="${settingsToConfigure}cfg.members[${memberIndex}].${nodeConfigKey} = ${value}; " + else + # General rs settings + settingsToConfigure="${settingsToConfigure}cfg.settings.${key} = ${value}; " + fi + desiredEqualsactual=false + else + logger "rs conf: ${key} is already at desired value: ${value}" + fi + done + + if [[ "${desiredEqualsactual}" != "false" ]]; then + logger "replicaSetConfigurationSettings match the settings of the currently running rs" + desiredEqualsactual=true + rs_conf_configured_ok=true + logger "Current settings match desired settings (There have been ${rsConfWriteAttempts} attempts to write to mongoDB rs configuration)" + exit + fi + + # apply the settings only if this member is currently the mongo replicaset PRIMARY + # it might take a little time before any pod is PRIMARY + isMaster=unknown + if ! mongosh ${usernameAndPassword} --eval 'rs.isMaster()' | grep -q "ismaster: true"; then + isMaster=false + logger "This node is not yet PRIMARY - replicaSetConfigurationSettings will only be set on the member that is currently PRIMARY" + else + isMaster=true + logger "This node is PRIMARY" + fi + + if [[ "${isMaster}" == "true" ]]; then + logger "This node is currently PRIMARY - will apply rs.conf settings" + + # avoiding tricky string substitution with single quotes by making the eval string a set of vars + rsconf="cfg = rs.conf();" + rsreconf="rs.reconfig(cfg);" + rsCommand="${rsconf} ${settingsToConfigure} ${rsreconf}" + + mongosh ${usernameAndPassword} --eval "${rsCommand}" + if [ $? -ne 0 ]; then + logger "Failed to apply mongodb cfg.settings configuration" + else + logger "mongodb replicaset cfg.settings configuration applied" + logger "Will check rs conf" + # don't exit just yet - the settings will be checked in the next loop + fi + rsConfWriteAttempts=$((${rsConfWriteAttempts} + 1 )) + fi + done + {{- end }} +{{- end }} + \ No newline at end of file diff --git a/backing-services/mongodb/templates/replicaset/statefulset.yaml b/backing-services/mongodb/templates/replicaset/statefulset.yaml new file mode 100644 index 0000000..60315f6 --- /dev/null +++ b/backing-services/mongodb/templates/replicaset/statefulset.yaml @@ -0,0 +1,562 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if eq .Values.architecture "replicaset" }} +{{- $replicaCount := int .Values.replicaCount }} +{{- $loadBalancerIPListLength := len .Values.externalAccess.service.loadBalancerIPs }} +{{- $publicNamesLength := len .Values.externalAccess.service.publicNames }} +{{- if not (and .Values.externalAccess.enabled (not .Values.externalAccess.autoDiscovery.enabled) (eq .Values.externalAccess.service.type "LoadBalancer") (not (eq $replicaCount $loadBalancerIPListLength)) (not (eq $replicaCount $publicNamesLength))) }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if or .Values.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + serviceName: {{ include "mongodb.service.nameOverride" . }} + podManagementPolicy: {{ .Values.podManagementPolicy }} + replicas: {{ .Values.replicaCount }} + {{- if .Values.updateStrategy }} + updateStrategy: {{- toYaml .Values.updateStrategy | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: mongodb + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: mongodb + {{- if or (include "mongodb.createConfigmap" .) .Values.podAnnotations }} + annotations: + {{- if (include "mongodb.createConfigmap" .) }} + checksum/configuration: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.podAnnotations "context" $) | nindent 8 }} + {{- end }} + {{- end }} + spec: + {{- include "mongodb.imagePullSecrets" . | nindent 6 }} + {{- if .Values.schedulerName }} + schedulerName: {{ .Values.schedulerName | quote }} + {{- end }} + serviceAccountName: {{ template "mongodb.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.automountServiceAccountToken }} + {{- if .Values.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAffinityPreset "component" "mongodb" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAntiAffinityPreset "component" "mongodb" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.nodeAffinityPreset.type "key" .Values.nodeAffinityPreset.key "values" .Values.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.topologySpreadConstraints "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + {{- if .Values.runtimeClassName }} + runtimeClassName: {{ .Values.runtimeClassName }} + {{- end }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + {{ if .Values.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} + {{- end }} + enableServiceLinks: {{ .Values.enableServiceLinks }} + initContainers: + {{- if .Values.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }} + {{- include "mongodb.initContainer.volumePermissions" . | nindent 8 }} + {{- end }} + {{- if and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.service.type "LoadBalancer") }} + {{- include "mongodb.initContainers.autoDiscovery" . | nindent 8 }} + {{- end }} + {{- if and .Values.externalAccess.enabled ( or .Values.externalAccess.service.publicNames .Values.externalAccess.service.domain ) }} + {{- include "mongodb.initContainers.dnsCheck" . | nindent 8 }} + {{- end }} + {{- include "mongodb.initContainer.prepareLogDir" . | nindent 8 }} + {{- if .Values.tls.enabled }} + - name: generate-tls-certs + image: {{ include "mongodb.tls.image" . }} + imagePullPolicy: {{ .Values.tls.image.pullPolicy | quote }} + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + volumeMounts: + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + mountPath: /certs/CAs + {{- else }} + {{- range $index, $_ := .Values.tls.replicaset.existingSecrets }} + - name: mongodb-certs-{{ $index }} + mountPath: /certs-{{ $index }} + {{- end }} + {{- end }} + - name: certs + mountPath: /certs + - name: common-scripts + mountPath: /bitnami/scripts + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + command: + - /bitnami/scripts/generate-certs.sh + args: + - -s {{ include "mongodb.service.nameOverride" . }} + {{- if .Values.externalAccess.service.loadBalancerIPs }} + - -i {{ join "," .Values.externalAccess.service.loadBalancerIPs }} + {{- end }} + {{- if or .Values.tls.extraDnsNames .Values.externalAccess.service.publicNames }} + - -n {{ join "," ( concat .Values.tls.extraDnsNames .Values.externalAccess.service.publicNames ) }} + {{- end }} + {{- if .Values.tls.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.tls.resources "context" $) | nindent 12 }} + {{- else if ne .Values.tls.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.tls.resourcesPreset) | nindent 12 }} + {{- end }} + {{- if .Values.tls.securityContext }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.tls.securityContext "context" $) | nindent 12 }} + {{- end }} + {{- end }} + containers: + - name: mongodb + image: {{ include "mongodb.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.command "context" $) | nindent 12 }} + {{- else }} + command: + - /scripts/setup.sh + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.args "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + {{- if and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.service.type "LoadBalancer") }} + - name: SHARED_FILE + value: "/shared/info.txt" + {{- end }} + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: MONGODB_INITIAL_PRIMARY_HOST + value: {{ include "mongodb.initialPrimaryHost" . | quote }} + - name: MONGODB_REPLICA_SET_NAME + value: {{ .Values.replicaSetName | quote }} + {{- if and .Values.replicaSetHostnames (not .Values.externalAccess.enabled) }} + - name: MONGODB_ADVERTISED_HOSTNAME + value: "$(MY_POD_NAME).{{ include "mongodb.service.nameOverride" . }}.$(MY_POD_NAMESPACE).svc.{{ .Values.clusterDomain }}" + {{- end }} + {{- $customUsers := include "mongodb.customUsers" . -}} + {{- $customDatabases := include "mongodb.customDatabases" . -}} + {{- if not (empty $customUsers) }} + - name: MONGODB_EXTRA_USERNAMES + value: {{ $customUsers | quote }} + {{- end }} + {{- if not (empty $customDatabases) }} + - name: MONGODB_EXTRA_DATABASES + value: {{ $customDatabases | quote }} + {{- end }} + {{- if .Values.auth.enabled }} + {{- if and (not (empty $customUsers)) (not (empty $customDatabases)) }} + - name: MONGODB_EXTRA_PASSWORDS + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-passwords + {{- end }} + - name: MONGODB_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + - name: MONGODB_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + - name: MONGODB_REPLICA_SET_KEY + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-replica-set-key + {{- end }} + {{- if and .Values.metrics.enabled (not (empty .Values.metrics.username)) }} + - name: MONGODB_METRICS_USERNAME + value: {{ .Values.metrics.username | quote }} + {{- if .Values.auth.enabled }} + - name: MONGODB_METRICS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-metrics-password + {{- end }} + {{- end }} + - name: ALLOW_EMPTY_PASSWORD + value: {{ ternary "no" "yes" .Values.auth.enabled | quote }} + - name: MONGODB_SYSTEM_LOG_VERBOSITY + value: {{ .Values.systemLogVerbosity | quote }} + - name: MONGODB_DISABLE_SYSTEM_LOG + value: {{ ternary "yes" "no" .Values.disableSystemLog | quote }} + - name: MONGODB_DISABLE_JAVASCRIPT + value: {{ ternary "yes" "no" .Values.disableJavascript | quote }} + - name: MONGODB_ENABLE_JOURNAL + value: {{ ternary "yes" "no" .Values.enableJournal | quote }} + - name: MONGODB_PORT_NUMBER + value: {{ .Values.containerPorts.mongodb | quote }} + - name: MONGODB_ENABLE_IPV6 + value: {{ ternary "yes" "no" .Values.enableIPv6 | quote }} + - name: MONGODB_ENABLE_DIRECTORY_PER_DB + value: {{ ternary "yes" "no" .Values.directoryPerDB | quote }} + {{- $extraFlags := .Values.extraFlags | join " " -}} + {{- if .Values.tls.enabled }} + {{- if .Values.tls.mTLS.enabled }} + {{- $extraFlags = printf "--tlsCAFile=/certs/mongodb-ca-cert %s" $extraFlags }} + {{- end }} + {{- $extraFlags = printf "--tlsMode=%s --tlsCertificateKeyFile=/certs/mongodb.pem %s" .Values.tls.mode $extraFlags }} + {{- end }} + {{- if ne $extraFlags "" }} + - name: MONGODB_EXTRA_FLAGS + value: {{ $extraFlags | quote }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: MONGODB_CLIENT_EXTRA_FLAGS + value: --tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert + {{- end }} + {{- if .Values.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.extraEnvVarsCM .Values.extraEnvVarsSecret }} + envFrom: + {{- if .Values.extraEnvVarsCM }} + - configMapRef: + name: {{ tpl .Values.extraEnvVarsCM . | quote }} + {{- end }} + {{- if .Values.extraEnvVarsSecret }} + - secretRef: + name: {{ tpl .Values.extraEnvVarsSecret . | quote }} + {{- end }} + {{- end }} + ports: + - name: mongodb + containerPort: {{ .Values.containerPorts.mongodb }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/ping-mongodb.sh + {{- end }} + {{- if .Values.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/readiness-probe.sh + {{- end }} + {{- if .Values.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/startup-probe.sh + {{- end }} + {{- end }} + {{- if .Values.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.resources "context" $) | nindent 12 }} + {{- else if ne .Values.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/conf + subPath: app-conf-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/tmp + subPath: app-tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/logs + subPath: app-logs-dir + - name: empty-dir + mountPath: /.mongodb + subPath: mongosh-home + - name: {{ .Values.persistence.name | default "datadir" }} + mountPath: {{ .Values.persistence.mountPath }} + subPath: {{ .Values.persistence.subPath }} + - name: common-scripts + mountPath: /bitnami/scripts + {{- if or .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + mountPath: /docker-entrypoint-initdb.d + {{- end }} + {{- if or .Values.configuration .Values.existingConfigmap }} + - name: config + mountPath: /opt/bitnami/mongodb/conf/mongodb.conf + subPath: mongodb.conf + {{- end }} + - name: scripts + mountPath: /scripts/setup.sh + subPath: setup.sh + {{ if .Values.replicaSetConfigurationSettings.enabled }} + - name: scripts + mountPath: /scripts/replicaSetConfigurationSettings.sh + subPath: replicaSetConfigurationSettings.sh + {{- end }} + {{- if and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.service.type "LoadBalancer") }} + - name: shared + mountPath: /shared + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + mountPath: /certs + {{- end }} + {{- if .Values.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ template "mongodb.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.metrics.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -ec + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.metrics.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.args "context" $) | nindent 12 }} + {{- else }} + args: + - | + /bin/mongodb_exporter {{ include "mongodb.exporterArgs" $ }} --mongodb.direct-connect --mongodb.global-conn-pool --web.listen-address ":{{ .Values.metrics.containerPort }}" --mongodb.uri "{{ include "mongodb.mongodb_exporter.uri" . }}" {{ .Values.metrics.extraFlags }} + {{- end }} + env: + {{- if .Values.auth.enabled }} + {{- if not .Values.metrics.username }} + - name: MONGODB_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + - name: MONGODB_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + {{- else }} + - name: MONGODB_METRICS_USERNAME + value: {{ .Values.metrics.username | quote }} + - name: MONGODB_METRICS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-metrics-password + {{- end }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if .Values.tls.enabled }} + - name: certs + mountPath: /certs + {{- end }} + {{- if .Values.metrics.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + ports: + - name: metrics + containerPort: {{ .Values.metrics.containerPort }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.resources "context" $) | nindent 12 }} + {{- else if ne .Values.metrics.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.metrics.resourcesPreset) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: empty-dir + emptyDir: {} + - name: common-scripts + configMap: + name: {{ printf "%s-common-scripts" (include "mongodb.fullname" .) }} + defaultMode: 0550 + {{- if or .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + configMap: + name: {{ template "mongodb.initdbScriptsCM" . }} + {{- end }} + {{- if or .Values.configuration .Values.existingConfigmap }} + - name: config + configMap: + name: {{ include "mongodb.configmapName" . }} + {{- end }} + {{- if and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.service.type "LoadBalancer") }} + - name: shared + emptyDir: {} + {{- end }} + - name: scripts + configMap: + name: {{ printf "%s-scripts" (include "mongodb.fullname" .) }} + defaultMode: 0755 + {{- if .Values.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraVolumes "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + emptyDir: {} + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + secret: + secretName: {{ template "mongodb.tlsSecretName" . }} + items: + - key: mongodb-ca-cert + path: mongodb-ca-cert + mode: 0600 + - key: mongodb-ca-key + path: mongodb-ca-key + mode: 0600 + {{- else }} + {{- range $index, $secret := .Values.tls.replicaset.existingSecrets }} + - name: mongodb-certs-{{ $index }} + secret: + secretName: {{ include "common.tplvalues.render" ( dict "value" $secret "context" $) }} + defaultMode: 256 + {{- end }} + {{- end }} + {{- end }} + {{- if not .Values.persistence.enabled }} + - name: datadir + {{- if .Values.persistence.medium }} + emptyDir: + medium: {{ .Values.persistence.medium | quote }} + {{- else }} + emptyDir: {} + {{- end }} + {{- else }} + {{- if .Values.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: datadir + {{- if .Values.persistence.annotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.annotations "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.persistence.labels }} + labels: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.labels "context" $) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- if .Values.persistence.volumeClaimTemplates.requests }} + {{- include "common.tplvalues.render" (dict "value" .Values.persistence.volumeClaimTemplates.requests "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.persistence.volumeClaimTemplates.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.volumeClaimTemplates.dataSource "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.persistence.volumeClaimTemplates.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.volumeClaimTemplates.selector "context" $) | nindent 10 }} + {{- end }} + {{ include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) }} + {{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/mongodb/templates/replicaset/svc.yaml b/backing-services/mongodb/templates/replicaset/svc.yaml new file mode 100644 index 0000000..20b347f --- /dev/null +++ b/backing-services/mongodb/templates/replicaset/svc.yaml @@ -0,0 +1,41 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled (eq .Values.externalAccess.service.type "ClusterIP") }} + +{{- $fullName := include "mongodb.fullname" . }} +{{- $replicaCount := .Values.replicaCount | int }} +{{- $root := . }} + +{{- range $i, $e := until $replicaCount }} +{{- $targetPod := printf "%s-%d" (printf "%s" $fullName) $i }} +{{- $_ := set $ "targetPod" $targetPod }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-%d" $fullName $i }} + namespace: {{ include "mongodb.namespace" $ }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $root.Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if or $root.Values.service.annotations $root.Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list $root.Values.service.annotations $root.Values.commonAnnotations ) "context" $ ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + ports: + - name: {{ $root.Values.service.portName | quote }} + port: {{ $root.Values.service.ports.mongodb }} + targetPort: mongodb + {{- if $root.Values.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" $root.Values.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list $root.Values.podLabels $root.Values.commonLabels ) "context" $ ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + statefulset.kubernetes.io/pod-name: {{ $targetPod }} +--- +{{- end }} +{{- end }} diff --git a/backing-services/mongodb/templates/role.yaml b/backing-services/mongodb/templates/role.yaml new file mode 100644 index 0000000..062e8f3 --- /dev/null +++ b/backing-services/mongodb/templates/role.yaml @@ -0,0 +1,31 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.rbac.create }} +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: Role +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} +rules: + - apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch +{{- if .Values.rbac.rules }} +{{- include "common.tplvalues.render" ( dict "value" .Values.rbac.rules "context" $ ) | nindent 2 }} +{{- end -}} +{{- if and (include "common.capabilities.psp.supported" .) .Values.podSecurityPolicy.create }} + - apiGroups: ['{{ template "podSecurityPolicy.apiGroup" . }}'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: [{{ include "mongodb.fullname" . }}] +{{- end -}} +{{- end }} diff --git a/backing-services/mongodb/templates/rolebinding.yaml b/backing-services/mongodb/templates/rolebinding.yaml new file mode 100644 index 0000000..7ff6b18 --- /dev/null +++ b/backing-services/mongodb/templates/rolebinding.yaml @@ -0,0 +1,21 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.serviceAccount.create .Values.rbac.create }} +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: RoleBinding +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} +roleRef: + kind: Role + name: {{ include "mongodb.fullname" . }} + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + name: {{ include "mongodb.serviceAccountName" . }} + namespace: {{ include "mongodb.namespace" . | quote }} +{{- end }} diff --git a/backing-services/mongodb/templates/secrets-ca.yaml b/backing-services/mongodb/templates/secrets-ca.yaml new file mode 100644 index 0000000..932b0e6 --- /dev/null +++ b/backing-services/mongodb/templates/secrets-ca.yaml @@ -0,0 +1,33 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.createTlsSecret" .) }} +{{- $secretName := printf "%s" (include "mongodb.tlsSecretName" .) }} +{{- $fullname := include "mongodb.fullname" . }} +{{- $releaseNamespace := .Release.Namespace }} +{{- $clusterDomain := .Values.clusterDomain }} +{{- $cn := printf "%s.%s.svc.%s" $fullname .Release.Namespace $clusterDomain }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ template "mongodb.namespace" . }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + {{- if or .Values.tls.caCert .Values.tls.caKey (not .Values.tls.autoGenerated) }} + {{- $ca := buildCustomCert (required "A valid .Values.tls.caCert is required!" .Values.tls.caCert) (required "A valid .Values.tls.caKey is required!" .Values.tls.caKey) }} + mongodb-ca-cert: {{ b64enc $ca.Cert }} + mongodb-ca-key: {{ b64enc $ca.Key }} + {{- else }} + {{- $ca := genCA "myMongo-ca" 3650 }} + mongodb-ca-cert: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "mongodb-ca-cert" "defaultValue" $ca.Cert "context" $) }} + mongodb-ca-key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "mongodb-ca-key" "defaultValue" $ca.Key "context" $) }} + {{- end }} +{{- end }} diff --git a/backing-services/mongodb/templates/secrets.yaml b/backing-services/mongodb/templates/secrets.yaml new file mode 100644 index 0000000..4ff27c1 --- /dev/null +++ b/backing-services/mongodb/templates/secrets.yaml @@ -0,0 +1,128 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.auth.enabled }} +{{- $replicaCount := int .Values.replicaCount }} +{{- $port := .Values.service.ports.mongodb }} +{{- $host := include "mongodb.service.nameOverride" . }} +{{- $hostForURI := printf "%s:%s" (include "mongodb.service.nameOverride" .) (print $port) }} +{{- if (eq .Values.architecture "replicaset") }} + {{- $fullname := include "mongodb.fullname" . }} + {{- $releaseNamespace := include "mongodb.namespace" . }} + {{- $clusterDomain := .Values.clusterDomain }} + {{- $mongoList := list }} + {{- $mongoOnlyHostList := list }} + {{- range $e, $i := until $replicaCount }} + {{- $mongoOnlyHostList = append $mongoList (printf "%s-%d.%s-headless.%s.svc.%s" $fullname $i $fullname $releaseNamespace $clusterDomain) }} + {{- $mongoList = append $mongoList (printf "%s-%d.%s-headless.%s.svc.%s:%s" $fullname $i $fullname $releaseNamespace $clusterDomain (print $port)) }} + {{- end }} + {{- $host = (join "," $mongoOnlyHostList) }} + {{- $hostForURI = (join "," $mongoList) }} +{{- end }} + +{{/* Root user section. */}} +{{- $rootPassword := include "common.secrets.passwords.manage" (dict "secret" (include "mongodb.secretName" .) "key" "mongodb-root-password" "providedValues" (list "auth.rootPassword" ) "context" $) | trimAll "\"" | b64dec }} + +{{/* Custom user section. This chart allows creating multiple users */}} +{{- $customUsers := include "mongodb.customUsers" . }} +{{- $customDatabases := include "mongodb.customDatabases" . }} +{{- $customPasswords := include "mongodb.customPasswords" . }} +{{- $passwords := "" }} +{{- $passwordList := list -}} +{{- $customUsersList := list }} +{{- $customDatabasesList := list }} +{{- $customPasswordsList := list }} +{{- if and (not (empty $customUsers)) (not (empty $customDatabases)) }} +{{- $customUsersList = splitList "," $customUsers }} +{{- $customDatabasesList = splitList "," $customDatabases }} +{{- if not (empty $customPasswords) }} +{{- $passwordList = $customPasswords }} +{{- $customPasswordsList = splitList "," $customPasswords }} +{{- else }} +{{- range $customUsersList }} +{{- $customPasswordsList = append $customPasswordsList (randAlphaNum 10) }} +{{- end -}} +{{- $passwordList = (join "," $customPasswordsList) }} +{{- end }} +{{- $passwords = include "common.secrets.passwords.manage" (dict "secret" (include "mongodb.secretName" .) "key" "mongodb-passwords" "providedValues" (list "mongodbPasswords") "context" (set (deepCopy $) "Values" (dict "mongodbPasswords" $passwordList))) | trimAll "\"" | b64dec }} +{{- end }} + +{{- if (include "mongodb.createSecret" .) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ template "mongodb.namespace" . }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + mongodb-root-password: {{ print $rootPassword | b64enc | quote }} + {{- if and (not (empty $customUsers)) (not (empty $customDatabases)) }} + mongodb-passwords: {{ print $passwords | b64enc | quote }} + {{- end }} + {{- if .Values.metrics.username }} + mongodb-metrics-password: {{ include "common.secrets.passwords.manage" (dict "secret" (include "mongodb.fullname" .) "key" "mongodb-metrics-password" "providedValues" (list "metrics.password" ) "context" $) }} + {{- end }} + {{- if eq .Values.architecture "replicaset" }} + mongodb-replica-set-key: {{ include "common.secrets.passwords.manage" (dict "secret" (include "mongodb.fullname" .) "key" "mongodb-replica-set-key" "providedValues" (list "auth.replicaSetKey" ) "context" $) }} + {{- end }} +{{- end }} +{{- if .Values.serviceBindings.enabled }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }}-svcbind-root + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: servicebinding.io/mongodb +data: + provider: {{ print "bitnami" | b64enc | quote }} + type: {{ print "mongodb" | b64enc | quote }} + host: {{ print $host | b64enc | quote }} + port: {{ print $port | b64enc | quote }} + username: {{ print .Values.auth.rootUser | b64enc | quote }} + password: {{ print $rootPassword | b64enc | quote }} + database: {{ print "admin" | b64enc | quote }} + uri: {{ printf "mongodb://%s:%s@%s/admin" .Values.auth.rootUser $rootPassword $hostForURI | b64enc | quote }} +{{- range $e, $i := until (len $customUsersList) }} +--- +{{- $currentSecret := printf "%s-svcbind-%d" (include "common.names.fullname" $) $i }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $currentSecret }} + namespace: {{ $.Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $.Values.commonLabels "context" $ ) | nindent 4 }} + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: servicebinding.io/mongodb +data: + {{- $currentUser := index $customUsersList $i }} + {{- $currentDatabase := last $customDatabasesList }} + {{- if gt (len $customDatabasesList) $i }} + {{- $currentDatabase = index $customDatabasesList $i }} + {{- end }} + {{- $currentProvidedPassword := index $customPasswordsList $i }} + {{- $currentPassword := include "common.secrets.lookup" (dict "secret" $currentSecret "key" "password" "defaultValue" $currentProvidedPassword "context" $) | b64dec }} + provider: {{ print "bitnami" | b64enc | quote }} + type: {{ print "mongodb" | b64enc | quote }} + host: {{ print $host | b64enc | quote }} + port: {{ print $port | b64enc | quote }} + username: {{ print $currentUser | b64enc | quote }} + password: {{ print $currentPassword | b64enc | quote }} + database: {{ print $currentDatabase | b64enc | quote }} + uri: {{ printf "mongodb://%s:%s@%s/%s" $currentUser $currentPassword $hostForURI $currentDatabase | b64enc | quote }} +{{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/mongodb/templates/serviceaccount.yaml b/backing-services/mongodb/templates/serviceaccount.yaml new file mode 100644 index 0000000..b54e8a0 --- /dev/null +++ b/backing-services/mongodb/templates/serviceaccount.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "mongodb.serviceAccountName" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +secrets: + - name: {{ include "mongodb.secretName" . }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/backing-services/mongodb/templates/servicemonitor.yaml b/backing-services/mongodb/templates/servicemonitor.yaml new file mode 100644 index 0000000..7849d46 --- /dev/null +++ b/backing-services/mongodb/templates/servicemonitor.yaml @@ -0,0 +1,48 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.serviceMonitor.namespace" . }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.serviceMonitor.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: metrics + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.metrics.serviceMonitor.jobLabel }} + jobLabel: {{ .Values.metrics.serviceMonitor.jobLabel }} + {{- end }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + {{- if .Values.metrics.serviceMonitor.selector }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.serviceMonitor.selector "context" $) | nindent 6 }} + {{- end }} + app.kubernetes.io/component: metrics + 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 }} + {{- if .Values.metrics.serviceMonitor.relabelings }} + relabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.relabelings "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.metricRelabelings "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.honorLabels }} + honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }} + {{- end }} + namespaceSelector: + matchNames: + - "{{ include "mongodb.namespace" . }}" +{{- end }} diff --git a/backing-services/mongodb/templates/standalone/dep-sts.yaml b/backing-services/mongodb/templates/standalone/dep-sts.yaml new file mode 100644 index 0000000..fdf55f2 --- /dev/null +++ b/backing-services/mongodb/templates/standalone/dep-sts.yaml @@ -0,0 +1,498 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if not (eq .Values.architecture "replicaset") }} +apiVersion: {{ if .Values.useStatefulSet }}{{ include "common.capabilities.statefulset.apiVersion" . }}{{- else }}{{ include "common.capabilities.deployment.apiVersion" . }}{{- end }} +kind: {{ if .Values.useStatefulSet }}StatefulSet{{- else }}Deployment{{- end }} +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if or .Values.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + replicas: {{ gt (.Values.replicaCount | int) 1 | ternary 1 .Values.replicaCount }} + {{- if .Values.useStatefulSet }} + serviceName: {{ include "mongodb.service.nameOverride" . }} + {{- end }} + {{- if .Values.updateStrategy}} + {{- if .Values.useStatefulSet }} + updateStrategy: + {{- else }} + strategy: + {{- end }} + {{- toYaml .Values.updateStrategy | nindent 4 }} + {{- end}} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: mongodb + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: mongodb + {{- if or (include "mongodb.createConfigmap" .) .Values.podAnnotations }} + annotations: + {{- if (include "mongodb.createConfigmap" .) }} + checksum/configuration: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.podAnnotations "context" $) | nindent 8 }} + {{- end }} + {{- end }} + spec: + {{- include "mongodb.imagePullSecrets" . | nindent 6 }} + automountServiceAccountToken: {{ .Values.automountServiceAccountToken }} + {{- if .Values.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.schedulerName }} + schedulerName: {{ .Values.schedulerName | quote }} + {{- end }} + serviceAccountName: {{ template "mongodb.serviceAccountName" . }} + {{- if .Values.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAffinityPreset "component" "mongodb" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAntiAffinityPreset "component" "mongodb" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.nodeAffinityPreset.type "key" .Values.nodeAffinityPreset.key "values" .Values.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + {{- if .Values.runtimeClassName }} + runtimeClassName: {{ .Values.runtimeClassName }} + {{- end }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + {{ if .Values.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} + {{- end }} + enableServiceLinks: {{ .Values.enableServiceLinks }} + initContainers: + {{- if .Values.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }} + {{- include "mongodb.initContainer.volumePermissions" . | indent 8 }} + {{- end }} + {{- include "mongodb.initContainer.prepareLogDir" . | nindent 8 }} + {{- if .Values.tls.enabled }} + - name: generate-tls-certs + image: {{ include "mongodb.tls.image" . }} + imagePullPolicy: {{ .Values.tls.image.pullPolicy | quote }} + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + mountPath: /certs/CAs + {{- else }} + - name: mongodb-certs-0 + mountPath: /certs-0 + {{- end }} + - name: certs + mountPath: /certs + - name: common-scripts + mountPath: /bitnami/scripts + command: + - /bitnami/scripts/generate-certs.sh + args: + - -s {{ include "mongodb.service.nameOverride" . }} + {{- if .Values.externalAccess.service.loadBalancerIPs }} + - -i {{ join "," .Values.externalAccess.service.loadBalancerIPs }} + {{- end }} + {{- if or .Values.tls.extraDnsNames .Values.externalAccess.service.publicNames }} + - -n {{ join "," ( concat .Values.tls.extraDnsNames .Values.externalAccess.service.publicNames ) }} + {{- end }} + {{- if .Values.tls.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.tls.resources "context" $) | nindent 12 }} + {{- else if ne .Values.tls.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.tls.resourcesPreset) | nindent 12 }} + {{- end }} + {{- if .Values.tls.securityContext }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.tls.securityContext "context" $) | nindent 12 }} + {{- end }} + {{- end }} + containers: + - name: mongodb + image: {{ include "mongodb.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.args "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + {{- $customUsers := include "mongodb.customUsers" . -}} + {{- $customDatabases := include "mongodb.customDatabases" . -}} + {{- if not (empty $customUsers) }} + - name: MONGODB_EXTRA_USERNAMES + value: {{ $customUsers | quote }} + {{- end }} + {{- if not (empty $customDatabases) }} + - name: MONGODB_EXTRA_DATABASES + value: {{ $customDatabases | quote }} + {{- end }} + {{- if .Values.auth.enabled }} + {{- if and (not (empty $customUsers)) (not (empty $customDatabases)) }} + - name: MONGODB_EXTRA_PASSWORDS + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-passwords + {{- end }} + - name: MONGODB_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + - name: MONGODB_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + {{- end }} + {{- if and .Values.metrics.enabled (not (empty .Values.metrics.username)) }} + - name: MONGODB_METRICS_USERNAME + value: {{ .Values.metrics.username | quote }} + {{- if .Values.auth.enabled }} + - name: MONGODB_METRICS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-metrics-password + {{- end }} + {{- end }} + - name: ALLOW_EMPTY_PASSWORD + value: {{ ternary "no" "yes" .Values.auth.enabled | quote }} + - name: MONGODB_SYSTEM_LOG_VERBOSITY + value: {{ .Values.systemLogVerbosity | quote }} + - name: MONGODB_DISABLE_SYSTEM_LOG + value: {{ ternary "yes" "no" .Values.disableSystemLog | quote }} + - name: MONGODB_DISABLE_JAVASCRIPT + value: {{ ternary "yes" "no" .Values.disableJavascript | quote }} + - name: MONGODB_ENABLE_JOURNAL + value: {{ ternary "yes" "no" .Values.enableJournal | quote }} + - name: MONGODB_PORT_NUMBER + value: {{ .Values.containerPorts.mongodb | quote }} + - name: MONGODB_ENABLE_IPV6 + value: {{ ternary "yes" "no" .Values.enableIPv6 | quote }} + - name: MONGODB_ENABLE_DIRECTORY_PER_DB + value: {{ ternary "yes" "no" .Values.directoryPerDB | quote }} + {{- $extraFlags := .Values.extraFlags | join " " -}} + {{- if .Values.tls.enabled }} + {{- if .Values.tls.mTLS.enabled }} + {{- $extraFlags = printf "--tlsCAFile=/certs/mongodb-ca-cert %s" $extraFlags }} + {{- end }} + {{- $extraFlags = printf "--tlsMode=%s --tlsCertificateKeyFile=/certs/mongodb.pem %s" .Values.tls.mode $extraFlags }} + {{- end }} + {{- if ne $extraFlags "" }} + - name: MONGODB_EXTRA_FLAGS + value: {{ $extraFlags | quote }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: MONGODB_CLIENT_EXTRA_FLAGS + value: --tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert + {{- end }} + {{- if .Values.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.extraEnvVarsCM .Values.extraEnvVarsSecret }} + envFrom: + {{- if .Values.extraEnvVarsCM }} + - configMapRef: + name: {{ tpl .Values.extraEnvVarsCM . | quote }} + {{- end }} + {{- if .Values.extraEnvVarsSecret }} + - secretRef: + name: {{ tpl .Values.extraEnvVarsSecret . | quote }} + {{- end }} + {{- end }} + ports: + - name: mongodb + containerPort: {{ .Values.containerPorts.mongodb }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/ping-mongodb.sh + {{- end }} + {{- end }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/readiness-probe.sh + {{- end }} + {{- end }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/startup-probe.sh + {{- end }} + {{- end }} + {{- if .Values.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.resources "context" $) | nindent 12 }} + {{- else if ne .Values.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/conf + subPath: app-conf-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/tmp + subPath: app-tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/logs + subPath: app-logs-dir + - name: empty-dir + mountPath: /.mongodb + subPath: mongosh-home + - name: {{ .Values.persistence.name | default "datadir" }} + mountPath: {{ .Values.persistence.mountPath }} + subPath: {{ .Values.persistence.subPath }} + - name: common-scripts + mountPath: /bitnami/scripts + {{- if or .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + mountPath: /docker-entrypoint-initdb.d + {{- end }} + {{- if or .Values.configuration .Values.existingConfigmap }} + - name: config + mountPath: /opt/bitnami/mongodb/conf/mongodb.conf + subPath: mongodb.conf + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + mountPath: /certs + {{- end }} + {{- if .Values.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ template "mongodb.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.metrics.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -ec + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.metrics.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.args "context" $) | nindent 12 }} + {{- else }} + args: + - | + /bin/mongodb_exporter {{ include "mongodb.exporterArgs" $ }} --mongodb.direct-connect --mongodb.global-conn-pool --web.listen-address ":{{ .Values.metrics.containerPort }}" --mongodb.uri "{{ include "mongodb.mongodb_exporter.uri" . }}" {{ .Values.metrics.extraFlags }} + {{- end }} + env: + {{- if .Values.auth.enabled }} + {{- if not .Values.metrics.username }} + - name: MONGODB_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + - name: MONGODB_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + {{- else }} + - name: MONGODB_METRICS_USERNAME + value: {{ .Values.metrics.username | quote }} + - name: MONGODB_METRICS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-metrics-password + {{- end }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if .Values.tls.enabled }} + - name: certs + mountPath: /certs + {{- end }} + {{- if .Values.metrics.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + ports: + - name: metrics + containerPort: {{ .Values.metrics.containerPort }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.resources "context" $) | nindent 12 }} + {{- else if ne .Values.metrics.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.metrics.resourcesPreset) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: empty-dir + emptyDir: {} + - name: common-scripts + configMap: + name: {{ printf "%s-common-scripts" (include "mongodb.fullname" .) }} + defaultMode: 0550 + {{- if or .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + configMap: + name: {{ template "mongodb.initdbScriptsCM" . }} + {{- end }} + {{- if or .Values.configuration .Values.existingConfigmap }} + - name: config + configMap: + name: {{ include "mongodb.configmapName" . }} + {{- end }} + {{- if .Values.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraVolumes "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + emptyDir: {} + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + secret: + secretName: {{ template "mongodb.tlsSecretName" . }} + items: + - key: mongodb-ca-cert + path: mongodb-ca-cert + mode: 0600 + - key: mongodb-ca-key + path: mongodb-ca-key + mode: 0600 + {{- else }} + - name: mongodb-certs-0 + secret: + secretName: {{ include "common.tplvalues.render" ( dict "value" .Values.tls.standalone.existingSecret "context" $) }} + defaultMode: 256 + {{- end }} + {{- end }} + {{- if not .Values.persistence.enabled }} + - name: {{ .Values.persistence.name | default "datadir" }} + {{- if .Values.persistence.medium }} + emptyDir: + medium: {{ .Values.persistence.medium | quote }} + {{- else }} + emptyDir: {} + {{- end }} + {{- else if .Values.persistence.existingClaim }} + - name: {{ .Values.persistence.name | default "datadir" }} + persistentVolumeClaim: + claimName: {{ printf "%s" (tpl .Values.persistence.existingClaim .) }} + {{- else if not .Values.useStatefulSet }} + - name: {{ .Values.persistence.name | default "datadir" }} + persistentVolumeClaim: + claimName: {{ template "mongodb.fullname" . }} + {{- else }} + {{- if .Values.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + volumeClaimTemplates: + - metadata: + name: {{ .Values.persistence.name | default "datadir" }} + {{- if .Values.persistence.annotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.annotations "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.persistence.labels }} + labels: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.labels "context" $) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- if .Values.persistence.volumeClaimTemplates.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.volumeClaimTemplates.selector "context" $) | nindent 10 }} + {{- end }} + {{ include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) }} + {{- end }} +{{- end }} diff --git a/backing-services/mongodb/templates/standalone/pdb.yaml b/backing-services/mongodb/templates/standalone/pdb.yaml new file mode 100644 index 0000000..d11b39a --- /dev/null +++ b/backing-services/mongodb/templates/standalone/pdb.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (not (eq .Values.architecture "replicaset")) .Values.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.pdb.minAvailable }} + minAvailable: {{ .Values.pdb.minAvailable }} + {{- end }} + {{- if or .Values.pdb.maxUnavailable (not .Values.pdb.minAvailable) }} + maxUnavailable: {{ .Values.pdb.maxUnavailable | default 1 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: mongodb +{{- end }} diff --git a/backing-services/mongodb/templates/standalone/pvc.yaml b/backing-services/mongodb/templates/standalone/pvc.yaml new file mode 100644 index 0000000..1609858 --- /dev/null +++ b/backing-services/mongodb/templates/standalone/pvc.yaml @@ -0,0 +1,31 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) (not (eq .Values.architecture "replicaset")) (not .Values.useStatefulSet) }} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + annotations: + {{- if .Values.persistence.resourcePolicy }} + helm.sh/resource-policy: {{ .Values.persistence.resourcePolicy | quote }} + {{- end }} + {{- if or .Values.persistence.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.persistence.annotations .Values.commonAnnotations ) "context" . ) }} + {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{ include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) }} +{{- end }} diff --git a/backing-services/mongodb/templates/standalone/svc.yaml b/backing-services/mongodb/templates/standalone/svc.yaml new file mode 100644 index 0000000..c1ec6f7 --- /dev/null +++ b/backing-services/mongodb/templates/standalone/svc.yaml @@ -0,0 +1,62 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if not (eq .Values.architecture "replicaset") }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mongodb.service.nameOverride" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if or .Values.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + {{- if and (eq .Values.service.type "ClusterIP") .Values.service.clusterIP }} + clusterIP: {{ .Values.service.clusterIP }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerClass }} + loadBalancerClass: {{ .Values.service.loadBalancerClass }} + {{- end }} + {{- if .Values.service.externalIPs }} + externalIPs: {{ toYaml .Values.service.externalIPs | nindent 4 }} + {{- end }} + {{- if .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{- toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + {{- if (eq .Values.service.type "LoadBalancer") }} + allocateLoadBalancerNodePorts: {{ .Values.service.allocateLoadBalancerNodePorts }} + {{- end }} + {{- if .Values.service.sessionAffinity }} + sessionAffinity: {{ .Values.service.sessionAffinity }} + {{- end }} + {{- if .Values.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + {{- if (or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort")) }} + externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy | quote }} + {{- end }} + ports: + - name: {{ .Values.service.portName | quote }} + port: {{ .Values.service.ports.mongodb }} + targetPort: mongodb + {{- if and (or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort")) .Values.service.nodePorts.mongodb }} + nodePort: {{ .Values.service.nodePorts.mongodb }} + {{- else if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb +{{- end }} diff --git a/backing-services/mongodb/values.schema.json b/backing-services/mongodb/values.schema.json new file mode 100644 index 0000000..3eb6a64 --- /dev/null +++ b/backing-services/mongodb/values.schema.json @@ -0,0 +1,232 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "architecture": { + "type": "string", + "title": "MongoDB® architecture", + "form": true, + "description": "Allowed values: `standalone` or `replicaset`" + }, + "auth": { + "type": "object", + "title": "Authentication configuration", + "form": true, + "properties": { + "enabled": { + "type": "boolean", + "title": "Enable Authentication", + "form": true + }, + "rootUser": { + "type": "string", + "title": "MongoDB® admin user", + "form": true, + "description": "Name of the admin user. Default is root" + }, + "rootPassword": { + "type": "string", + "title": "MongoDB® admin password", + "form": true, + "description": "Defaults to a random 10-character alphanumeric string if not set", + "hidden": { + "value": false, + "path": "auth/enabled" + } + }, + "database": { + "type": "string", + "title": "MongoDB® custom database", + "description": "Name of the custom database to be created during the 1st initialization of MongoDB®", + "form": true + }, + "username": { + "type": "string", + "title": "MongoDB® custom user", + "description": "Name of the custom user to be created during the 1st initialization of MongoDB®. This user only has permissions on the MongoDB® custom database", + "form": true + }, + "password": { + "type": "string", + "title": "Password for MongoDB® custom user", + "form": true, + "description": "Defaults to a random 10-character alphanumeric string if not set", + "hidden": { + "value": false, + "path": "auth/enabled" + } + }, + "replicaSetKey": { + "type": "string", + "title": "Key used for replica set authentication", + "form": true, + "description": "Defaults to a random 10-character alphanumeric string if not set", + "hidden": { + "value": "standalone", + "path": "architecture" + } + } + } + }, + "replicaCount": { + "type": "integer", + "form": true, + "title": "Number of MongoDB® replicas", + "hidden": { + "value": "standalone", + "path": "architecture" + } + }, + "configuration": { + "type": "string", + "title": "MongoDB® Custom Configuration", + "form": true, + "render": "textArea" + }, + "arbiter": { + "type": "object", + "title": "Arbiter configuration", + "form": true, + "properties": { + "configuration": { + "type": "string", + "title": "Arbiter Custom Configuration", + "form": true, + "render": "textArea", + "hidden": { + "value": "standalone", + "path": "architecture" + } + } + } + }, + "networkPolicy": { + "type": "object", + "title": "Network policy configuration", + "form": true, + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable network policy", + "description": "Enable network policy using Kubernetes native NP", + "hidden": { + "value": false, + "path": "networkPolicy/enabled" + } + }, + "ingress": { + "type": "object", + "properties": { + "namespaceSelector": { + "type": "object", + "title": "Namespace selector label that is allowed to access this instance", + "hidden": { + "value": {}, + "path": "networkPolicy/ingress/namespaceSelector" + } + }, + "podSelector": { + "type": "object", + "title": "Pod selector label that is allowed to access this instance", + "hidden": { + "value": {}, + "path": "networkPolicy/ingress/podSelector" + } + }, + "customRules": { + "type": "array", + "title": "Custom rules for ingress network policy", + "hidden": { + "value": [], + "path": "networkPolicy/ingress/customRules" + } + } + } + }, + "egress": { + "type": "object", + "properties": { + "customRules": { + "type": "array", + "title": "Custom rules for egress network policy", + "hidden": { + "value": [], + "path": "networkPolicy/egress/customRules" + } + } + } + } + } + }, + "persistence": { + "type": "object", + "title": "Persistence configuration", + "form": true, + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable persistence", + "description": "Enable persistence using Persistent Volume Claims" + }, + "size": { + "type": "string", + "title": "Persistent Volume Size", + "form": true, + "render": "slider", + "sliderMin": 1, + "sliderMax": 100, + "sliderUnit": "Gi", + "hidden": { + "value": false, + "path": "persistence/enabled" + } + } + } + }, + "volumePermissions": { + "type": "object", + "hidden": { + "value": false, + "path": "persistence/enabled" + }, + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable Init Containers", + "description": "Use an init container to set required folder permissions on the data volume before mounting it in the final destination" + } + } + }, + "metrics": { + "type": "object", + "form": true, + "title": "Prometheus metrics details", + "properties": { + "enabled": { + "type": "boolean", + "title": "Create Prometheus metrics exporter", + "description": "Create a side-car container to expose Prometheus metrics", + "form": true + }, + "serviceMonitor": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Create Prometheus Operator ServiceMonitor", + "description": "Create a ServiceMonitor to track metrics using Prometheus Operator", + "form": true, + "hidden": { + "value": false, + "path": "metrics/enabled" + } + } + } + } + } + } + } +} diff --git a/backing-services/mongodb/values.yaml b/backing-services/mongodb/values.yaml new file mode 100644 index 0000000..ed90a9f --- /dev/null +++ b/backing-services/mongodb/values.yaml @@ -0,0 +1,2521 @@ +# Copyright Broadcom, Inc. All Rights Reserved. +# SPDX-License-Identifier: APACHE-2.0 + +## @section Global parameters +## 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, imagePullSecrets and storageClass +## + +## @param global.imageRegistry Global Docker image registry +## @param global.imagePullSecrets Global Docker registry secret names as an array +## @param global.defaultStorageClass Global default StorageClass for Persistent Volume(s) +## @param global.storageClass DEPRECATED: use global.defaultStorageClass instead +## @param global.namespaceOverride Override the namespace for resource deployed by the chart, but can itself be overridden by the local namespaceOverride +## +global: + imageRegistry: "" + ## E.g. + ## imagePullSecrets: + ## - myRegistryKeySecretName + ## + imagePullSecrets: [] + defaultStorageClass: "" + storageClass: "" + namespaceOverride: "" + ## Compatibility adaptations for Kubernetes platforms + ## + compatibility: + ## Compatibility adaptations for Openshift + ## + openshift: + ## @param global.compatibility.openshift.adaptSecurityContext Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) + ## + adaptSecurityContext: auto +## @section Common parameters +## + +## @param nameOverride String to partially override mongodb.fullname template (will maintain the release name) +## +nameOverride: "" +## @param fullnameOverride String to fully override mongodb.fullname template +## +fullnameOverride: "" +## @param namespaceOverride String to fully override common.names.namespace +## +namespaceOverride: "" +## @param kubeVersion Force target Kubernetes version (using Helm capabilities if not set) +## +kubeVersion: "" +## @param clusterDomain Default Kubernetes cluster domain +## +clusterDomain: cluster.local +## @param extraDeploy Array of extra objects to deploy with the release +## extraDeploy: +## This needs to be uncommented and added to 'extraDeploy' in order to use the replicaset 'mongo-labeler' sidecar +## for dynamically discovering the mongodb primary pod +## suggestion is to use a hard-coded and predictable TCP port for the primary mongodb pod (here is 30001, choose your own) +## - apiVersion: v1 +## kind: Service +## metadata: +## name: mongodb-primary +## namespace: the-mongodb-namespace +## labels: +## app.kubernetes.io/component: mongodb +## app.kubernetes.io/instance: mongodb +## app.kubernetes.io/managed-by: Helm +## app.kubernetes.io/name: mongodb +## spec: +## type: NodePort +## externalTrafficPolicy: Cluster +## ports: +## - name: mongodb +## port: 30001 +## nodePort: 30001 +## protocol: TCP +## targetPort: mongodb +## selector: +## app.kubernetes.io/component: mongodb +## app.kubernetes.io/instance: mongodb +## app.kubernetes.io/name: mongodb +## primary: "true" +## +extraDeploy: [] +## @param commonLabels Add labels to all the deployed resources (sub-charts are not considered). Evaluated as a template +## +commonLabels: {} +## @param commonAnnotations Common annotations to add to all Mongo resources (sub-charts are not considered). Evaluated as a template +## +commonAnnotations: {} +## @param topologyKey Override common lib default topology key. If empty - "kubernetes.io/hostname" is used +## i.e. topologyKey: topology.kubernetes.io/zone +## +topologyKey: "" +## @param serviceBindings.enabled Create secret for service binding (Experimental) +## Ref: https://servicebinding.io/service-provider/ +## +serviceBindings: + enabled: false +## @param enableServiceLinks Whether information about services should be injected into pod's environment variable +## The environment variables injected by service links are not used, but can lead to slow boot times or slow running of the scripts when there are many services in the current namespace. +## If you experience slow pod startups or slow running of the scripts you probably want to set this to `false`. +## +enableServiceLinks: true +## Enable diagnostic mode in the deployment +## +diagnosticMode: + ## @param diagnosticMode.enabled Enable diagnostic mode (all probes will be disabled and the command will be overridden) + ## + enabled: false + ## @param diagnosticMode.command Command to override all containers in the deployment + ## + command: + - sleep + ## @param diagnosticMode.args Args to override all containers in the deployment + ## + args: + - infinity +## @section MongoDB(®) parameters +## + +## Bitnami MongoDB(®) image +## ref: https://hub.docker.com/r/bitnami/mongodb/tags/ +## @param image.registry [default: REGISTRY_NAME] MongoDB(®) image registry +## @param image.repository [default: REPOSITORY_NAME/mongodb] MongoDB(®) image registry +## @skip image.tag MongoDB(®) image tag (immutable tags are recommended) +## @param image.digest MongoDB(®) image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag +## @param image.pullPolicy MongoDB(®) image pull policy +## @param image.pullSecrets Specify docker-registry secret names as an array +## @param image.debug Set to true if you would like to see extra information on logs +## +image: + registry: docker.io + repository: bitnami/mongodb + tag: 8.0.3-debian-12-r0 + digest: "" + ## Specify a imagePullPolicy + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Set to true if you would like to see extra information on logs + ## + debug: true +## @param schedulerName Name of the scheduler (other than default) to dispatch pods +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +schedulerName: "" +## @param architecture MongoDB(®) architecture (`standalone` or `replicaset`) +## +architecture: standalone +## @param useStatefulSet Set to true to use a StatefulSet instead of a Deployment (only when `architecture=standalone`) +## +useStatefulSet: false +## MongoDB(®) Authentication parameters +## +auth: + ## @param auth.enabled Enable authentication + ## ref: https://docs.mongodb.com/manual/tutorial/enable-authentication/ + ## + enabled: true + ## @param auth.rootUser MongoDB(®) root user + ## + rootUser: root + ## @param auth.rootPassword MongoDB(®) root password + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/mongodb#setting-the-root-user-and-password-on-first-run + ## + rootPassword: "" + ## MongoDB(®) custom users and databases + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/mongodb#creating-a-user-and-database-on-first-run + ## @param auth.usernames List of custom users to be created during the initialization + ## @param auth.passwords List of passwords for the custom users set at `auth.usernames` + ## @param auth.databases List of custom databases to be created during the initialization + ## + usernames: [] + passwords: [] + databases: [] + ## @param auth.username DEPRECATED: use `auth.usernames` instead + ## @param auth.password DEPRECATED: use `auth.passwords` instead + ## @param auth.database DEPRECATED: use `auth.databases` instead + ## + username: "" + password: "" + database: "" + ## @param auth.replicaSetKey Key used for authentication in the replicaset (only when `architecture=replicaset`) + ## + replicaSetKey: "" + ## @param auth.existingSecret Existing secret with MongoDB(®) credentials (keys: `mongodb-passwords`, `mongodb-root-password`, `mongodb-metrics-password`, `mongodb-replica-set-key`) + ## NOTE: When it's set the previous parameters are ignored. + ## + existingSecret: "" +tls: + ## @param tls.enabled Enable MongoDB(®) TLS support between nodes in the cluster as well as between mongo clients and nodes + ## + enabled: false + mTLS: + ## @param tls.mTLS.enabled IF TLS support is enabled, require clients to provide certificates + enabled: true + ## @param tls.autoGenerated Generate a custom CA and self-signed certificates + ## + autoGenerated: true + ## @param tls.existingSecret Existing secret with TLS certificates (keys: `mongodb-ca-cert`, `mongodb-ca-key`) + ## NOTE: When it's set it will disable secret creation. + ## + existingSecret: "" + ## Add Custom CA certificate + ## @param tls.caCert Custom CA certificated (base64 encoded) + ## @param tls.caKey CA certificate private key (base64 encoded) + ## + caCert: "" + caKey: "" + ## @param tls.pemChainIncluded Flag to denote that the Certificate Authority (CA) certificates are bundled with the endpoint cert. + ## Certificates must be in proper order, where the top certificate is the leaf and the bottom certificate is the top-most intermediate CA. + ## + pemChainIncluded: false + standalone: + ## @param tls.standalone.existingSecret Existing secret with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. + ## NOTE: When it's set it will disable certificate self-generation from existing CA. + ## + existingSecret: "" + replicaset: + ## @param tls.replicaset.existingSecrets Array of existing secrets with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. + ## existingSecrets: + ## - "mySecret-0" + ## - "mySecret-1" + ## NOTE: When it's set it will disable certificate self-generation from existing CA. + ## + existingSecrets: [] + hidden: + ## @param tls.hidden.existingSecrets Array of existing secrets with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. + ## existingSecrets: + ## - "mySecret-0" + ## - "mySecret-1" + ## NOTE: When it's set it will disable certificate self-generation from existing CA. + ## + existingSecrets: [] + arbiter: + ## @param tls.arbiter.existingSecret Existing secret with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. + ## NOTE: When it's set it will disable certificate self-generation from existing CA. + ## + existingSecret: "" + ## Bitnami Nginx image + ## @param tls.image.registry [default: REGISTRY_NAME] Init container TLS certs setup image registry + ## @param tls.image.repository [default: REPOSITORY_NAME/nginx] Init container TLS certs setup image repository + ## @skip tls.image.tag Init container TLS certs setup image tag (immutable tags are recommended) + ## @param tls.image.digest Init container TLS certs setup image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param tls.image.pullPolicy Init container TLS certs setup image pull policy + ## @param tls.image.pullSecrets Init container TLS certs specify docker-registry secret names as an array + ## @param tls.extraDnsNames Add extra dns names to the CA, can solve x509 auth issue for pod clients + ## + image: + registry: docker.io + repository: bitnami/nginx + tag: 1.27.2-debian-12-r2 + digest: "" + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## e.g: + ## extraDnsNames + ## "DNS.6": "$my_host" + ## "DNS.7": "$test" + ## + extraDnsNames: [] + ## @param tls.mode Allows to set the tls mode which should be used when tls is enabled (options: `allowTLS`, `preferTLS`, `requireTLS`) + ## + mode: requireTLS + ## Init Container resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## 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:'. + ## @param tls.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if tls.resources is set (tls.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param tls.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Init Container securityContext + ## ref: https://kubernetes.io/docs/concepts/security/pod-security-policy/ + ## @param tls.securityContext Init container generate-tls-cert Security context + ## + securityContext: {} + ## Example: + ## allowPrivilegeEscalation: false + ## capabilities: + ## drop: ["ALL"] + ## +## @param automountServiceAccountToken Mount Service Account token in pod +## +automountServiceAccountToken: false +## @param hostAliases Add deployment host aliases +## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ +## +hostAliases: [] +## @param replicaSetName Name of the replica set (only when `architecture=replicaset`) +## Ignored when mongodb.architecture=standalone +## +replicaSetName: rs0 +## @param replicaSetHostnames Enable DNS hostnames in the replicaset config (only when `architecture=replicaset`) +## Ignored when mongodb.architecture=standalone +## Ignored when externalAccess.enabled=true +## +replicaSetHostnames: true +## @param enableIPv6 Switch to enable/disable IPv6 on MongoDB(®) +## ref: https://github.com/bitnami/containers/tree/main/bitnami/mongodb#enablingdisabling-ipv6 +## +enableIPv6: false +## @param directoryPerDB Switch to enable/disable DirectoryPerDB on MongoDB(®) +## ref: https://github.com/bitnami/containers/tree/main/bitnami/mongodb#enablingdisabling-directoryperdb +## +directoryPerDB: false +## MongoDB(®) System Log configuration +## ref: https://github.com/bitnami/containers/tree/main/bitnami/mongodb#configuring-system-log-verbosity-level +## @param systemLogVerbosity MongoDB(®) system log verbosity level +## @param disableSystemLog Switch to enable/disable MongoDB(®) system log +## +systemLogVerbosity: 0 +disableSystemLog: false +## @param disableJavascript Switch to enable/disable MongoDB(®) server-side JavaScript execution +## ref: https://docs.mongodb.com/manual/core/server-side-javascript/ +## +disableJavascript: false +## @param enableJournal Switch to enable/disable MongoDB(®) Journaling +## ref: https://docs.mongodb.com/manual/reference/configuration-options/#mongodb-setting-storage.journal.enabled +## +enableJournal: true +## @param configuration MongoDB(®) configuration file to be used for Primary and Secondary nodes +## For documentation of all options, see: http://docs.mongodb.org/manual/reference/configuration-options/ +## Example: +## configuration: |- +## # where and how to store data. +## storage: +## dbPath: /bitnami/mongodb/data/db +## journal: +## enabled: true +## directoryPerDB: false +## # where to write logging data +## systemLog: +## destination: file +## quiet: false +## logAppend: true +## logRotate: reopen +## path: /opt/bitnami/mongodb/logs/mongodb.log +## verbosity: 0 +## # network interfaces +## net: +## port: 27017 +## unixDomainSocket: +## enabled: true +## pathPrefix: /opt/bitnami/mongodb/tmp +## ipv6: false +## bindIpAll: true +## # replica set options +## #replication: +## #replSetName: replicaset +## #enableMajorityReadConcern: true +## # process management options +## processManagement: +## fork: false +## pidFilePath: /opt/bitnami/mongodb/tmp/mongodb.pid +## # set parameter options +## setParameter: +## enableLocalhostAuthBypass: true +## # security options +## security: +## authorization: disabled +## #keyFile: /opt/bitnami/mongodb/conf/keyfile +## +configuration: "" +## @section replicaSetConfigurationSettings settings applied during runtime (not via configuration file) +## If enabled, these are applied by a script which is called within setup.sh +## for documentation see https://docs.mongodb.com/manual/reference/replica-configuration/#replica-set-configuration-fields +## @param replicaSetConfigurationSettings.enabled Enable MongoDB(®) Switch to enable/disable configuring MongoDB(®) run time rs.conf settings +## @param replicaSetConfigurationSettings.configuration run-time rs.conf settings +## +replicaSetConfigurationSettings: + enabled: false + configuration: {} +## Custom configurations for individual replica set members. +## Use the prefix 'members[X].' to apply settings to the member X of the replica set. +## Example: 'members[0].priority: 3' sets the priority of the first replica set member to 3. +## The index X in 'members[X]' corresponds to the member's position in the replica set. +## members[0].priority: 3 +## chainingAllowed : false +## heartbeatTimeoutSecs : 10 +## heartbeatIntervalMillis : 2000 +## electionTimeoutMillis : 10000 +## catchUpTimeoutMillis : 30000 +## @param existingConfigmap Name of existing ConfigMap with MongoDB(®) configuration for Primary and Secondary nodes +## NOTE: When it's set the arbiter.configuration parameter is ignored +## +existingConfigmap: "" +## @param initdbScripts Dictionary of initdb scripts +## Specify dictionary of scripts to be run at first boot +## Example: +## initdbScripts: +## my_init_script.sh: | +## #!/bin/bash +## echo "Do something." +## +initdbScripts: {} +## @param initdbScriptsConfigMap Existing ConfigMap with custom initdb scripts +## +initdbScriptsConfigMap: "" +## Command and args for running the container (set to default if not set). Use array form +## @param command Override default container command (useful when using custom images) +## @param args Override default container args (useful when using custom images) +## +command: [] +args: [] +## @param extraFlags MongoDB(®) additional command line flags +## Example: +## extraFlags: +## - "--wiredTigerCacheSizeGB=2" +## +extraFlags: [] +## @param extraEnvVars Extra environment variables to add to MongoDB(®) pods +## E.g: +## extraEnvVars: +## - name: FOO +## value: BAR +## +extraEnvVars: [] +## @param extraEnvVarsCM Name of existing ConfigMap containing extra env vars +## +extraEnvVarsCM: "" +## @param extraEnvVarsSecret Name of existing Secret containing extra env vars (in case of sensitive data) +## +extraEnvVarsSecret: "" +## @section MongoDB(®) statefulset parameters +## + +## @param annotations Additional labels to be added to the MongoDB(®) statefulset. Evaluated as a template +## +annotations: {} +## @param labels Annotations to be added to the MongoDB(®) statefulset. Evaluated as a template +## +labels: {} +## @param replicaCount Number of MongoDB(®) nodes +## When `mongodb.architecture=replicaset`, the number of replicas is taken in account +## When `mongodb.architecture=standalone`, the number of replicas can only be 0 or 1 (value higher then 1 will not be taken in account) +## +replicaCount: 1 +## @param updateStrategy.type Strategy to use to replace existing MongoDB(®) pods. When architecture=standalone and useStatefulSet=false, +## this parameter will be applied on a deployment object. In other case it will be applied on a statefulset object +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy +## Example: +## updateStrategy: +## type: RollingUpdate +## rollingUpdate: +## maxSurge: 25% +## maxUnavailable: 25% +## +updateStrategy: + type: RollingUpdate +## @param podManagementPolicy Pod management policy for MongoDB(®) +## Should be initialized one by one when building the replicaset for the first time +## +podManagementPolicy: OrderedReady +## @param podAffinityPreset MongoDB(®) Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## +podAffinityPreset: "" +## @param podAntiAffinityPreset MongoDB(®) Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## +podAntiAffinityPreset: soft +## Node affinity preset +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity +## +nodeAffinityPreset: + ## @param nodeAffinityPreset.type MongoDB(®) Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param nodeAffinityPreset.key MongoDB(®) Node label key to match Ignored if `affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param nodeAffinityPreset.values MongoDB(®) Node label values to match. Ignored if `affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] +## @param affinity MongoDB(®) Affinity for pod assignment +## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +## Note: podAffinityPreset, podAntiAffinityPreset, and nodeAffinityPreset will be ignored when it's set +## +affinity: {} +## @param nodeSelector MongoDB(®) Node labels for pod assignment +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ +## +nodeSelector: {} +## @param tolerations MongoDB(®) Tolerations for pod assignment +## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +## +tolerations: [] +## @param topologySpreadConstraints MongoDB(®) Spread Constraints for Pods +## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ +## +topologySpreadConstraints: [] +## @param lifecycleHooks LifecycleHook for the MongoDB(®) container(s) to automate configuration before or after startup +## +lifecycleHooks: {} +## @param terminationGracePeriodSeconds MongoDB(®) Termination Grace Period +## +terminationGracePeriodSeconds: "" +## @param podLabels MongoDB(®) pod labels +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +## +podLabels: {} +## @param podAnnotations MongoDB(®) Pod annotations +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +## +podAnnotations: {} +## @param priorityClassName Name of the existing priority class to be used by MongoDB(®) pod(s) +## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ +## +priorityClassName: "" +## @param runtimeClassName Name of the runtime class to be used by MongoDB(®) pod(s) +## ref: https://kubernetes.io/docs/concepts/containers/runtime-class/ +## +runtimeClassName: "" +## MongoDB(®) pods' Security Context. +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod +## @param podSecurityContext.enabled Enable MongoDB(®) pod(s)' Security Context +## @param podSecurityContext.fsGroupChangePolicy Set filesystem group change policy +## @param podSecurityContext.supplementalGroups Set filesystem extra groups +## @param podSecurityContext.fsGroup Group ID for the volumes of the MongoDB(®) pod(s) +## @param podSecurityContext.sysctls sysctl settings of the MongoDB(®) pod(s)' +## +podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + supplementalGroups: [] + fsGroup: 1001 + ## sysctl settings + ## Example: + ## sysctls: + ## - name: net.core.somaxconn + ## value: "10000" + ## + sysctls: [] +## MongoDB(®) containers' Security Context (main and metrics container). +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container +## @param containerSecurityContext.enabled Enabled containers' Security Context +## @param containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container +## @param containerSecurityContext.runAsUser Set containers' Security Context runAsUser +## @param containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup +## @param containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot +## @param containerSecurityContext.privileged Set container's Security Context privileged +## @param containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem +## @param containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation +## @param containerSecurityContext.capabilities.drop List of capabilities to be dropped +## @param containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile +## +containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" +## MongoDB(®) containers' resource requests and limits. +## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ +## 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:'. +## @param resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). +## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 +## +resourcesPreset: "small" +## @param resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) +## Example: +## resources: +## requests: +## cpu: 2 +## memory: 512Mi +## limits: +## cpu: 3 +## memory: 1024Mi +## +resources: {} +## @param containerPorts.mongodb MongoDB(®) container port +## +containerPorts: + mongodb: 27017 +## MongoDB(®) pods' liveness probe. Evaluated as a template. +## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes +## @param livenessProbe.enabled Enable livenessProbe +## @param livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe +## @param livenessProbe.periodSeconds Period seconds for livenessProbe +## @param livenessProbe.timeoutSeconds Timeout seconds for livenessProbe +## @param livenessProbe.failureThreshold Failure threshold for livenessProbe +## @param livenessProbe.successThreshold Success threshold for livenessProbe +## +livenessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 20 + timeoutSeconds: 10 + failureThreshold: 6 + successThreshold: 1 +## MongoDB(®) pods' readiness probe. Evaluated as a template. +## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes +## @param readinessProbe.enabled Enable readinessProbe +## @param readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe +## @param readinessProbe.periodSeconds Period seconds for readinessProbe +## @param readinessProbe.timeoutSeconds Timeout seconds for readinessProbe +## @param readinessProbe.failureThreshold Failure threshold for readinessProbe +## @param readinessProbe.successThreshold Success threshold for readinessProbe +## +readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 +## Slow starting containers can be protected through startup probes +## Startup probes are available in Kubernetes version 1.16 and above +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-startup-probes +## @param startupProbe.enabled Enable startupProbe +## @param startupProbe.initialDelaySeconds Initial delay seconds for startupProbe +## @param startupProbe.periodSeconds Period seconds for startupProbe +## @param startupProbe.timeoutSeconds Timeout seconds for startupProbe +## @param startupProbe.failureThreshold Failure threshold for startupProbe +## @param startupProbe.successThreshold Success threshold for startupProbe +## +startupProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 20 + timeoutSeconds: 10 + successThreshold: 1 + failureThreshold: 30 +## @param customLivenessProbe Override default liveness probe for MongoDB(®) containers +## Ignored when livenessProbe.enabled=true +## +customLivenessProbe: {} +## @param customReadinessProbe Override default readiness probe for MongoDB(®) containers +## Ignored when readinessProbe.enabled=true +## +customReadinessProbe: {} +## @param customStartupProbe Override default startup probe for MongoDB(®) containers +## Ignored when startupProbe.enabled=true +## +customStartupProbe: {} +## @param initContainers Add additional init containers for the hidden node pod(s) +## Example: +## initContainers: +## - name: your-image-name +## image: your-image +## imagePullPolicy: Always +## ports: +## - name: portname +## containerPort: 1234 +## +initContainers: [] +## @param sidecars Add additional sidecar containers for the MongoDB(®) pod(s) +## Example: +## sidecars: +## - name: your-image-name +## image: your-image +## imagePullPolicy: Always +## ports: +## - name: portname +## containerPort: 1234 +## This is an optional 'mongo-labeler' sidecar container that tracks replica-set for the primary mongodb pod +## and labels it dynamically with ' primary: "true" ' in order for an extra-deployed service to always expose +## and attach to the primary pod, this needs to be uncommented along with the suggested 'extraDeploy' example +## and the suggested rbac example for the pod to be allowed adding labels to mongo replica pods +## search 'mongo-labeler' through this file to find the sections that needs to be uncommented to make it work +## +## - name: mongo-labeler +## image: korenlev/k8s-mongo-labeler-sidecar +## imagePullPolicy: Always +## env: +## - name: LABEL_SELECTOR +## value: "app.kubernetes.io/component=mongodb,app.kubernetes.io/instance=mongodb,app.kubernetes.io/name=mongodb" +## - name: NAMESPACE +## value: "the-mongodb-namespace" +## - name: DEBUG +## value: "true" +## +sidecars: [] +## @param extraVolumeMounts Optionally specify extra list of additional volumeMounts for the MongoDB(®) container(s) +## Examples: +## extraVolumeMounts: +## - name: extras +## mountPath: /usr/share/extras +## readOnly: true +## +extraVolumeMounts: [] +## @param extraVolumes Optionally specify extra list of additional volumes to the MongoDB(®) statefulset +## extraVolumes: +## - name: extras +## emptyDir: {} +## +extraVolumes: [] +## MongoDB(®) Pod Disruption Budget configuration +## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ +## +pdb: + ## @param pdb.create Enable/disable a Pod Disruption Budget creation for MongoDB(®) pod(s) + ## + create: true + ## @param pdb.minAvailable Minimum number/percentage of MongoDB(®) pods that must still be available after the eviction + ## + minAvailable: "" + ## @param pdb.maxUnavailable Maximum number/percentage of MongoDB(®) pods that may be made unavailable after the eviction. Defaults to `1` if both `pdb.minAvailable` and `pdb.maxUnavailable` are empty. + ## + maxUnavailable: "" +## @section Traffic exposure parameters +## + +## Service parameters +## +service: + ## @param service.nameOverride MongoDB(®) service name + ## + nameOverride: "" + ## @param service.type Kubernetes Service type (only for standalone architecture) + ## + type: ClusterIP + ## @param service.portName MongoDB(®) service port name (only for standalone architecture) + ## + portName: mongodb + ## @param service.ports.mongodb MongoDB(®) service port. + ## + ports: + mongodb: 27017 + ## @param service.nodePorts.mongodb Port to bind to for NodePort and LoadBalancer service types (only for standalone architecture) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + nodePorts: + mongodb: "" + ## @param service.clusterIP MongoDB(®) service cluster IP (only for standalone architecture) + ## e.g: + ## clusterIP: None + ## + clusterIP: "" + ## @param service.externalIPs Specify the externalIP value ClusterIP service type (only for standalone architecture) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips + ## + externalIPs: [] + ## @param service.loadBalancerIP loadBalancerIP for MongoDB(®) Service (only for standalone architecture) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer + ## + loadBalancerIP: "" + ## @param service.loadBalancerClass loadBalancerClass for MongoDB(®) Service (only for standalone architecture) + # ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + loadBalancerClass: "" + ## @param service.loadBalancerSourceRanges Address(es) that are allowed when service is LoadBalancer (only for standalone architecture) + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## + loadBalancerSourceRanges: [] + ## @param service.allocateLoadBalancerNodePorts Wheter to allocate node ports when service type is LoadBalancer + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-nodeport-allocation + ## + allocateLoadBalancerNodePorts: true + ## @param service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param service.annotations Provide any additional annotations that may be required + ## + annotations: {} + ## @param service.externalTrafficPolicy service external traffic policy (only for standalone architecture) + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Local + ## @param service.sessionAffinity Control where client requests go, to the same pod or round-robin + ## Values: ClientIP or None + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/ + ## + sessionAffinity: None + ## @param service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## Headless service properties + ## + headless: + ## @param service.headless.annotations Annotations for the headless service. + ## + annotations: {} +## External Access to MongoDB(®) nodes configuration +## +externalAccess: + ## @param externalAccess.enabled Enable Kubernetes external cluster access to MongoDB(®) nodes (only for replicaset architecture) + ## + enabled: false + ## External IPs auto-discovery configuration + ## An init container is used to auto-detect LB IPs or node ports by querying the K8s API + ## Note: RBAC might be required + ## + autoDiscovery: + ## @param externalAccess.autoDiscovery.enabled Enable using an init container to auto-detect external IPs by querying the K8s API + ## + enabled: false + ## Bitnami Kubectl image + ## ref: https://hub.docker.com/r/bitnami/kubectl/tags/ + ## @param externalAccess.autoDiscovery.image.registry [default: REGISTRY_NAME] Init container auto-discovery image registry + ## @param externalAccess.autoDiscovery.image.repository [default: REPOSITORY_NAME/kubectl] Init container auto-discovery image repository + ## @skip externalAccess.autoDiscovery.image.tag Init container auto-discovery image tag (immutable tags are recommended) + ## @param externalAccess.autoDiscovery.image.digest Init container auto-discovery image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param externalAccess.autoDiscovery.image.pullPolicy Init container auto-discovery image pull policy + ## @param externalAccess.autoDiscovery.image.pullSecrets Init container auto-discovery image pull secrets + ## + image: + registry: docker.io + repository: bitnami/kubectl + tag: 1.31.2-debian-12-r3 + digest: "" + ## Specify a imagePullPolicy + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-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/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Init Container resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## 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:'. + ## @param externalAccess.autoDiscovery.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if externalAccess.autoDiscovery.resources is set (externalAccess.autoDiscovery.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param externalAccess.autoDiscovery.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Init container what mission is ensure public names can be resolved. + ## + dnsCheck: + ## Bitnami os-shell image + ## ref: https://hub.docker.com/r/bitnami/os-shell/tags/ + ## @param externalAccess.dnsCheck.image.registry [default: REGISTRY_NAME] Init container dns-check image registry + ## @param externalAccess.dnsCheck.image.repository [default: REPOSITORY_NAME/kubectl] Init container dns-check image repository + ## @skip externalAccess.dnsCheck.image.tag Init container dns-check image tag (immutable tags are recommended) + ## @param externalAccess.dnsCheck.image.digest Init container dns-check image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param externalAccess.dnsCheck.image.pullPolicy Init container dns-check image pull policy + ## @param externalAccess.dnsCheck.image.pullSecrets Init container dns-check image pull secrets + ## + image: + registry: docker.io + repository: bitnami/os-shell + tag: 12-debian-12-r32 + digest: "" + ## Specify a imagePullPolicy + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-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/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Init Container resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## 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:'. + ## @param externalAccess.dnsCheck.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if externalAccess.autoDiscovery.resources is set (externalAccess.autoDiscovery.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param externalAccess.dnsCheck.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Parameters to configure a set of Pods that connect to an existing MongoDB(®) deployment that lies outside of Kubernetes. + ## @param externalAccess.externalMaster.enabled Use external master for bootstrapping + ## @param externalAccess.externalMaster.host External master host to bootstrap from + ## @param externalAccess.externalMaster.port Port for MongoDB(®) service external master host + ## + externalMaster: + enabled: false + host: "" + port: 27017 + ## Parameters to configure K8s service(s) used to externally access MongoDB(®) + ## A new service per broker will be created + ## + service: + ## @param externalAccess.service.type Kubernetes Service type for external access. Allowed values: NodePort, LoadBalancer or ClusterIP + ## + type: LoadBalancer + ## @param externalAccess.service.portName MongoDB(®) port name used for external access when service type is LoadBalancer + ## + portName: "mongodb" + ## @param externalAccess.service.ports.mongodb MongoDB(®) port used for external access when service type is LoadBalancer + ## + ports: + mongodb: 27017 + ## @param externalAccess.service.loadBalancerIPs Array of load balancer IPs for MongoDB(®) nodes + ## Example: + ## loadBalancerIPs: + ## - X.X.X.X + ## - Y.Y.Y.Y + ## + loadBalancerIPs: [] + ## @param externalAccess.service.publicNames Array of public names. The size should be equal to the number of replicas. + ## + publicNames: [] + ## @param externalAccess.service.loadBalancerClass loadBalancerClass when service type is LoadBalancer + # ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + loadBalancerClass: "" + ## @param externalAccess.service.loadBalancerSourceRanges Address(es) that are allowed when service is LoadBalancer + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## Example: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param externalAccess.service.allocateLoadBalancerNodePorts Whether to allocate node ports when service type is LoadBalancer + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-nodeport-allocation + ## + allocateLoadBalancerNodePorts: true + ## @param externalAccess.service.externalTrafficPolicy MongoDB(®) service external traffic policy + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Local + ## @param externalAccess.service.nodePorts Array of node ports used to configure MongoDB(®) advertised hostname when service type is NodePort + ## Example: + ## nodePorts: + ## - 30001 + ## - 30002 + ## + nodePorts: [] + ## @param externalAccess.service.domain Domain or external IP used to configure MongoDB(®) advertised hostname when service type is NodePort + ## If not specified, the container will try to get the kubernetes node external IP + ## e.g: + ## domain: mydomain.com + ## + domain: "" + ## @param externalAccess.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param externalAccess.service.annotations Service annotations for external access. These annotations are common for all services created. + ## + annotations: {} + ## @param externalAccess.service.annotationsList Service annotations for eache external service. This value contains a list allowing different annotations per each external service. + ## Eg: + ## annotationsList: + ## - external-dns.alpha.kubernetes.io/hostname: mongodb-0.example.com + ## - external-dns.alpha.kubernetes.io/hostname: mongodb-1.example.com + ## + annotationsList: [] + ## @param externalAccess.service.sessionAffinity Control where client requests go, to the same pod or round-robin + ## Values: ClientIP or None + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/ + ## + sessionAffinity: None + ## @param externalAccess.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## External Access to MongoDB(®) Hidden nodes configuration + ## + hidden: + ## @param externalAccess.hidden.enabled Enable Kubernetes external cluster access to MongoDB(®) hidden nodes + ## + enabled: false + ## Parameters to configure K8s service(s) used to externally access MongoDB(®) + ## A new service per broker will be created + ## + service: + ## @param externalAccess.hidden.service.type Kubernetes Service type for external access. Allowed values: NodePort or LoadBalancer + ## + type: LoadBalancer + ## @param externalAccess.hidden.service.portName MongoDB(®) port name used for external access when service type is LoadBalancer + ## + portName: "mongodb" + ## @param externalAccess.hidden.service.ports.mongodb MongoDB(®) port used for external access when service type is LoadBalancer + ## + ports: + mongodb: 27017 + ## @param externalAccess.hidden.service.loadBalancerIPs Array of load balancer IPs for MongoDB(®) nodes + ## Example: + ## loadBalancerIPs: + ## - X.X.X.X + ## - Y.Y.Y.Y + ## + loadBalancerIPs: [] + ## @param externalAccess.hidden.service.loadBalancerClass loadBalancerClass when service type is LoadBalancer + # ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + loadBalancerClass: "" + ## @param externalAccess.hidden.service.loadBalancerSourceRanges Address(es) that are allowed when service is LoadBalancer + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## Example: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param externalAccess.hidden.service.allocateLoadBalancerNodePorts Wheter to allocate node ports when service type is LoadBalancer + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-nodeport-allocation + ## + allocateLoadBalancerNodePorts: true + ## @param externalAccess.hidden.service.externalTrafficPolicy MongoDB(®) service external traffic policy + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Local + ## @param externalAccess.hidden.service.nodePorts Array of node ports used to configure MongoDB(®) advertised hostname when service type is NodePort. Length must be the same as replicaCount + ## Example: + ## nodePorts: + ## - 30001 + ## - 30002 + ## + nodePorts: [] + ## @param externalAccess.hidden.service.domain Domain or external IP used to configure MongoDB(®) advertised hostname when service type is NodePort + ## If not specified, the container will try to get the kubernetes node external IP + ## e.g: + ## domain: mydomain.com + ## + domain: "" + ## @param externalAccess.hidden.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param externalAccess.hidden.service.annotations Service annotations for external access + ## + annotations: {} + ## @param externalAccess.hidden.service.sessionAffinity Control where client requests go, to the same pod or round-robin + ## Values: ClientIP or None + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/ + ## + sessionAffinity: None + ## @param externalAccess.hidden.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} +## @section Network policy parameters +## + +## Network Policies +## Ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ +## +networkPolicy: + ## @param networkPolicy.enabled Specifies whether a NetworkPolicy should be created + ## + enabled: true + ## @param networkPolicy.allowExternal Don't require server label for connections + ## The Policy model to apply. When set to false, only pods with the correct + ## server label will have network access to the ports server is listening + ## on. When true, server will accept connections from any source + ## (with the correct destination port). + ## + allowExternal: true + ## @param networkPolicy.allowExternalEgress Allow the pod to access any range of port and all destinations. + ## + allowExternalEgress: true + ## @param networkPolicy.addExternalClientAccess Allow access from pods with client label set to "true". Ignored if `networkPolicy.allowExternal` is true. + ## + addExternalClientAccess: true + ## @param networkPolicy.extraIngress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraIngress: + ## - ports: + ## - port: 1234 + ## from: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + extraIngress: [] + ## @param networkPolicy.extraEgress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraEgress: + ## - ports: + ## - port: 1234 + ## to: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraEgress: [] + ## @param networkPolicy.ingressPodMatchLabels [object] Labels to match to allow traffic from other pods. Ignored if `networkPolicy.allowExternal` is true. + ## e.g: + ## ingressPodMatchLabels: + ## my-client: "true" + # + ingressPodMatchLabels: {} + ## @param networkPolicy.ingressNSMatchLabels [object] Labels to match to allow traffic from other namespaces. Ignored if `networkPolicy.allowExternal` is true. + ## @param networkPolicy.ingressNSPodMatchLabels [object] Pod labels to match to allow traffic from other namespaces. Ignored if `networkPolicy.allowExternal` is true. + ## + ingressNSMatchLabels: {} + ingressNSPodMatchLabels: {} +persistence: + ## @param persistence.enabled Enable MongoDB(®) data persistence using PVC + ## + enabled: true + ## @param persistence.name Name of the PVC and mounted volume + ## + name: "datadir" + ## @param persistence.medium Provide a medium for `emptyDir` volumes. + ## Requires persistence.enabled: false + ## + medium: "" + ## @param persistence.existingClaim Provide an existing `PersistentVolumeClaim` (only when `architecture=standalone`) + ## Requires persistence.enabled: true + ## If defined, PVC must be created manually before volume will be bound + ## Ignored when mongodb.architecture=replicaset + ## + existingClaim: "" + ## @param persistence.resourcePolicy Setting it to "keep" to avoid removing PVCs during a helm delete operation. Leaving it empty will delete PVCs after the chart deleted + ## + resourcePolicy: "" + ## @param persistence.storageClass PVC Storage Class for MongoDB(®) data volume + ## 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. + ## + storageClass: "" + ## @param persistence.accessModes PV Access Mode + ## + accessModes: + - ReadWriteOnce + ## @param persistence.size PVC Storage Request for MongoDB(®) data volume + ## + size: 8Gi + ## @param persistence.annotations PVC annotations + ## + annotations: {} + ## @param persistence.labels PVC labels + ## + labels: {} + ## @param persistence.mountPath Path to mount the volume at + ## MongoDB(®) images. + ## + mountPath: /bitnami/mongodb + ## @param persistence.subPath Subdirectory of the volume to mount at + ## and one PV for multiple services. + ## + subPath: "" + ## Fine tuning for volumeClaimTemplates + ## + volumeClaimTemplates: + ## @param persistence.volumeClaimTemplates.selector A label query over volumes to consider for binding (e.g. when using local volumes) + ## A label query over volumes to consider for binding (e.g. when using local volumes) + ## See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#labelselector-v1-meta for more details + ## + selector: {} + ## @param persistence.volumeClaimTemplates.requests Custom PVC requests attributes + ## Sometime cloud providers use additional requests attributes to provision custom storage instance + ## See https://cloud.ibm.com/docs/containers?topic=containers-file_storage#file_dynamic_statefulset + ## + requests: {} + ## @param persistence.volumeClaimTemplates.dataSource Add dataSource to the VolumeClaimTemplate + ## + dataSource: {} +## Persistent Volume Claim Retention Policy +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention +## +persistentVolumeClaimRetentionPolicy: + ## @param persistentVolumeClaimRetentionPolicy.enabled Enable Persistent volume retention policy for MongoDB(®) Statefulset + ## + enabled: false + ## @param persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced + ## + whenScaled: Retain + ## @param persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted + ## + whenDeleted: Retain +## @section Backup parameters +## This section implements a trivial logical dump cronjob of the database. +## This only comes with the consistency guarantees of the dump program. +## This is not a snapshot based roll forward/backward recovery backup. +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/ +## +backup: + ## @param backup.enabled Enable the logical dump of the database "regularly" + ## + enabled: false + ## Fine tuning cronjob's config + ## + cronjob: + ## @param backup.cronjob.schedule Set the cronjob parameter schedule + ## + schedule: "@daily" + ## @param backup.cronjob.concurrencyPolicy Set the cronjob parameter concurrencyPolicy + ## + concurrencyPolicy: Allow + ## @param backup.cronjob.failedJobsHistoryLimit Set the cronjob parameter failedJobsHistoryLimit + ## + failedJobsHistoryLimit: 1 + ## @param backup.cronjob.successfulJobsHistoryLimit Set the cronjob parameter successfulJobsHistoryLimit + ## + successfulJobsHistoryLimit: 3 + ## @param backup.cronjob.startingDeadlineSeconds Set the cronjob parameter startingDeadlineSeconds + ## + startingDeadlineSeconds: "" + ## @param backup.cronjob.ttlSecondsAfterFinished Set the cronjob parameter ttlSecondsAfterFinished + ## + ttlSecondsAfterFinished: "" + ## @param backup.cronjob.restartPolicy Set the cronjob parameter restartPolicy + ## + restartPolicy: OnFailure + ## @param backup.cronjob.backoffLimit Set the cronjob parameter backoffLimit + backoffLimit: 6 + ## backup container's Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param backup.cronjob.containerSecurityContext.enabled Enabled containers' Security Context + ## @param backup.cronjob.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param backup.cronjob.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param backup.cronjob.containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup + ## @param backup.cronjob.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param backup.cronjob.containerSecurityContext.privileged Set container's Security Context privileged + ## @param backup.cronjob.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param backup.cronjob.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param backup.cronjob.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param backup.cronjob.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## backup container's resource requests and limits. + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## 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:'. + ## @param backup.cronjob.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "none" + ## @param backup.cronjob.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## @param backup.cronjob.command Set backup container's command to run + ## + command: [] + ## @param backup.cronjob.labels Set the cronjob labels + ## + labels: {} + ## @param backup.cronjob.annotations Set the cronjob annotations + ## + annotations: {} + ## Backup container's + ## + storage: + ## @param backup.cronjob.storage.existingClaim Provide an existing `PersistentVolumeClaim` (only when `architecture=standalone`) + ## If defined, PVC must be created manually before volume will be bound + ## + existingClaim: "" + ## @param backup.cronjob.storage.resourcePolicy Setting it to "keep" to avoid removing PVCs during a helm delete operation. Leaving it empty will delete PVCs after the chart deleted + ## + resourcePolicy: "" + ## @param backup.cronjob.storage.storageClass PVC Storage Class for the backup data volume + ## 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. + ## + storageClass: "" + ## @param backup.cronjob.storage.accessModes PV Access Mode + ## + accessModes: + - ReadWriteOnce + ## @param backup.cronjob.storage.size PVC Storage Request for the backup data volume + ## + size: 8Gi + ## @param backup.cronjob.storage.annotations PVC annotations + ## + annotations: {} + ## @param backup.cronjob.storage.mountPath Path to mount the volume at + ## + mountPath: /backup/mongodb + ## @param backup.cronjob.storage.subPath Subdirectory of the volume to mount at + ## and one PV for multiple services. + ## + subPath: "" + ## Fine tuning for volumeClaimTemplates + ## + volumeClaimTemplates: + ## @param backup.cronjob.storage.volumeClaimTemplates.selector A label query over volumes to consider for binding (e.g. when using local volumes) + ## A label query over volumes to consider for binding (e.g. when using local volumes) + ## See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#labelselector-v1-meta for more details + ## + selector: {} +## @section RBAC parameters +## + +## ServiceAccount +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ +## +serviceAccount: + ## @param serviceAccount.create Enable creation of ServiceAccount for MongoDB(®) pods + ## + create: true + ## @param serviceAccount.name Name of the created serviceAccount + ## If not set and create is true, a name is generated using the mongodb.fullname template + ## + name: "" + ## @param serviceAccount.annotations Additional Service Account annotations + ## + annotations: {} + ## @param serviceAccount.automountServiceAccountToken Allows auto mount of ServiceAccountToken on the serviceAccount created + ## Can be set to false if pods using this serviceAccount do not need to use K8s API + ## + automountServiceAccountToken: false +## Role Based Access +## ref: https://kubernetes.io/docs/admin/authorization/rbac/ +## +rbac: + ## @param rbac.create Whether to create & use RBAC resources or not + ## binding MongoDB(®) ServiceAccount to a role + ## that allows MongoDB(®) pods querying the K8s API + ## this needs to be set to 'true' to enable the mongo-labeler sidecar primary mongodb discovery + ## + create: false + ## @param rbac.rules Custom rules to create following the role specification + ## The example below needs to be uncommented to use the 'mongo-labeler' sidecar for dynamic discovery of the primary mongodb pod: + ## rules: + ## - apiGroups: + ## - "" + ## resources: + ## - pods + ## verbs: + ## - get + ## - list + ## - watch + ## - update + ## + rules: [] +## PodSecurityPolicy configuration +## Be sure to also set rbac.create to true, otherwise Role and RoleBinding won't be created. +## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ +## +podSecurityPolicy: + ## @param podSecurityPolicy.create Whether to create a PodSecurityPolicy. WARNING: PodSecurityPolicy is deprecated in Kubernetes v1.21 or later, unavailable in v1.25 or later + ## + create: false + ## @param podSecurityPolicy.allowPrivilegeEscalation Enable privilege escalation + ## Either use predefined policy with some adjustments or use `podSecurityPolicy.spec` + ## + allowPrivilegeEscalation: false + ## @param podSecurityPolicy.privileged Allow privileged + ## + privileged: false + ## @param podSecurityPolicy.spec Specify the full spec to use for Pod Security Policy + ## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ + ## Defining a spec ignores the above values. + ## + spec: {} + ## Example: + ## allowPrivilegeEscalation: false + ## fsGroup: + ## rule: 'MustRunAs' + ## ranges: + ## - min: 1001 + ## max: 1001 + ## hostIPC: false + ## hostNetwork: false + ## hostPID: false + ## privileged: false + ## readOnlyRootFilesystem: true + ## requiredDropCapabilities: + ## - ALL + ## runAsUser: + ## rule: 'MustRunAs' + ## ranges: + ## - min: 1001 + ## max: 1001 + ## seLinux: + ## rule: 'RunAsAny' + ## supplementalGroups: + ## rule: 'MustRunAs' + ## ranges: + ## - min: 1001 + ## max: 1001 + ## volumes: + ## - 'configMap' + ## - 'secret' + ## - 'emptyDir' + ## - 'persistentVolumeClaim' + ## +## @section Volume Permissions parameters +## +## Init Container parameters +## Change the owner and group of the persistent volume(s) mountpoint(s) to 'runAsUser:fsGroup' on each component +## values from the securityContext section of the component +## +volumePermissions: + ## @param volumePermissions.enabled Enable init container that changes the owner and group of the persistent volume(s) mountpoint to `runAsUser:fsGroup` + ## + enabled: false + ## @param volumePermissions.image.registry [default: REGISTRY_NAME] Init container volume-permissions image registry + ## @param volumePermissions.image.repository [default: REPOSITORY_NAME/os-shell] Init container volume-permissions image repository + ## @skip volumePermissions.image.tag Init container volume-permissions image tag (immutable tags are recommended) + ## @param volumePermissions.image.digest Init container volume-permissions image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param volumePermissions.image.pullPolicy Init container volume-permissions image pull policy + ## @param volumePermissions.image.pullSecrets Specify docker-registry secret names as an array + ## + image: + registry: docker.io + repository: bitnami/os-shell + tag: 12-debian-12-r32 + digest: "" + ## Specify a imagePullPolicy + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-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/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Init Container resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## 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:'. + ## @param volumePermissions.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if volumePermissions.resources is set (volumePermissions.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param volumePermissions.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Init container Security Context + ## Note: the chown of the data folder is done to containerSecurityContext.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 + ## podSecurityContext.enabled=false,containerSecurityContext.enabled=false and shmVolume.chmod.enabled=false + ## @param volumePermissions.securityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param volumePermissions.securityContext.runAsUser User ID for the volumePermissions container + ## + securityContext: + seLinuxOptions: {} + runAsUser: 0 +## @section Arbiter parameters +## +arbiter: + ## @param arbiter.enabled Enable deploying the arbiter + ## https://docs.mongodb.com/manual/tutorial/add-replica-set-arbiter/ + ## + enabled: true + ## @param arbiter.automountServiceAccountToken Mount Service Account token in pod + ## + automountServiceAccountToken: false + ## @param arbiter.hostAliases Add deployment host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param arbiter.configuration Arbiter configuration file to be used + ## http://docs.mongodb.org/manual/reference/configuration-options/ + ## + configuration: "" + ## @param arbiter.existingConfigmap Name of existing ConfigMap with Arbiter configuration + ## NOTE: When it's set the arbiter.configuration parameter is ignored + ## + existingConfigmap: "" + ## Command and args for running the container (set to default if not set). Use array form + ## @param arbiter.command Override default container command (useful when using custom images) + ## @param arbiter.args Override default container args (useful when using custom images) + ## + command: [] + args: [] + ## @param arbiter.extraFlags Arbiter additional command line flags + ## Example: + ## extraFlags: + ## - "--wiredTigerCacheSizeGB=2" + ## + extraFlags: [] + ## @param arbiter.extraEnvVars Extra environment variables to add to Arbiter pods + ## E.g: + ## extraEnvVars: + ## - name: FOO + ## value: BAR + ## + extraEnvVars: [] + ## @param arbiter.extraEnvVarsCM Name of existing ConfigMap containing extra env vars + ## + extraEnvVarsCM: "" + ## @param arbiter.extraEnvVarsSecret Name of existing Secret containing extra env vars (in case of sensitive data) + ## + extraEnvVarsSecret: "" + ## @param arbiter.annotations Additional labels to be added to the Arbiter statefulset + ## + annotations: {} + ## @param arbiter.labels Annotations to be added to the Arbiter statefulset + ## + labels: {} + ## @param arbiter.topologySpreadConstraints MongoDB(®) Spread Constraints for arbiter Pods + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## + topologySpreadConstraints: [] + ## @param arbiter.lifecycleHooks LifecycleHook for the Arbiter container to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param arbiter.terminationGracePeriodSeconds Arbiter Termination Grace Period + ## + terminationGracePeriodSeconds: "" + ## @param arbiter.updateStrategy.type Strategy that will be employed to update Pods in the StatefulSet + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## updateStrategy: + ## type: RollingUpdate + ## rollingUpdate: + ## maxSurge: 25% + ## maxUnavailable: 25% + ## + updateStrategy: + type: RollingUpdate + ## @param arbiter.podManagementPolicy Pod management policy for MongoDB(®) + ## Should be initialized one by one when building the replicaset for the first time + ## + podManagementPolicy: OrderedReady + ## @param arbiter.schedulerName Name of the scheduler (other than default) to dispatch pods + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param arbiter.podAffinityPreset Arbiter Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param arbiter.podAntiAffinityPreset Arbiter Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param arbiter.nodeAffinityPreset.type Arbiter Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param arbiter.nodeAffinityPreset.key Arbiter Node label key to match Ignored if `affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param arbiter.nodeAffinityPreset.values Arbiter Node label values to match. Ignored if `affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param arbiter.affinity Arbiter Affinity for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## Note: arbiter.podAffinityPreset, arbiter.podAntiAffinityPreset, and arbiter.nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## @param arbiter.nodeSelector Arbiter Node labels for pod assignment + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: {} + ## @param arbiter.tolerations Arbiter Tolerations for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param arbiter.podLabels Arbiter pod labels + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param arbiter.podAnnotations Arbiter Pod annotations + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param arbiter.priorityClassName Name of the existing priority class to be used by Arbiter pod(s) + ## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ + ## + priorityClassName: "" + ## @param arbiter.runtimeClassName Name of the runtime class to be used by Arbiter pod(s) + ## ref: https://kubernetes.io/docs/concepts/containers/runtime-class/ + ## + runtimeClassName: "" + ## MongoDB(®) Arbiter pods' Security Context. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param arbiter.podSecurityContext.enabled Enable Arbiter pod(s)' Security Context + ## @param arbiter.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy + ## @param arbiter.podSecurityContext.supplementalGroups Set filesystem extra groups + ## @param arbiter.podSecurityContext.fsGroup Group ID for the volumes of the Arbiter pod(s) + ## @param arbiter.podSecurityContext.sysctls sysctl settings of the Arbiter pod(s)' + ## + podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + supplementalGroups: [] + fsGroup: 1001 + ## sysctl settings + ## Example: + ## sysctls: + ## - name: net.core.somaxconn + ## value: "10000" + ## + sysctls: [] + ## MongoDB(®) Arbiter containers' Security Context (only main container). + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param arbiter.containerSecurityContext.enabled Enabled containers' Security Context + ## @param arbiter.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param arbiter.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param arbiter.containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup + ## @param arbiter.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param arbiter.containerSecurityContext.privileged Set container's Security Context privileged + ## @param arbiter.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param arbiter.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param arbiter.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param arbiter.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## MongoDB(®) Arbiter containers' resource requests and limits. + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## 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:'. + ## @param arbiter.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if arbiter.resources is set (arbiter.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "small" + ## @param arbiter.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## @param arbiter.containerPorts.mongodb MongoDB(®) arbiter container port + ## + containerPorts: + mongodb: 27017 + ## MongoDB(®) Arbiter pods' liveness probe. Evaluated as a template. + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param arbiter.livenessProbe.enabled Enable livenessProbe + ## @param arbiter.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param arbiter.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param arbiter.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param arbiter.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param arbiter.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 20 + timeoutSeconds: 10 + failureThreshold: 6 + successThreshold: 1 + ## MongoDB(®) Arbiter pods' readiness probe. Evaluated as a template. + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param arbiter.readinessProbe.enabled Enable readinessProbe + ## @param arbiter.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param arbiter.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param arbiter.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param arbiter.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param arbiter.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 20 + timeoutSeconds: 10 + failureThreshold: 6 + successThreshold: 1 + ## MongoDB(®) Arbiter pods' startup probe. Evaluated as a template. + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param arbiter.startupProbe.enabled Enable startupProbe + ## @param arbiter.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param arbiter.startupProbe.periodSeconds Period seconds for startupProbe + ## @param arbiter.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param arbiter.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param arbiter.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 30 + ## @param arbiter.customLivenessProbe Override default liveness probe for Arbiter containers + ## Ignored when arbiter.livenessProbe.enabled=true + ## + customLivenessProbe: {} + ## @param arbiter.customReadinessProbe Override default readiness probe for Arbiter containers + ## Ignored when arbiter.readinessProbe.enabled=true + ## + customReadinessProbe: {} + ## @param arbiter.customStartupProbe Override default startup probe for Arbiter containers + ## Ignored when arbiter.startupProbe.enabled=true + ## + customStartupProbe: {} + ## @param arbiter.initContainers Add additional init containers for the Arbiter pod(s) + ## Example: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + initContainers: [] + ## @param arbiter.sidecars Add additional sidecar containers for the Arbiter pod(s) + ## Example: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param arbiter.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the Arbiter container(s) + ## Examples: + ## extraVolumeMounts: + ## - name: extras + ## mountPath: /usr/share/extras + ## readOnly: true + ## + extraVolumeMounts: [] + ## @param arbiter.extraVolumes Optionally specify extra list of additional volumes to the Arbiter statefulset + ## extraVolumes: + ## - name: extras + ## emptyDir: {} + ## + extraVolumes: [] + ## MongoDB(®) Arbiter Pod Disruption Budget configuration + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ + ## + pdb: + ## @param arbiter.pdb.create Enable/disable a Pod Disruption Budget creation for Arbiter pod(s) + ## + create: true + ## @param arbiter.pdb.minAvailable Minimum number/percentage of Arbiter pods that should remain scheduled + ## + minAvailable: "" + ## @param arbiter.pdb.maxUnavailable Maximum number/percentage of Arbiter pods that may be made unavailable. Defaults to `1` if both `arbiter.pdb.minAvailable` and `arbiter.pdb.maxUnavailable` are empty. + ## + maxUnavailable: "" + ## MongoDB(®) Arbiter service parameters + ## + service: + ## @param arbiter.service.nameOverride The arbiter service name + ## + nameOverride: "" + ## @param arbiter.service.ports.mongodb MongoDB(®) service port + ## + ports: + mongodb: 27017 + ## @param arbiter.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param arbiter.service.annotations Provide any additional annotations that may be required + ## + annotations: {} + ## Headless service properties + ## + headless: + ## @param arbiter.service.headless.annotations Annotations for the headless service. + ## + annotations: {} +## @section Hidden Node parameters +## +hidden: + ## @param hidden.enabled Enable deploying the hidden nodes + ## https://docs.mongodb.com/manual/tutorial/configure-a-hidden-replica-set-member/ + ## + enabled: false + ## @param hidden.automountServiceAccountToken Mount Service Account token in pod + ## + automountServiceAccountToken: false + ## @param hidden.hostAliases Add deployment host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param hidden.configuration Hidden node configuration file to be used + ## http://docs.mongodb.org/manual/reference/configuration-options/ + ## + configuration: "" + ## @param hidden.existingConfigmap Name of existing ConfigMap with Hidden node configuration + ## NOTE: When it's set the hidden.configuration parameter is ignored + ## + existingConfigmap: "" + ## Command and args for running the container (set to default if not set). Use array form + ## @param hidden.command Override default container command (useful when using custom images) + ## @param hidden.args Override default container args (useful when using custom images) + ## + command: [] + args: [] + ## @param hidden.extraFlags Hidden node additional command line flags + ## Example: + ## extraFlags: + ## - "--wiredTigerCacheSizeGB=2" + ## + extraFlags: [] + ## @param hidden.extraEnvVars Extra environment variables to add to Hidden node pods + ## E.g: + ## extraEnvVars: + ## - name: FOO + ## value: BAR + ## + extraEnvVars: [] + ## @param hidden.extraEnvVarsCM Name of existing ConfigMap containing extra env vars + ## + extraEnvVarsCM: "" + ## @param hidden.extraEnvVarsSecret Name of existing Secret containing extra env vars (in case of sensitive data) + ## + extraEnvVarsSecret: "" + ## @param hidden.annotations Additional labels to be added to thehidden node statefulset + ## + annotations: {} + ## @param hidden.labels Annotations to be added to the hidden node statefulset + ## + labels: {} + ## @param hidden.topologySpreadConstraints MongoDB(®) Spread Constraints for hidden Pods + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## + topologySpreadConstraints: [] + ## @param hidden.lifecycleHooks LifecycleHook for the Hidden container to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param hidden.replicaCount Number of hidden nodes (only when `architecture=replicaset`) + ## Ignored when mongodb.architecture=standalone + ## + replicaCount: 1 + ## @param hidden.terminationGracePeriodSeconds Hidden Termination Grace Period + ## + terminationGracePeriodSeconds: "" + ## @param hidden.updateStrategy.type Strategy that will be employed to update Pods in the StatefulSet + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## updateStrategy: + ## type: RollingUpdate + ## rollingUpdate: + ## maxSurge: 25% + ## maxUnavailable: 25% + ## + updateStrategy: + type: RollingUpdate + ## @param hidden.podManagementPolicy Pod management policy for hidden node + ## + podManagementPolicy: OrderedReady + ## @param hidden.schedulerName Name of the scheduler (other than default) to dispatch pods + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param hidden.podAffinityPreset Hidden node Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param hidden.podAntiAffinityPreset Hidden node Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## Allowed values: soft, hard + ## + nodeAffinityPreset: + ## @param hidden.nodeAffinityPreset.type Hidden Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param hidden.nodeAffinityPreset.key Hidden Node label key to match Ignored if `affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param hidden.nodeAffinityPreset.values Hidden Node label values to match. Ignored if `affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param hidden.affinity Hidden node Affinity for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## Note: podAffinityPreset, podAntiAffinityPreset, and nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## @param hidden.nodeSelector Hidden node Node labels for pod assignment + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: {} + ## @param hidden.tolerations Hidden node Tolerations for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param hidden.podLabels Hidden node pod labels + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param hidden.podAnnotations Hidden node Pod annotations + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param hidden.priorityClassName Name of the existing priority class to be used by hidden node pod(s) + ## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ + ## + priorityClassName: "" + ## @param hidden.runtimeClassName Name of the runtime class to be used by hidden node pod(s) + ## ref: https://kubernetes.io/docs/concepts/containers/runtime-class/ + ## + runtimeClassName: "" + ## MongoDB(®) Hidden pods' Security Context. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param hidden.podSecurityContext.enabled Enable Hidden pod(s)' Security Context + ## @param hidden.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy + ## @param hidden.podSecurityContext.supplementalGroups Set filesystem extra groups + ## @param hidden.podSecurityContext.fsGroup Group ID for the volumes of the Hidden pod(s) + ## @param hidden.podSecurityContext.sysctls sysctl settings of the Hidden pod(s)' + ## + podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + supplementalGroups: [] + fsGroup: 1001 + ## sysctl settings + ## Example: + ## sysctls: + ## - name: net.core.somaxconn + ## value: "10000" + ## + sysctls: [] + ## MongoDB(®) Hidden containers' Security Context (only main container). + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param hidden.containerSecurityContext.enabled Enabled containers' Security Context + ## @param hidden.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param hidden.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param hidden.containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup + ## @param hidden.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param hidden.containerSecurityContext.privileged Set container's Security Context privileged + ## @param hidden.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param hidden.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param hidden.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param hidden.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## MongoDB(®) Hidden containers' resource requests and limits. + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## 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:'. + ## @param hidden.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if hidden.resources is set (hidden.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "micro" + ## @param hidden.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## @param hidden.containerPorts.mongodb MongoDB(®) hidden container port + ## + containerPorts: + mongodb: 27017 + ## MongoDB(®) Hidden pods' liveness probe. Evaluated as a template. + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param hidden.livenessProbe.enabled Enable livenessProbe + ## @param hidden.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param hidden.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param hidden.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param hidden.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param hidden.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 20 + timeoutSeconds: 10 + failureThreshold: 6 + successThreshold: 1 + ## MongoDB(®) Hidden pods' readiness probe. Evaluated as a template. + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param hidden.readinessProbe.enabled Enable readinessProbe + ## @param hidden.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param hidden.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param hidden.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param hidden.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param hidden.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 20 + timeoutSeconds: 10 + failureThreshold: 6 + successThreshold: 1 + ## Slow starting containers can be protected through startup probes + ## Startup probes are available in Kubernetes version 1.16 and above + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-startup-probes + ## @param hidden.startupProbe.enabled Enable startupProbe + ## @param hidden.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param hidden.startupProbe.periodSeconds Period seconds for startupProbe + ## @param hidden.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param hidden.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param hidden.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 30 + ## @param hidden.customLivenessProbe Override default liveness probe for hidden node containers + ## Ignored when hidden.livenessProbe.enabled=true + ## + customLivenessProbe: {} + ## @param hidden.customReadinessProbe Override default readiness probe for hidden node containers + ## Ignored when hidden.readinessProbe.enabled=true + ## + customReadinessProbe: {} + ## @param hidden.customStartupProbe Override default startup probe for MongoDB(®) containers + ## Ignored when hidden.startupProbe.enabled=true + ## + customStartupProbe: {} + ## @param hidden.initContainers Add init containers to the MongoDB(®) Hidden pods. + ## Example: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + initContainers: [] + ## @param hidden.sidecars Add additional sidecar containers for the hidden node pod(s) + ## Example: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param hidden.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the hidden node container(s) + ## Examples: + ## extraVolumeMounts: + ## - name: extras + ## mountPath: /usr/share/extras + ## readOnly: true + ## + extraVolumeMounts: [] + ## @param hidden.extraVolumes Optionally specify extra list of additional volumes to the hidden node statefulset + ## extraVolumes: + ## - name: extras + ## emptyDir: {} + ## + extraVolumes: [] + ## MongoDB(®) Hidden Pod Disruption Budget configuration + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ + ## + pdb: + ## @param hidden.pdb.create Enable/disable a Pod Disruption Budget creation for hidden node pod(s) + ## + create: true + ## @param hidden.pdb.minAvailable Minimum number/percentage of hidden node pods that should remain scheduled + ## + minAvailable: "" + ## @param hidden.pdb.maxUnavailable Maximum number/percentage of hidden node pods that may be made unavailable. Defaults to `1` if both `hidden.pdb.minAvailable` and `hidden.pdb.maxUnavailable` are empty. + ## + maxUnavailable: "" + ## Enable persistence using Persistent Volume Claims + ## ref: https://kubernetes.io/docs/concepts/storage/persistent-volumes/ + ## + persistence: + ## @param hidden.persistence.enabled Enable hidden node data persistence using PVC + ## + enabled: true + ## @param hidden.persistence.medium Provide a medium for `emptyDir` volumes. + ## Requires hidden.persistence.enabled: false + ## + medium: "" + ## @param hidden.persistence.storageClass PVC Storage Class for hidden node data volume + ## 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. + ## + storageClass: "" + ## @param hidden.persistence.accessModes PV Access Mode + ## + accessModes: + - ReadWriteOnce + ## @param hidden.persistence.size PVC Storage Request for hidden node data volume + ## + size: 8Gi + ## @param hidden.persistence.annotations PVC annotations + ## + annotations: {} + ## @param hidden.persistence.mountPath The path the volume will be mounted at, useful when using different MongoDB(®) images. + ## + mountPath: /bitnami/mongodb + ## @param hidden.persistence.subPath The subdirectory of the volume to mount to, useful in dev environments + ## and one PV for multiple services. + ## + subPath: "" + ## Fine tuning for volumeClaimTemplates + ## + volumeClaimTemplates: + ## @param hidden.persistence.volumeClaimTemplates.selector A label query over volumes to consider for binding (e.g. when using local volumes) + ## See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#labelselector-v1-meta for more details + ## + selector: {} + ## @param hidden.persistence.volumeClaimTemplates.requests Custom PVC requests attributes + ## Sometime cloud providers use additional requests attributes to provision custom storage instance + ## See https://cloud.ibm.com/docs/containers?topic=containers-file_storage#file_dynamic_statefulset + ## + requests: {} + ## @param hidden.persistence.volumeClaimTemplates.dataSource Set volumeClaimTemplate dataSource + ## + dataSource: {} + service: + ## @param hidden.service.nameOverride The hidden service name + ## + nameOverride: "" + ## @param hidden.service.portName MongoDB(®) service port name + ## + portName: "mongodb" + ## @param hidden.service.ports.mongodb MongoDB(®) service port + ## + ports: + mongodb: 27017 + ## @param hidden.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param hidden.service.annotations Provide any additional annotations that may be required + ## + annotations: {} + ## Headless service properties + ## + headless: + ## @param hidden.service.headless.annotations Annotations for the headless service. + ## + annotations: {} +## @section Metrics parameters +## +metrics: + ## @param metrics.enabled Enable using a sidecar Prometheus exporter + ## + enabled: false + ## Bitnami MongoDB(®) Promtheus Exporter image + ## ref: https://hub.docker.com/r/bitnami/mongodb-exporter/tags/ + ## @param metrics.image.registry [default: REGISTRY_NAME] MongoDB(®) Prometheus exporter image registry + ## @param metrics.image.repository [default: REPOSITORY_NAME/mongodb-exporter] MongoDB(®) Prometheus exporter image repository + ## @skip metrics.image.tag MongoDB(®) Prometheus exporter image tag (immutable tags are recommended) + ## @param metrics.image.digest MongoDB(®) image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param metrics.image.pullPolicy MongoDB(®) Prometheus exporter image pull policy + ## @param metrics.image.pullSecrets Specify docker-registry secret names as an array + ## + image: + registry: docker.io + repository: bitnami/mongodb-exporter + tag: 0.41.2-debian-12-r1 + digest: "" + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## @param metrics.username String with username for the metrics exporter + ## If undefined the root user will be used for the metrics exporter + ## + username: "" + ## @param metrics.password String with password for the metrics exporter + ## If undefined but metrics.username is defined, a random password will be generated + ## + password: "" + ## @param metrics.compatibleMode Enables old style mongodb-exporter metrics + compatibleMode: true + collector: + ## @param metrics.collector.all Enable all collectors. Same as enabling all individual metrics + ## Enabling all metrics will cause significant CPU load on mongod + all: false + ## @param metrics.collector.diagnosticdata Boolean Enable collecting metrics from getDiagnosticData + diagnosticdata: true + ## @param metrics.collector.replicasetstatus Boolean Enable collecting metrics from replSetGetStatus + replicasetstatus: true + ## @param metrics.collector.dbstats Boolean Enable collecting metrics from dbStats + dbstats: false + ## @param metrics.collector.topmetrics Boolean Enable collecting metrics from top admin command + topmetrics: false + ## @param metrics.collector.indexstats Boolean Enable collecting metrics from $indexStats + indexstats: false + ## @param metrics.collector.collstats Boolean Enable collecting metrics from $collStats + collstats: false + ## @param metrics.collector.collstatsColls List of \.\ to get $collStats + collstatsColls: [] + ## @param metrics.collector.indexstatsColls List - List of \.\ to get $indexStats + indexstatsColls: [] + ## @param metrics.collector.collstatsLimit Number - Disable collstats, dbstats, topmetrics and indexstats collector if there are more than \ collections. 0=No limit + collstatsLimit: 0 + ## @param metrics.extraFlags String with extra flags to the metrics exporter + ## ref: https://github.com/percona/mongodb_exporter/blob/main/main.go + ## + extraFlags: "" + ## Command and args for running the container (set to default if not set). Use array form + ## @param metrics.command Override default container command (useful when using custom images) + ## @param metrics.args Override default container args (useful when using custom images) + ## + command: [] + args: [] + ## Metrics exporter container resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## 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:'. + ## @param metrics.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if metrics.resources is set (metrics.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param metrics.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## @param metrics.containerPort Port of the Prometheus metrics container + ## + containerPort: 9216 + ## Prometheus Exporter service configuration + ## + service: + ## @param metrics.service.annotations [object] Annotations for Prometheus Exporter pods. Evaluated as a template. + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "{{ .Values.metrics.service.ports.metrics }}" + prometheus.io/path: "/metrics" + ## @param metrics.service.type Type of the Prometheus metrics service + ## + type: ClusterIP + ## @param metrics.service.ports.metrics Port of the Prometheus metrics service + ## + ports: + metrics: 9216 + ## @param metrics.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## Metrics exporter liveness probe + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) + ## @param metrics.livenessProbe.enabled Enable livenessProbe + ## @param metrics.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param metrics.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param metrics.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param metrics.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param metrics.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 15 + periodSeconds: 5 + timeoutSeconds: 10 + failureThreshold: 3 + successThreshold: 1 + ## Metrics exporter readiness probe + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) + ## @param metrics.readinessProbe.enabled Enable readinessProbe + ## @param metrics.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param metrics.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param metrics.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param metrics.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param metrics.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 10 + failureThreshold: 3 + successThreshold: 1 + ## Slow starting containers can be protected through startup probes + ## Startup probes are available in Kubernetes version 1.16 and above + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-startup-probes + ## @param metrics.startupProbe.enabled Enable startupProbe + ## @param metrics.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param metrics.startupProbe.periodSeconds Period seconds for startupProbe + ## @param metrics.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param metrics.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param metrics.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 30 + ## @param metrics.customLivenessProbe Override default liveness probe for MongoDB(®) containers + ## Ignored when livenessProbe.enabled=true + ## + customLivenessProbe: {} + ## @param metrics.customReadinessProbe Override default readiness probe for MongoDB(®) containers + ## Ignored when readinessProbe.enabled=true + ## + customReadinessProbe: {} + ## @param metrics.customStartupProbe Override default startup probe for MongoDB(®) containers + ## Ignored when startupProbe.enabled=true + ## + customStartupProbe: {} + ## @param metrics.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the metrics container(s) + ## Examples: + ## extraVolumeMounts: + ## - name: extras + ## mountPath: /usr/share/extras + ## readOnly: true + ## + extraVolumeMounts: [] + ## Prometheus Service Monitor + ## ref: https://github.com/coreos/prometheus-operator + ## https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md + ## + serviceMonitor: + ## @param metrics.serviceMonitor.enabled Create ServiceMonitor Resource for scraping metrics using Prometheus Operator + ## + enabled: false + ## @param metrics.serviceMonitor.namespace Namespace which Prometheus is running in + ## + namespace: "" + ## @param metrics.serviceMonitor.interval Interval at which metrics should be scraped + ## + interval: 30s + ## @param metrics.serviceMonitor.scrapeTimeout Specify the timeout after which the scrape is ended + ## e.g: + ## scrapeTimeout: 30s + ## + scrapeTimeout: "" + ## @param metrics.serviceMonitor.relabelings RelabelConfigs to apply to samples before scraping. + ## + relabelings: [] + ## @param metrics.serviceMonitor.metricRelabelings MetricsRelabelConfigs to apply to samples before ingestion. + ## + metricRelabelings: [] + ## @param metrics.serviceMonitor.labels Used to pass Labels that are used by the Prometheus installed in your cluster to select Service Monitors to work with + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#prometheusspec + ## + labels: {} + ## @param metrics.serviceMonitor.selector Prometheus instance selector labels + ## ref: https://github.com/bitnami/charts/tree/main/bitnami/prometheus-operator#prometheus-configuration + ## + selector: {} + ## @param metrics.serviceMonitor.honorLabels Specify honorLabels parameter to add the scrape endpoint + ## + honorLabels: false + ## @param metrics.serviceMonitor.jobLabel The name of the label on the target service to use as the job name in prometheus. + ## + jobLabel: "" + ## Custom PrometheusRule to be defined + ## ref: https://github.com/coreos/prometheus-operator#customresourcedefinitions + ## + prometheusRule: + ## @param metrics.prometheusRule.enabled Set this to true to create prometheusRules for Prometheus operator + ## + enabled: false + ## @param metrics.prometheusRule.additionalLabels Additional labels that can be used so prometheusRules will be discovered by Prometheus + ## + additionalLabels: {} + ## @param metrics.prometheusRule.namespace Namespace where prometheusRules resource should be created + ## + namespace: "" + ## @param metrics.prometheusRule.rules Rules to be created, check values for an example + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#rulegroup + ## https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/ + ## + ## This is an example of a rule, you should add the below code block under the "rules" param, removing the brackets + ## rules: + ## - alert: HighRequestLatency + ## expr: job:request_latency_seconds:mean5m{job="myjob"} > 0.5 + ## for: 10m + ## labels: + ## severity: page + ## annotations: + ## summary: High request latency + ## + rules: [] diff --git a/backing-services/mssql/Chart.lock b/backing-services/mssql/Chart.lock new file mode 100644 index 0000000..3f6e75f --- /dev/null +++ b/backing-services/mssql/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: https://charts.bitnami.com/bitnami + version: 2.23.0 +digest: sha256:5fb74412c91f46fb4d3b8a990d2c849237d0c82158d02b652fadae78bce10519 +generated: "2024-09-25T20:23:22.930481811+02:00" diff --git a/backing-services/mssql/Chart.yaml b/backing-services/mssql/Chart.yaml new file mode 100644 index 0000000..8077eb0 --- /dev/null +++ b/backing-services/mssql/Chart.yaml @@ -0,0 +1,40 @@ +annotations: + artifacthub.io/category: database + artifacthub.io/maintainers: | + - name: Björn Dieding + email: bjoern@xrow.de + artifacthub.io/operator: "false" + artifacthub.io/signKey: | + fingerprint: "U/A3w781aiA3oGnsr34dEKhn/EGNJN37WpmGKsHU0MY" + url: https://gitlab.com/xrow.keys +apiVersion: v2 +appVersion: 2022-CU14-GDR1-rhel-9.1 +dependencies: +- name: common + repository: https://charts.bitnami.com/bitnami + tags: + - bitnami-common + version: 2.x.x +description: 'Microsoft SQL Server is a DBMS used by many organizations. Ease Migrating + your SQL Servers to Cloud Native by leveraging this Helm chart. ' +home: https://gitlab.com/xrow-public/helm-mssql +icon: https://upload.wikimedia.org/wikipedia/de/8/8c/Microsoft_SQL_Server_Logo.svg +keywords: +- mssql +- microsoftsql +- database +- dbms +- sql +- cluster +- high availability +maintainers: +- name: Björn Dieding + url: https://www.xrow.de +- name: xrow GmbH + url: https://www.xrow.de +name: mssql +sources: +- https://gitlab.com/xrow-public/helm-mssql +- https://github.com/Microsoft/mssql-docker +- https://hub.docker.com/_/microsoft-mssql-server +version: 1.1.3 diff --git a/backing-services/mssql/README.md b/backing-services/mssql/README.md new file mode 100644 index 0000000..cda3199 --- /dev/null +++ b/backing-services/mssql/README.md @@ -0,0 +1,66 @@ +# Helm chart for Microsoft SQL Server + +Microsoft SQL Server is still used by many organizations. And migration to Cloud native can be a blocked by having this technology. +In order to help organization to lift-shift to Cloud Native, they can run also MS SQL in kubernetes via this Helm chart + +> **DISCLAIMER** +> BY DEPLOYING THIS HELM CHART, YOU ARE ACCEPTING THE [END-USER Licensing Agreement of Microsoft SQL Server](https://github.com/microsoft/mssql-docker/blob/master/LICENSE) + +## Install + +Verify the helm chart via cosign + +```sh +export COSIGN_PUBLIC_KEY=$(curl https://gitlab.com/xrow.keys | grep rsa | ssh-keygen -f /dev/stdin -e -m pem) +cosign verify --key env://COSIGN_PUBLIC_KEY registry.gitlab.com/xrow-public/helm-mssql/charts/mssql:1.1.3 +``` + +values.yaml +```yaml +--- +global: + storageClass: "openebs-kernel-nfs" # Change this + +auth: + database: test + rootPassword: 'yourStrong(#)Password' + username: test + password: 'yourStrong(#)Password' +``` + +```sh +helm upgrade --install mssql oci://registry.gitlab.com/xrow-public/helm-mssql/charts/mssql --version 1.1.3 --create-namespace -n mssql -f values.yaml +``` + +# values.yaml + +Check default values of this chart [here](https://gitlab.com/xrow-public/helm-mssql/-/blob/main/chart/values.yaml) . + +# Features + +* Applying Helm Chart standards +* Ability to specify own registry +* Persisting data +* Auto Bootstrapping Database +* Auto Bootstraping Database Owner User with given password +* Ability to execute initial DB scripts (SQL) +* Performance Monitoring - Integrated with Prometheus Operator + +## Data initalisation via init folder + +```Docker +FROM registry.gitlab.com/xrow-public/helm-mssql:1.1.3 + +COPY *.sql /docker-entrypoint-initdb.d +``` + +## Test the container + +```bash +podman build -t mssql . +docker run -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=' -p 1433:1433 -v sqlvolume:/var/opt/mssql -it localhost/mssql:1.1.3 +``` + +## Credits + +Credits to [ElmCompany](https://github.com/ElmCompany/helm-charts/tree/master/charts/mssql) for inital work. diff --git a/backing-services/mssql/artifacthub-repo.yml b/backing-services/mssql/artifacthub-repo.yml new file mode 100644 index 0000000..c1623b3 --- /dev/null +++ b/backing-services/mssql/artifacthub-repo.yml @@ -0,0 +1,6 @@ +# https://github.com/artifacthub/hub/blob/master/docs/metadata/artifacthub-repo.yml + +repositoryID: d21186d5-1cfe-4ed7-b9ad-7ff8a63c8def +owners: +- name: xrow + email: bjoern@xrow.de \ No newline at end of file diff --git a/backing-services/mssql/charts/common/.helmignore b/backing-services/mssql/charts/common/.helmignore new file mode 100644 index 0000000..d0e1084 --- /dev/null +++ b/backing-services/mssql/charts/common/.helmignore @@ -0,0 +1,26 @@ +# 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 +.vscode/ +# img folder +img/ +# Changelog +CHANGELOG.md diff --git a/backing-services/mssql/charts/common/Chart.yaml b/backing-services/mssql/charts/common/Chart.yaml new file mode 100644 index 0000000..8cc0aaa --- /dev/null +++ b/backing-services/mssql/charts/common/Chart.yaml @@ -0,0 +1,23 @@ +annotations: + category: Infrastructure + licenses: Apache-2.0 +apiVersion: v2 +appVersion: 2.23.0 +description: A Library Helm Chart for grouping common logic between bitnami charts. + This chart is not deployable by itself. +home: https://bitnami.com +icon: https://bitnami.com/downloads/logos/bitnami-mark.png +keywords: +- common +- helper +- template +- function +- bitnami +maintainers: +- name: Broadcom, Inc. All Rights Reserved. + url: https://github.com/bitnami/charts +name: common +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/common +type: library +version: 2.23.0 diff --git a/backing-services/mssql/charts/common/README.md b/backing-services/mssql/charts/common/README.md new file mode 100644 index 0000000..fee26c9 --- /dev/null +++ b/backing-services/mssql/charts/common/README.md @@ -0,0 +1,235 @@ +# Bitnami Common Library Chart + +A [Helm Library Chart](https://helm.sh/docs/topics/library_charts/#helm) for grouping common logic between Bitnami charts. + +## TL;DR + +```yaml +dependencies: + - name: common + version: 2.x.x + repository: oci://registry-1.docker.io/bitnamicharts +``` + +```console +helm dependency update +``` + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "common.names.fullname" . }} +data: + myvalue: "Hello World" +``` + +Looking to use our applications in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the commercial edition of the Bitnami catalog. + +## Introduction + +This chart provides a common template helpers which can be used to develop new charts using [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ + +## Parameters + +## Special input schemas + +### ImageRoot + +```yaml +registry: + type: string + description: Docker registry where the image is located + example: docker.io + +repository: + type: string + description: Repository and image name + example: bitnami/nginx + +tag: + type: string + description: image tag + example: 1.16.1-debian-10-r63 + +pullPolicy: + type: string + description: Specify a imagePullPolicy. Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + +pullSecrets: + type: array + items: + type: string + description: Optionally specify an array of imagePullSecrets (evaluated as templates). + +debug: + type: boolean + description: Set to true if you would like to see extra information on logs + example: false + +## An instance would be: +# registry: docker.io +# repository: bitnami/nginx +# tag: 1.16.1-debian-10-r63 +# pullPolicy: IfNotPresent +# debug: false +``` + +### Persistence + +```yaml +enabled: + type: boolean + description: Whether enable persistence. + example: true + +storageClass: + type: string + description: Ghost data Persistent Volume Storage Class, If set to "-", storageClassName: "" which disables dynamic provisioning. + example: "-" + +accessMode: + type: string + description: Access mode for the Persistent Volume Storage. + example: ReadWriteOnce + +size: + type: string + description: Size the Persistent Volume Storage. + example: 8Gi + +path: + type: string + description: Path to be persisted. + example: /bitnami + +## An instance would be: +# enabled: true +# storageClass: "-" +# accessMode: ReadWriteOnce +# size: 8Gi +# path: /bitnami +``` + +### ExistingSecret + +```yaml +name: + type: string + description: Name of the existing secret. + example: mySecret +keyMapping: + description: Mapping between the expected key name and the name of the key in the existing secret. + type: object + +## An instance would be: +# name: mySecret +# keyMapping: +# password: myPasswordKey +``` + +#### Example of use + +When we store sensitive data for a deployment in a secret, some times we want to give to users the possibility of using theirs existing secrets. + +```yaml +# templates/secret.yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }} + labels: + app: {{ include "common.names.fullname" . }} +type: Opaque +data: + password: {{ .Values.password | b64enc | quote }} + +# templates/dpl.yaml +--- +... + env: + - name: PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "common.secrets.name" (dict "existingSecret" .Values.existingSecret "context" $) }} + key: {{ include "common.secrets.key" (dict "existingSecret" .Values.existingSecret "key" "password") }} +... + +# values.yaml +--- +name: mySecret +keyMapping: + password: myPasswordKey +``` + +### ValidateValue + +#### NOTES.txt + +```console +{{- $validateValueConf00 := (dict "valueKey" "path.to.value00" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value01" "secret" "secretName" "field" "password-01") -}} + +{{ include "common.validations.values.multiple.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} +``` + +If we force those values to be empty we will see some alerts + +```console +helm install test mychart --set path.to.value00="",path.to.value01="" + 'path.to.value00' must not be empty, please add '--set path.to.value00=$PASSWORD_00' to the command. To get the current value: + + export PASSWORD_00=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-00}" | base64 -d) + + 'path.to.value01' must not be empty, please add '--set path.to.value01=$PASSWORD_01' to the command. To get the current value: + + export PASSWORD_01=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-01}" | base64 -d) +``` + +## Upgrading + +### To 1.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +#### What changes were introduced in this major version? + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- Use `type: library`. [Here](https://v3.helm.sh/docs/faq/#library-chart-support) you can find more information. +- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts + +#### Considerations when upgrading to this version + +- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues +- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore +- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 + +#### Useful links + +- +- +- + +## License + +Copyright © 2024 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/backing-services/mssql/charts/common/templates/_affinities.tpl b/backing-services/mssql/charts/common/templates/_affinities.tpl new file mode 100644 index 0000000..c2d2907 --- /dev/null +++ b/backing-services/mssql/charts/common/templates/_affinities.tpl @@ -0,0 +1,139 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a soft nodeAffinity definition +{{ include "common.affinities.nodes.soft" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.soft" -}} +preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} + weight: 1 +{{- end -}} + +{{/* +Return a hard nodeAffinity definition +{{ include "common.affinities.nodes.hard" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.hard" -}} +requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} +{{- end -}} + +{{/* +Return a nodeAffinity definition +{{ include "common.affinities.nodes" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.nodes.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.nodes.hard" . -}} + {{- end -}} +{{- end -}} + +{{/* +Return a topologyKey definition +{{ include "common.affinities.topologyKey" (dict "topologyKey" "BAR") -}} +*/}} +{{- define "common.affinities.topologyKey" -}} +{{ .topologyKey | default "kubernetes.io/hostname" -}} +{{- end -}} + +{{/* +Return a soft podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.soft" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "context" $) -}} +*/}} +{{- define "common.affinities.pods.soft" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: 1 + {{- range $extraPodAffinityTerms }} + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: {{ .weight | default 1 -}} + {{- end -}} +{{- end -}} + +{{/* +Return a hard podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.hard" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "context" $) -}} +*/}} +{{- define "common.affinities.pods.hard" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- range $extraPodAffinityTerms }} + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- end -}} +{{- end -}} + +{{/* +Return a podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.pods" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.pods.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.pods.hard" . -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/mssql/charts/common/templates/_capabilities.tpl b/backing-services/mssql/charts/common/templates/_capabilities.tpl new file mode 100644 index 0000000..2fe81d3 --- /dev/null +++ b/backing-services/mssql/charts/common/templates/_capabilities.tpl @@ -0,0 +1,229 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the target Kubernetes version +*/}} +{{- define "common.capabilities.kubeVersion" -}} +{{- default (default .Capabilities.KubeVersion.Version .Values.kubeVersion) ((.Values.global).kubeVersion) -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for poddisruptionbudget. +*/}} +{{- define "common.capabilities.policy.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.21-0" $kubeVersion) -}} +{{- print "policy/v1beta1" -}} +{{- else -}} +{{- print "policy/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "common.capabilities.networkPolicy.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.7-0" $kubeVersion) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for cronjob. +*/}} +{{- define "common.capabilities.cronjob.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.21-0" $kubeVersion) -}} +{{- print "batch/v1beta1" -}} +{{- else -}} +{{- print "batch/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for daemonset. +*/}} +{{- define "common.capabilities.daemonset.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.14-0" $kubeVersion) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for deployment. +*/}} +{{- define "common.capabilities.deployment.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.14-0" $kubeVersion) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for statefulset. +*/}} +{{- define "common.capabilities.statefulset.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.14-0" $kubeVersion) -}} +{{- print "apps/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "common.capabilities.ingress.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if (.Values.ingress).apiVersion -}} +{{- .Values.ingress.apiVersion -}} +{{- else if and (not (empty $kubeVersion)) (semverCompare "<1.14-0" $kubeVersion) -}} +{{- print "extensions/v1beta1" -}} +{{- else if and (not (empty $kubeVersion)) (semverCompare "<1.19-0" $kubeVersion) -}} +{{- print "networking.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end }} +{{- end -}} + +{{/* +Return the appropriate apiVersion for RBAC resources. +*/}} +{{- define "common.capabilities.rbac.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.17-0" $kubeVersion) -}} +{{- print "rbac.authorization.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "rbac.authorization.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for CRDs. +*/}} +{{- define "common.capabilities.crd.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.19-0" $kubeVersion) -}} +{{- print "apiextensions.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiextensions.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for APIService. +*/}} +{{- define "common.capabilities.apiService.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.10-0" $kubeVersion) -}} +{{- print "apiregistration.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiregistration.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Horizontal Pod Autoscaler. +*/}} +{{- define "common.capabilities.hpa.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" .context -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.23-0" $kubeVersion) -}} +{{- if .beta2 -}} +{{- print "autoscaling/v2beta2" -}} +{{- else -}} +{{- print "autoscaling/v2beta1" -}} +{{- end -}} +{{- else -}} +{{- print "autoscaling/v2" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Vertical Pod Autoscaler. +*/}} +{{- define "common.capabilities.vpa.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" .context -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.23-0" $kubeVersion) -}} +{{- if .beta2 -}} +{{- print "autoscaling/v2beta2" -}} +{{- else -}} +{{- print "autoscaling/v2beta1" -}} +{{- end -}} +{{- else -}} +{{- print "autoscaling/v2" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if PodSecurityPolicy is supported +*/}} +{{- define "common.capabilities.psp.supported" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if or (empty $kubeVersion) (semverCompare "<1.25-0" $kubeVersion) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if AdmissionConfiguration is supported +*/}} +{{- define "common.capabilities.admissionConfiguration.supported" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if or (empty $kubeVersion) (not (semverCompare "<1.23-0" $kubeVersion)) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for AdmissionConfiguration. +*/}} +{{- define "common.capabilities.admissionConfiguration.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.23-0" $kubeVersion) -}} +{{- print "apiserver.config.k8s.io/v1alpha1" -}} +{{- else if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "apiserver.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiserver.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for PodSecurityConfiguration. +*/}} +{{- define "common.capabilities.podSecurityConfiguration.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.23-0" $kubeVersion) -}} +{{- print "pod-security.admission.config.k8s.io/v1alpha1" -}} +{{- else if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "pod-security.admission.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "pod-security.admission.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the used Helm version is 3.3+. +A way to check the used Helm version was not introduced until version 3.3.0 with .Capabilities.HelmVersion, which contains an additional "{}}" structure. +This check is introduced as a regexMatch instead of {{ if .Capabilities.HelmVersion }} because checking for the key HelmVersion in <3.3 results in a "interface not found" error. +**To be removed when the catalog's minimun Helm version is 3.3** +*/}} +{{- define "common.capabilities.supportsHelmVersion" -}} +{{- if regexMatch "{(v[0-9])*[^}]*}}$" (.Capabilities | toString ) }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/mssql/charts/common/templates/_compatibility.tpl b/backing-services/mssql/charts/common/templates/_compatibility.tpl new file mode 100644 index 0000000..a61588d --- /dev/null +++ b/backing-services/mssql/charts/common/templates/_compatibility.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return true if the detected platform is Openshift +Usage: +{{- include "common.compatibility.isOpenshift" . -}} +*/}} +{{- define "common.compatibility.isOpenshift" -}} +{{- if .Capabilities.APIVersions.Has "security.openshift.io/v1" -}} +{{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Render a compatible securityContext depending on the platform. By default it is maintained as it is. In other platforms like Openshift we remove default user/group values that do not work out of the box with the restricted-v1 SCC +Usage: +{{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) -}} +*/}} +{{- define "common.compatibility.renderSecurityContext" -}} +{{- $adaptedContext := .secContext -}} + +{{- if (((.context.Values.global).compatibility).openshift) -}} + {{- if or (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "force") (and (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "auto") (include "common.compatibility.isOpenshift" .context)) -}} + {{/* Remove incompatible user/group values that do not work in Openshift out of the box */}} + {{- $adaptedContext = omit $adaptedContext "fsGroup" "runAsUser" "runAsGroup" -}} + {{- if not .secContext.seLinuxOptions -}} + {{/* If it is an empty object, we remove it from the resulting context because it causes validation issues */}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{/* Remove empty seLinuxOptions object if global.compatibility.omitEmptySeLinuxOptions is set to true */}} +{{- if and (((.context.Values.global).compatibility).omitEmptySeLinuxOptions) (not .secContext.seLinuxOptions) -}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} +{{- end -}} +{{/* Remove fields that are disregarded when running the container in privileged mode */}} +{{- if $adaptedContext.privileged -}} + {{- $adaptedContext = omit $adaptedContext "capabilities" "seLinuxOptions" -}} +{{- end -}} +{{- omit $adaptedContext "enabled" | toYaml -}} +{{- end -}} diff --git a/backing-services/mssql/charts/common/templates/_errors.tpl b/backing-services/mssql/charts/common/templates/_errors.tpl new file mode 100644 index 0000000..e965365 --- /dev/null +++ b/backing-services/mssql/charts/common/templates/_errors.tpl @@ -0,0 +1,28 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Through error when upgrading using empty passwords values that must not be empty. + +Usage: +{{- $validationError00 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password00" "secret" "secretName" "field" "password-00") -}} +{{- $validationError01 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password01" "secret" "secretName" "field" "password-01") -}} +{{ include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $validationError00 $validationError01) "context" $) }} + +Required password params: + - validationErrors - String - Required. List of validation strings to be return, if it is empty it won't throw error. + - context - Context - Required. Parent context. +*/}} +{{- define "common.errors.upgrade.passwords.empty" -}} + {{- $validationErrors := join "" .validationErrors -}} + {{- if and $validationErrors .context.Release.IsUpgrade -}} + {{- $errorString := "\nPASSWORDS ERROR: You must provide your current passwords when upgrading the release." -}} + {{- $errorString = print $errorString "\n Note that even after reinstallation, old credentials may be needed as they may be kept in persistent volume claims." -}} + {{- $errorString = print $errorString "\n Further information can be obtained at https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues/#credential-errors-while-upgrading-chart-releases" -}} + {{- $errorString = print $errorString "\n%s" -}} + {{- printf $errorString $validationErrors | fail -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/mssql/charts/common/templates/_images.tpl b/backing-services/mssql/charts/common/templates/_images.tpl new file mode 100644 index 0000000..76bb7ce --- /dev/null +++ b/backing-services/mssql/charts/common/templates/_images.tpl @@ -0,0 +1,115 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Return the proper image name. +If image tag and digest are not defined, termination fallbacks to chart appVersion. +{{ include "common.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" .Values.global "chart" .Chart ) }} +*/}} +{{- define "common.images.image" -}} +{{- $registryName := default .imageRoot.registry ((.global).imageRegistry) -}} +{{- $repositoryName := .imageRoot.repository -}} +{{- $separator := ":" -}} +{{- $termination := .imageRoot.tag | toString -}} + +{{- if not .imageRoot.tag }} + {{- if .chart }} + {{- $termination = .chart.AppVersion | toString -}} + {{- end -}} +{{- end -}} +{{- if .imageRoot.digest }} + {{- $separator = "@" -}} + {{- $termination = .imageRoot.digest | toString -}} +{{- end -}} +{{- if $registryName }} + {{- printf "%s/%s%s%s" $registryName $repositoryName $separator $termination -}} +{{- else -}} + {{- printf "%s%s%s" $repositoryName $separator $termination -}} +{{- end -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead) +{{ include "common.images.pullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global) }} +*/}} +{{- define "common.images.pullSecrets" -}} + {{- $pullSecrets := list }} + + {{- range ((.global).imagePullSecrets) -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end }} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) -}} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names evaluating values as templates +{{ include "common.images.renderPullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $) }} +*/}} +{{- define "common.images.renderPullSecrets" -}} + {{- $pullSecrets := list }} + {{- $context := .context }} + + {{- range (($context.Values.global).imagePullSecrets) -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) -}} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper image version (ingores image revision/prerelease info & fallbacks to chart appVersion) +{{ include "common.images.version" ( dict "imageRoot" .Values.path.to.the.image "chart" .Chart ) }} +*/}} +{{- define "common.images.version" -}} +{{- $imageTag := .imageRoot.tag | toString -}} +{{/* regexp from https://github.com/Masterminds/semver/blob/23f51de38a0866c5ef0bfc42b3f735c73107b700/version.go#L41-L44 */}} +{{- if regexMatch `^([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?$` $imageTag -}} + {{- $version := semver $imageTag -}} + {{- printf "%d.%d.%d" $version.Major $version.Minor $version.Patch -}} +{{- else -}} + {{- print .chart.AppVersion -}} +{{- end -}} +{{- end -}} + diff --git a/backing-services/mssql/charts/common/templates/_ingress.tpl b/backing-services/mssql/charts/common/templates/_ingress.tpl new file mode 100644 index 0000000..7d2b879 --- /dev/null +++ b/backing-services/mssql/charts/common/templates/_ingress.tpl @@ -0,0 +1,73 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Generate backend entry that is compatible with all Kubernetes API versions. + +Usage: +{{ include "common.ingress.backend" (dict "serviceName" "backendName" "servicePort" "backendPort" "context" $) }} + +Params: + - serviceName - String. Name of an existing service backend + - servicePort - String/Int. Port name (or number) of the service. It will be translated to different yaml depending if it is a string or an integer. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.ingress.backend" -}} +{{- $apiVersion := (include "common.capabilities.ingress.apiVersion" .context) -}} +{{- if or (eq $apiVersion "extensions/v1beta1") (eq $apiVersion "networking.k8s.io/v1beta1") -}} +serviceName: {{ .serviceName }} +servicePort: {{ .servicePort }} +{{- else -}} +service: + name: {{ .serviceName }} + port: + {{- if typeIs "string" .servicePort }} + name: {{ .servicePort }} + {{- else if or (typeIs "int" .servicePort) (typeIs "float64" .servicePort) }} + number: {{ .servicePort | int }} + {{- end }} +{{- end -}} +{{- end -}} + +{{/* +Print "true" if the API pathType field is supported +Usage: +{{ include "common.ingress.supportsPathType" . }} +*/}} +{{- define "common.ingress.supportsPathType" -}} +{{- if (semverCompare "<1.18-0" (include "common.capabilities.kubeVersion" .)) -}} +{{- print "false" -}} +{{- else -}} +{{- print "true" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the ingressClassname field is supported +Usage: +{{ include "common.ingress.supportsIngressClassname" . }} +*/}} +{{- define "common.ingress.supportsIngressClassname" -}} +{{- if semverCompare "<1.18-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "false" -}} +{{- else -}} +{{- print "true" -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if cert-manager required annotations for TLS signed +certificates are set in the Ingress annotations +Ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations +Usage: +{{ include "common.ingress.certManagerRequest" ( dict "annotations" .Values.path.to.the.ingress.annotations ) }} +*/}} +{{- define "common.ingress.certManagerRequest" -}} +{{ if or (hasKey .annotations "cert-manager.io/cluster-issuer") (hasKey .annotations "cert-manager.io/issuer") (hasKey .annotations "kubernetes.io/tls-acme") }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/mssql/charts/common/templates/_labels.tpl b/backing-services/mssql/charts/common/templates/_labels.tpl new file mode 100644 index 0000000..0a0cc54 --- /dev/null +++ b/backing-services/mssql/charts/common/templates/_labels.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Kubernetes standard labels +{{ include "common.labels.standard" (dict "customLabels" .Values.commonLabels "context" $) -}} +*/}} +{{- define "common.labels.standard" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{- $default := dict "app.kubernetes.io/name" (include "common.names.name" .context) "helm.sh/chart" (include "common.names.chart" .context) "app.kubernetes.io/instance" .context.Release.Name "app.kubernetes.io/managed-by" .context.Release.Service -}} +{{- with .context.Chart.AppVersion -}} +{{- $_ := set $default "app.kubernetes.io/version" . -}} +{{- end -}} +{{ template "common.tplvalues.merge" (dict "values" (list .customLabels $default) "context" .context) }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +helm.sh/chart: {{ include "common.names.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Chart.AppVersion }} +app.kubernetes.io/version: {{ . | quote }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Labels used on immutable fields such as deploy.spec.selector.matchLabels or svc.spec.selector +{{ include "common.labels.matchLabels" (dict "customLabels" .Values.podLabels "context" $) -}} + +We don't want to loop over custom labels appending them to the selector +since it's very likely that it will break deployments, services, etc. +However, it's important to overwrite the standard labels if the user +overwrote them on metadata.labels fields. +*/}} +{{- define "common.labels.matchLabels" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{ merge (pick (include "common.tplvalues.render" (dict "value" .customLabels "context" .context) | fromYaml) "app.kubernetes.io/name" "app.kubernetes.io/instance") (dict "app.kubernetes.io/name" (include "common.names.name" .context) "app.kubernetes.io/instance" .context.Release.Name ) | toYaml }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} +{{- end -}} diff --git a/backing-services/mssql/charts/common/templates/_names.tpl b/backing-services/mssql/charts/common/templates/_names.tpl new file mode 100644 index 0000000..ba83956 --- /dev/null +++ b/backing-services/mssql/charts/common/templates/_names.tpl @@ -0,0 +1,71 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "common.names.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "common.names.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "common.names.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 dependency name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +Usage: +{{ include "common.names.dependency.fullname" (dict "chartName" "dependency-chart-name" "chartValues" .Values.dependency-chart "context" $) }} +*/}} +{{- define "common.names.dependency.fullname" -}} +{{- if .chartValues.fullnameOverride -}} +{{- .chartValues.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .chartName .chartValues.nameOverride -}} +{{- if contains $name .context.Release.Name -}} +{{- .context.Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .context.Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts. +*/}} +{{- define "common.names.namespace" -}} +{{- default .Release.Namespace .Values.namespaceOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a fully qualified app name adding the installation's namespace. +*/}} +{{- define "common.names.fullname.namespace" -}} +{{- printf "%s-%s" (include "common.names.fullname" .) (include "common.names.namespace" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/backing-services/mssql/charts/common/templates/_resources.tpl b/backing-services/mssql/charts/common/templates/_resources.tpl new file mode 100644 index 0000000..d8a43e1 --- /dev/null +++ b/backing-services/mssql/charts/common/templates/_resources.tpl @@ -0,0 +1,50 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a resource request/limit object based on a given preset. +These presets are for basic testing and not meant to be used in production +{{ include "common.resources.preset" (dict "type" "nano") -}} +*/}} +{{- define "common.resources.preset" -}} +{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} +{{- $presets := dict + "nano" (dict + "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "2Gi") + ) + "micro" (dict + "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "2Gi") + ) + "small" (dict + "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "2Gi") + ) + "medium" (dict + "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "2Gi") + ) + "large" (dict + "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "2Gi") + ) + "xlarge" (dict + "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "2Gi") + ) + "2xlarge" (dict + "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "2Gi") + ) + }} +{{- if hasKey $presets .type -}} +{{- index $presets .type | toYaml -}} +{{- else -}} +{{- printf "ERROR: Preset key '%s' invalid. Allowed values are %s" .type (join "," (keys $presets)) | fail -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/mssql/charts/common/templates/_secrets.tpl b/backing-services/mssql/charts/common/templates/_secrets.tpl new file mode 100644 index 0000000..801918c --- /dev/null +++ b/backing-services/mssql/charts/common/templates/_secrets.tpl @@ -0,0 +1,185 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Generate secret name. + +Usage: +{{ include "common.secrets.name" (dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $) }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - defaultNameSuffix - String - Optional. It is used only if we have several secrets in the same deployment. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.secrets.name" -}} +{{- $name := (include "common.names.fullname" .context) -}} + +{{- if .defaultNameSuffix -}} +{{- $name = printf "%s-%s" $name .defaultNameSuffix | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- with .existingSecret -}} +{{- if not (typeIs "string" .) -}} +{{- with .name -}} +{{- $name = . -}} +{{- end -}} +{{- else -}} +{{- $name = . -}} +{{- end -}} +{{- end -}} + +{{- printf "%s" $name -}} +{{- end -}} + +{{/* +Generate secret key. + +Usage: +{{ include "common.secrets.key" (dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName") }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - key - String - Required. Name of the key in the secret. +*/}} +{{- define "common.secrets.key" -}} +{{- $key := .key -}} + +{{- if .existingSecret -}} + {{- if not (typeIs "string" .existingSecret) -}} + {{- if .existingSecret.keyMapping -}} + {{- $key = index .existingSecret.keyMapping $.key -}} + {{- end -}} + {{- end }} +{{- end -}} + +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Generate secret password or retrieve one if already created. + +Usage: +{{ include "common.secrets.passwords.manage" (dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - providedValues - List - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - length - int - Optional - Length of the generated random password. + - strong - Boolean - Optional - Whether to add symbols to the generated random password. + - chartName - String - Optional - Name of the chart used when said chart is deployed as a subchart. + - context - Context - Required - Parent context. + - failOnNew - Boolean - Optional - Default to true. If set to false, skip errors adding new keys to existing secrets. + - skipB64enc - Boolean - Optional - Default to false. If set to true, no the secret will not be base64 encrypted. + - skipQuote - Boolean - Optional - Default to false. If set to true, no quotes will be added around the secret. +The order in which this function returns a secret password: + 1. Already existing 'Secret' resource + (If a 'Secret' resource is found under the name provided to the 'secret' parameter to this function and that 'Secret' resource contains a key with the name passed as the 'key' parameter to this function then the value of this existing secret password will be returned) + 2. Password provided via the values.yaml + (If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned) + 3. Randomly generated secret password + (A new random secret password with the length specified in the 'length' parameter will be generated and returned) + +*/}} +{{- define "common.secrets.passwords.manage" -}} + +{{- $password := "" }} +{{- $subchart := "" }} +{{- $chartName := default "" .chartName }} +{{- $passwordLength := default 10 .length }} +{{- $providedPasswordKey := include "common.utils.getKeyFromList" (dict "keys" .providedValues "context" $.context) }} +{{- $providedPasswordValue := include "common.utils.getValueFromKey" (dict "key" $providedPasswordKey "context" $.context) }} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data }} +{{- if $secretData }} + {{- if hasKey $secretData .key }} + {{- $password = index $secretData .key | b64dec }} + {{- else if not (eq .failOnNew false) }} + {{- printf "\nPASSWORDS ERROR: The secret \"%s\" does not contain the key \"%s\"\n" .secret .key | fail -}} + {{- end -}} +{{- end }} + +{{- if not $password }} + {{- if $providedPasswordValue }} + {{- $password = $providedPasswordValue | toString }} + {{- else }} + {{- if .context.Values.enabled }} + {{- $subchart = $chartName }} + {{- end -}} + + {{- if not (eq .failOnNew false) }} + {{- $requiredPassword := dict "valueKey" $providedPasswordKey "secret" .secret "field" .key "subchart" $subchart "context" $.context -}} + {{- $requiredPasswordError := include "common.validations.values.single.empty" $requiredPassword -}} + {{- $passwordValidationErrors := list $requiredPasswordError -}} + {{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" $passwordValidationErrors "context" $.context) -}} + {{- end }} + + {{- if .strong }} + {{- $subStr := list (lower (randAlpha 1)) (randNumeric 1) (upper (randAlpha 1)) | join "_" }} + {{- $password = randAscii $passwordLength }} + {{- $password = regexReplaceAllLiteral "\\W" $password "@" | substr 5 $passwordLength }} + {{- $password = printf "%s%s" $subStr $password | toString | shuffle }} + {{- else }} + {{- $password = randAlphaNum $passwordLength }} + {{- end }} + {{- end -}} +{{- end -}} +{{- if not .skipB64enc }} +{{- $password = $password | b64enc }} +{{- end -}} +{{- if .skipQuote -}} +{{- printf "%s" $password -}} +{{- else -}} +{{- printf "%s" $password | quote -}} +{{- end -}} +{{- end -}} + +{{/* +Reuses the value from an existing secret, otherwise sets its value to a default value. + +Usage: +{{ include "common.secrets.lookup" (dict "secret" "secret-name" "key" "keyName" "defaultValue" .Values.myValue "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - defaultValue - String - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - context - Context - Required - Parent context. + +*/}} +{{- define "common.secrets.lookup" -}} +{{- $value := "" -}} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data -}} +{{- if and $secretData (hasKey $secretData .key) -}} + {{- $value = index $secretData .key -}} +{{- else if .defaultValue -}} + {{- $value = .defaultValue | toString | b64enc -}} +{{- end -}} +{{- if $value -}} +{{- printf "%s" $value -}} +{{- end -}} +{{- end -}} + +{{/* +Returns whether a previous generated secret already exists + +Usage: +{{ include "common.secrets.exists" (dict "secret" "secret-name" "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - context - Context - Required - Parent context. +*/}} +{{- define "common.secrets.exists" -}} +{{- $secret := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret) }} +{{- if $secret }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/mssql/charts/common/templates/_storage.tpl b/backing-services/mssql/charts/common/templates/_storage.tpl new file mode 100644 index 0000000..aa75856 --- /dev/null +++ b/backing-services/mssql/charts/common/templates/_storage.tpl @@ -0,0 +1,21 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the proper Storage Class +{{ include "common.storage.class" ( dict "persistence" .Values.path.to.the.persistence "global" $) }} +*/}} +{{- define "common.storage.class" -}} +{{- $storageClass := (.global).storageClass | default .persistence.storageClass | default (.global).defaultStorageClass | default "" -}} +{{- if $storageClass -}} + {{- if (eq "-" $storageClass) -}} + {{- printf "storageClassName: \"\"" -}} + {{- else -}} + {{- printf "storageClassName: %s" $storageClass -}} + {{- end -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/mssql/charts/common/templates/_tplvalues.tpl b/backing-services/mssql/charts/common/templates/_tplvalues.tpl new file mode 100644 index 0000000..c84d72c --- /dev/null +++ b/backing-services/mssql/charts/common/templates/_tplvalues.tpl @@ -0,0 +1,38 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Renders a value that contains template perhaps with scope if the scope is present. +Usage: +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ ) }} +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ "scope" $app ) }} +*/}} +{{- define "common.tplvalues.render" -}} +{{- $value := typeIs "string" .value | ternary .value (.value | toYaml) }} +{{- if contains "{{" (toJson .value) }} + {{- if .scope }} + {{- tpl (cat "{{- with $.RelativeScope -}}" $value "{{- end }}") (merge (dict "RelativeScope" .scope) .context) }} + {{- else }} + {{- tpl $value .context }} + {{- end }} +{{- else }} + {{- $value }} +{{- end }} +{{- end -}} + +{{/* +Merge a list of values that contains template after rendering them. +Merge precedence is consistent with http://masterminds.github.io/sprig/dicts.html#merge-mustmerge +Usage: +{{ include "common.tplvalues.merge" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }} +*/}} +{{- define "common.tplvalues.merge" -}} +{{- $dst := dict -}} +{{- range .values -}} +{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | merge $dst -}} +{{- end -}} +{{ $dst | toYaml }} +{{- end -}} diff --git a/backing-services/mssql/charts/common/templates/_utils.tpl b/backing-services/mssql/charts/common/templates/_utils.tpl new file mode 100644 index 0000000..d53c74a --- /dev/null +++ b/backing-services/mssql/charts/common/templates/_utils.tpl @@ -0,0 +1,77 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Print instructions to get a secret value. +Usage: +{{ include "common.utils.secret.getvalue" (dict "secret" "secret-name" "field" "secret-value-field" "context" $) }} +*/}} +{{- define "common.utils.secret.getvalue" -}} +{{- $varname := include "common.utils.fieldToEnvVar" . -}} +export {{ $varname }}=$(kubectl get secret --namespace {{ include "common.names.namespace" .context | quote }} {{ .secret }} -o jsonpath="{.data.{{ .field }}}" | base64 -d) +{{- end -}} + +{{/* +Build env var name given a field +Usage: +{{ include "common.utils.fieldToEnvVar" dict "field" "my-password" }} +*/}} +{{- define "common.utils.fieldToEnvVar" -}} + {{- $fieldNameSplit := splitList "-" .field -}} + {{- $upperCaseFieldNameSplit := list -}} + + {{- range $fieldNameSplit -}} + {{- $upperCaseFieldNameSplit = append $upperCaseFieldNameSplit ( upper . ) -}} + {{- end -}} + + {{ join "_" $upperCaseFieldNameSplit }} +{{- end -}} + +{{/* +Gets a value from .Values given +Usage: +{{ include "common.utils.getValueFromKey" (dict "key" "path.to.key" "context" $) }} +*/}} +{{- define "common.utils.getValueFromKey" -}} +{{- $splitKey := splitList "." .key -}} +{{- $value := "" -}} +{{- $latestObj := $.context.Values -}} +{{- range $splitKey -}} + {{- if not $latestObj -}} + {{- printf "please review the entire path of '%s' exists in values" $.key | fail -}} + {{- end -}} + {{- $value = ( index $latestObj . ) -}} + {{- $latestObj = $value -}} +{{- end -}} +{{- printf "%v" (default "" $value) -}} +{{- end -}} + +{{/* +Returns first .Values key with a defined value or first of the list if all non-defined +Usage: +{{ include "common.utils.getKeyFromList" (dict "keys" (list "path.to.key1" "path.to.key2") "context" $) }} +*/}} +{{- define "common.utils.getKeyFromList" -}} +{{- $key := first .keys -}} +{{- $reverseKeys := reverse .keys }} +{{- range $reverseKeys }} + {{- $value := include "common.utils.getValueFromKey" (dict "key" . "context" $.context ) }} + {{- if $value -}} + {{- $key = . }} + {{- end -}} +{{- end -}} +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Checksum a template at "path" containing a *single* resource (ConfigMap,Secret) for use in pod annotations, excluding the metadata (see #18376). +Usage: +{{ include "common.utils.checksumTemplate" (dict "path" "/configmap.yaml" "context" $) }} +*/}} +{{- define "common.utils.checksumTemplate" -}} +{{- $obj := include (print .context.Template.BasePath .path) .context | fromYaml -}} +{{ omit $obj "apiVersion" "kind" "metadata" | toYaml | sha256sum }} +{{- end -}} diff --git a/backing-services/mssql/charts/common/templates/_warnings.tpl b/backing-services/mssql/charts/common/templates/_warnings.tpl new file mode 100644 index 0000000..e4dbecd --- /dev/null +++ b/backing-services/mssql/charts/common/templates/_warnings.tpl @@ -0,0 +1,109 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Warning about using rolling tag. +Usage: +{{ include "common.warnings.rollingTag" .Values.path.to.the.imageRoot }} +*/}} +{{- define "common.warnings.rollingTag" -}} + +{{- if and (contains "bitnami/" .repository) (not (.tag | toString | regexFind "-r\\d+$|sha256:")) }} +WARNING: Rolling tag detected ({{ .repository }}:{{ .tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. ++info https://docs.vmware.com/en/VMware-Tanzu-Application-Catalog/services/tutorials/GUID-understand-rolling-tags-containers-index.html +{{- end }} +{{- end -}} + +{{/* +Warning about replaced images from the original. +Usage: +{{ include "common.warnings.modifiedImages" (dict "images" (list .Values.path.to.the.imageRoot) "context" $) }} +*/}} +{{- define "common.warnings.modifiedImages" -}} +{{- $affectedImages := list -}} +{{- $printMessage := false -}} +{{- $originalImages := .context.Chart.Annotations.images -}} +{{- range .images -}} + {{- $fullImageName := printf (printf "%s/%s:%s" .registry .repository .tag) -}} + {{- if not (contains $fullImageName $originalImages) }} + {{- $affectedImages = append $affectedImages (printf "%s/%s:%s" .registry .repository .tag) -}} + {{- $printMessage = true -}} + {{- end -}} +{{- end -}} +{{- if $printMessage }} + +⚠ SECURITY WARNING: Original containers have been substituted. This Helm chart was designed, tested, and validated on multiple platforms using a specific set of Bitnami and Tanzu Application Catalog containers. Substituting other containers is likely to cause degraded security and performance, broken chart features, and missing environment variables. + +Substituted images detected: +{{- range $affectedImages }} + - {{ . }} +{{- end }} +{{- end -}} +{{- end -}} + +{{/* +Warning about not setting the resource object in all deployments. +Usage: +{{ include "common.warnings.resources" (dict "sections" (list "path1" "path2") context $) }} +Example: +{{- include "common.warnings.resources" (dict "sections" (list "csiProvider.provider" "server" "volumePermissions" "") "context" $) }} +The list in the example assumes that the following values exist: + - csiProvider.provider.resources + - server.resources + - volumePermissions.resources + - resources +*/}} +{{- define "common.warnings.resources" -}} +{{- $values := .context.Values -}} +{{- $printMessage := false -}} +{{ $affectedSections := list -}} +{{- range .sections -}} + {{- if eq . "" -}} + {{/* Case where the resources section is at the root (one main deployment in the chart) */}} + {{- if not (index $values "resources") -}} + {{- $affectedSections = append $affectedSections "resources" -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Case where the are multiple resources sections (more than one main deployment in the chart) */}} + {{- $keys := split "." . -}} + {{/* We iterate through the different levels until arriving to the resource section. Example: a.b.c.resources */}} + {{- $section := $values -}} + {{- range $keys -}} + {{- $section = index $section . -}} + {{- end -}} + {{- if not (index $section "resources") -}} + {{/* If the section has enabled=false or replicaCount=0, do not include it */}} + {{- if and (hasKey $section "enabled") -}} + {{- if index $section "enabled" -}} + {{/* enabled=true */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else if and (hasKey $section "replicaCount") -}} + {{/* We need a casting to int because number 0 is not treated as an int by default */}} + {{- if (gt (index $section "replicaCount" | int) 0) -}} + {{/* replicaCount > 0 */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Default case, add it to the affected sections */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- if $printMessage }} + +WARNING: There are "resources" sections in the chart not set. Using "resourcesPreset" is not recommended for production. For production installations, please set the following values according to your workload needs: +{{- range $affectedSections }} + - {{ . }} +{{- end }} ++info https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +{{- end -}} +{{- end -}} diff --git a/backing-services/mssql/charts/common/templates/validations/_cassandra.tpl b/backing-services/mssql/charts/common/templates/validations/_cassandra.tpl new file mode 100644 index 0000000..3f41ff8 --- /dev/null +++ b/backing-services/mssql/charts/common/templates/validations/_cassandra.tpl @@ -0,0 +1,77 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate Cassandra required passwords are not empty. + +Usage: +{{ include "common.validations.values.cassandra.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where Cassandra values are stored, e.g: "cassandra-passwords-secret" + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.cassandra.passwords" -}} + {{- $existingSecret := include "common.cassandra.values.existingSecret" . -}} + {{- $enabled := include "common.cassandra.values.enabled" . -}} + {{- $dbUserPrefix := include "common.cassandra.values.key.dbUser" . -}} + {{- $valueKeyPassword := printf "%s.password" $dbUserPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "cassandra-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.cassandra.values.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.cassandra.dbUser.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.dbUser.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled cassandra. + +Usage: +{{ include "common.cassandra.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.cassandra.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.cassandra.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key dbUser + +Usage: +{{ include "common.cassandra.values.key.dbUser" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.key.dbUser" -}} + {{- if .subchart -}} + cassandra.dbUser + {{- else -}} + dbUser + {{- end -}} +{{- end -}} diff --git a/backing-services/mssql/charts/common/templates/validations/_mariadb.tpl b/backing-services/mssql/charts/common/templates/validations/_mariadb.tpl new file mode 100644 index 0000000..6ea8c0f --- /dev/null +++ b/backing-services/mssql/charts/common/templates/validations/_mariadb.tpl @@ -0,0 +1,108 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MariaDB required passwords are not empty. + +Usage: +{{ include "common.validations.values.mariadb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MariaDB values are stored, e.g: "mysql-passwords-secret" + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mariadb.passwords" -}} + {{- $existingSecret := include "common.mariadb.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mariadb.values.enabled" . -}} + {{- $architecture := include "common.mariadb.values.architecture" . -}} + {{- $authPrefix := include "common.mariadb.values.key.auth" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mariadb-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- if not (empty $valueUsername) -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mariadb-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replication") -}} + {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mariadb-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mariadb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mariadb. + +Usage: +{{ include "common.mariadb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mariadb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mariadb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mariadb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mariadb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.key.auth" -}} + {{- if .subchart -}} + mariadb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/backing-services/mssql/charts/common/templates/validations/_mongodb.tpl b/backing-services/mssql/charts/common/templates/validations/_mongodb.tpl new file mode 100644 index 0000000..d4cd38c --- /dev/null +++ b/backing-services/mssql/charts/common/templates/validations/_mongodb.tpl @@ -0,0 +1,113 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MongoDB® required passwords are not empty. + +Usage: +{{ include "common.validations.values.mongodb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MongoDB® values are stored, e.g: "mongodb-passwords-secret" + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mongodb.passwords" -}} + {{- $existingSecret := include "common.mongodb.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mongodb.values.enabled" . -}} + {{- $authPrefix := include "common.mongodb.values.key.auth" . -}} + {{- $architecture := include "common.mongodb.values.architecture" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyDatabase := printf "%s.database" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicaSetKey := printf "%s.replicaSetKey" $authPrefix -}} + {{- $valueKeyAuthEnabled := printf "%s.enabled" $authPrefix -}} + + {{- $authEnabled := include "common.utils.getValueFromKey" (dict "key" $valueKeyAuthEnabled "context" .context) -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") (eq $authEnabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mongodb-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- $valueDatabase := include "common.utils.getValueFromKey" (dict "key" $valueKeyDatabase "context" .context) }} + {{- if and $valueUsername $valueDatabase -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mongodb-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replicaset") -}} + {{- $requiredReplicaSetKey := dict "valueKey" $valueKeyReplicaSetKey "secret" .secret "field" "mongodb-replica-set-key" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicaSetKey -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mongodb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDb is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mongodb. + +Usage: +{{ include "common.mongodb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mongodb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mongodb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mongodb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.key.auth" -}} + {{- if .subchart -}} + mongodb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mongodb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/mssql/charts/common/templates/validations/_mysql.tpl b/backing-services/mssql/charts/common/templates/validations/_mysql.tpl new file mode 100644 index 0000000..924812a --- /dev/null +++ b/backing-services/mssql/charts/common/templates/validations/_mysql.tpl @@ -0,0 +1,108 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MySQL required passwords are not empty. + +Usage: +{{ include "common.validations.values.mysql.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MySQL values are stored, e.g: "mysql-passwords-secret" + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mysql.passwords" -}} + {{- $existingSecret := include "common.mysql.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mysql.values.enabled" . -}} + {{- $architecture := include "common.mysql.values.architecture" . -}} + {{- $authPrefix := include "common.mysql.values.key.auth" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mysql-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- if not (empty $valueUsername) -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mysql-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replication") -}} + {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mysql-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mysql.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mysql. + +Usage: +{{ include "common.mysql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mysql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mysql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mysql.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mysql.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.key.auth" -}} + {{- if .subchart -}} + mysql.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/backing-services/mssql/charts/common/templates/validations/_postgresql.tpl b/backing-services/mssql/charts/common/templates/validations/_postgresql.tpl new file mode 100644 index 0000000..0fa0b14 --- /dev/null +++ b/backing-services/mssql/charts/common/templates/validations/_postgresql.tpl @@ -0,0 +1,134 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate PostgreSQL required passwords are not empty. + +Usage: +{{ include "common.validations.values.postgresql.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where postgresql values are stored, e.g: "postgresql-passwords-secret" + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.postgresql.passwords" -}} + {{- $existingSecret := include "common.postgresql.values.existingSecret" . -}} + {{- $enabled := include "common.postgresql.values.enabled" . -}} + {{- $valueKeyPostgresqlPassword := include "common.postgresql.values.key.postgressPassword" . -}} + {{- $valueKeyPostgresqlReplicationEnabled := include "common.postgresql.values.key.replicationPassword" . -}} + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + {{- $requiredPostgresqlPassword := dict "valueKey" $valueKeyPostgresqlPassword "secret" .secret "field" "postgresql-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlPassword -}} + + {{- $enabledReplication := include "common.postgresql.values.enabled.replication" . -}} + {{- if (eq $enabledReplication "true") -}} + {{- $requiredPostgresqlReplicationPassword := dict "valueKey" $valueKeyPostgresqlReplicationEnabled "secret" .secret "field" "postgresql-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to decide whether evaluate global values. + +Usage: +{{ include "common.postgresql.values.use.global" (dict "key" "key-of-global" "context" $) }} +Params: + - key - String - Required. Field to be evaluated within global, e.g: "existingSecret" +*/}} +{{- define "common.postgresql.values.use.global" -}} + {{- if .context.Values.global -}} + {{- if .context.Values.global.postgresql -}} + {{- index .context.Values.global.postgresql .key | quote -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.postgresql.values.existingSecret" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.existingSecret" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "existingSecret" "context" .context) -}} + + {{- if .subchart -}} + {{- default (.context.Values.postgresql.existingSecret | quote) $globalValue -}} + {{- else -}} + {{- default (.context.Values.existingSecret | quote) $globalValue -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled postgresql. + +Usage: +{{ include "common.postgresql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key postgressPassword. + +Usage: +{{ include "common.postgresql.values.key.postgressPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.postgressPassword" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "postgresqlUsername" "context" .context) -}} + + {{- if not $globalValue -}} + {{- if .subchart -}} + postgresql.postgresqlPassword + {{- else -}} + postgresqlPassword + {{- end -}} + {{- else -}} + global.postgresql.postgresqlPassword + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled.replication. + +Usage: +{{ include "common.postgresql.values.enabled.replication" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.enabled.replication" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.replication.enabled -}} + {{- else -}} + {{- printf "%v" .context.Values.replication.enabled -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key replication.password. + +Usage: +{{ include "common.postgresql.values.key.replicationPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.replicationPassword" -}} + {{- if .subchart -}} + postgresql.replication.password + {{- else -}} + replication.password + {{- end -}} +{{- end -}} diff --git a/backing-services/mssql/charts/common/templates/validations/_redis.tpl b/backing-services/mssql/charts/common/templates/validations/_redis.tpl new file mode 100644 index 0000000..f477825 --- /dev/null +++ b/backing-services/mssql/charts/common/templates/validations/_redis.tpl @@ -0,0 +1,81 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate Redis® required passwords are not empty. + +Usage: +{{ include "common.validations.values.redis.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where redis values are stored, e.g: "redis-passwords-secret" + - subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.redis.passwords" -}} + {{- $enabled := include "common.redis.values.enabled" . -}} + {{- $valueKeyPrefix := include "common.redis.values.keys.prefix" . -}} + {{- $standarizedVersion := include "common.redis.values.standarized.version" . }} + + {{- $existingSecret := ternary (printf "%s%s" $valueKeyPrefix "auth.existingSecret") (printf "%s%s" $valueKeyPrefix "existingSecret") (eq $standarizedVersion "true") }} + {{- $existingSecretValue := include "common.utils.getValueFromKey" (dict "key" $existingSecret "context" .context) }} + + {{- $valueKeyRedisPassword := ternary (printf "%s%s" $valueKeyPrefix "auth.password") (printf "%s%s" $valueKeyPrefix "password") (eq $standarizedVersion "true") }} + {{- $valueKeyRedisUseAuth := ternary (printf "%s%s" $valueKeyPrefix "auth.enabled") (printf "%s%s" $valueKeyPrefix "usePassword") (eq $standarizedVersion "true") }} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $useAuth := include "common.utils.getValueFromKey" (dict "key" $valueKeyRedisUseAuth "context" .context) -}} + {{- if eq $useAuth "true" -}} + {{- $requiredRedisPassword := dict "valueKey" $valueKeyRedisPassword "secret" .secret "field" "redis-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRedisPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled redis. + +Usage: +{{ include "common.redis.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.redis.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.redis.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right prefix path for the values + +Usage: +{{ include "common.redis.values.key.prefix" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false +*/}} +{{- define "common.redis.values.keys.prefix" -}} + {{- if .subchart -}}redis.{{- else -}}{{- end -}} +{{- end -}} + +{{/* +Checks whether the redis chart's includes the standarizations (version >= 14) + +Usage: +{{ include "common.redis.values.standarized.version" (dict "context" $) }} +*/}} +{{- define "common.redis.values.standarized.version" -}} + + {{- $standarizedAuth := printf "%s%s" (include "common.redis.values.keys.prefix" .) "auth" -}} + {{- $standarizedAuthValues := include "common.utils.getValueFromKey" (dict "key" $standarizedAuth "context" .context) }} + + {{- if $standarizedAuthValues -}} + {{- true -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/mssql/charts/common/templates/validations/_validations.tpl b/backing-services/mssql/charts/common/templates/validations/_validations.tpl new file mode 100644 index 0000000..7cdee61 --- /dev/null +++ b/backing-services/mssql/charts/common/templates/validations/_validations.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate values must not be empty. + +Usage: +{{- $validateValueConf00 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-01") -}} +{{ include "common.validations.values.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" +*/}} +{{- define "common.validations.values.multiple.empty" -}} + {{- range .required -}} + {{- include "common.validations.values.single.empty" (dict "valueKey" .valueKey "secret" .secret "field" .field "context" $.context) -}} + {{- end -}} +{{- end -}} + +{{/* +Validate a value must not be empty. + +Usage: +{{ include "common.validations.value.empty" (dict "valueKey" "mariadb.password" "secret" "secretName" "field" "my-password" "subchart" "subchart" "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" + - subchart - String - Optional - Name of the subchart that the validated password is part of. +*/}} +{{- define "common.validations.values.single.empty" -}} + {{- $value := include "common.utils.getValueFromKey" (dict "key" .valueKey "context" .context) }} + {{- $subchart := ternary "" (printf "%s." .subchart) (empty .subchart) }} + + {{- if not $value -}} + {{- $varname := "my-value" -}} + {{- $getCurrentValue := "" -}} + {{- if and .secret .field -}} + {{- $varname = include "common.utils.fieldToEnvVar" . -}} + {{- $getCurrentValue = printf " To get the current value:\n\n %s\n" (include "common.utils.secret.getvalue" .) -}} + {{- end -}} + {{- printf "\n '%s' must not be empty, please add '--set %s%s=$%s' to the command.%s" .valueKey $subchart .valueKey $varname $getCurrentValue -}} + {{- end -}} +{{- end -}} diff --git a/backing-services/mssql/charts/common/values.yaml b/backing-services/mssql/charts/common/values.yaml new file mode 100644 index 0000000..de2cac5 --- /dev/null +++ b/backing-services/mssql/charts/common/values.yaml @@ -0,0 +1,8 @@ +# Copyright Broadcom, Inc. All Rights Reserved. +# SPDX-License-Identifier: APACHE-2.0 + +## bitnami/common +## It is required by CI/CD tools and processes. +## @skip exampleValue +## +exampleValue: common-chart diff --git a/backing-services/mssql/files/scripts/entrypoint/restore.sh b/backing-services/mssql/files/scripts/entrypoint/restore.sh new file mode 100644 index 0000000..61586f6 --- /dev/null +++ b/backing-services/mssql/files/scripts/entrypoint/restore.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +{{- if .Values.backup.enabled }} +export database=$1; +export now=$2; + +if [ -z "$database" ]; then + echo ERROR Database name is not specified at the 1st argument + exit 1 +fi +if [ -z "$now" ]; then + echo "ERROR Backup time is not specified as 2nd argument" + exit 1 +fi + +backuppath={{ .Values.backup.persistence.mount }}/$database-$now.bak + +if [ -f "${backuppath}" ];then + echo INFO - DB $database Snapshot found! Restoring... +else + echo ERROR - No Snapshot Found under $backuppath + exit 1; +fi + +sqlcmd -C \ + -S {{ include "mssql.primary.fullname" . }}.{{ include "common.names.namespace" $ }}.svc.{{ .Values.clusterDomain }} \ + -U sa -P "$MSSQL_SA_PASSWORD" \ + -e -Q "RESTORE DATABASE $database FROM DISK = '$backuppath'" +{{- else }} +printf "WARN No restore script available because" +echo " .Values.backup.enabled is falsy when you deployed this helm chart" +{{- end }} \ No newline at end of file diff --git a/backing-services/mssql/files/sql/00_create_db_owner_user.sql b/backing-services/mssql/files/sql/00_create_db_owner_user.sql new file mode 100644 index 0000000..592d733 --- /dev/null +++ b/backing-services/mssql/files/sql/00_create_db_owner_user.sql @@ -0,0 +1,21 @@ +-- Credits for https://stackoverflow.com/a/52484134/747579 +{{- if .Values.auth.createLogin }} +USE [master] +GO +CREATE LOGIN [{{ .Values.auth.username }}] WITH PASSWORD=N'$(MSSQL_PASSWORD)' +GO +{{- end }} +{{- if .Values.auth.username }} +USE [master] +GO +CREATE USER [{{ .Values.auth.username }}] FOR LOGIN [{{ .Values.auth.username }}] +GO +{{- end }} + +{{- if and .Values.auth.database .Values.auth.username }} +USE [{{ .Values.auth.database }}] +GO +CREATE USER [{{ .Values.auth.username }}] FOR LOGIN [{{ .Values.auth.username }}] +ALTER ROLE db_owner ADD MEMBER [{{ .Values.auth.username }}] +GO +{{- end }} diff --git a/backing-services/mssql/symbon-stage-tavana.values.yaml b/backing-services/mssql/symbon-stage-tavana.values.yaml new file mode 100644 index 0000000..5780208 --- /dev/null +++ b/backing-services/mssql/symbon-stage-tavana.values.yaml @@ -0,0 +1,15 @@ +image: + registry: 45.159.150.146:4158 + repository: razzaghib/sqlserver + tag: latest +auth: + rootPassword: "Secret@123" + createDatabase: true + database: "database" + databaseCollate: Latin1_General_CI_AS + username: "sa" + password: "Secret@123" + +primary: + service: + type: NodePort \ No newline at end of file diff --git a/backing-services/mssql/templates/NOTES.txt b/backing-services/mssql/templates/NOTES.txt new file mode 100644 index 0000000..757391e --- /dev/null +++ b/backing-services/mssql/templates/NOTES.txt @@ -0,0 +1,44 @@ +Execute the following to get the administrator credentials: + + echo Username: sa + MSSQL_SA_PASSWORD=$(kubectl -n {{ include "common.names.namespace" . }} get secret {{ template "mssql.secretName" . }} -o jsonpath="{.data.mssql-root-password}" | base64 -d) + + +To connect to your database: + + 1. Run a pod that you can use as a client: + + kubectl -n {{ include "common.names.namespace" . }} run {{ include "common.names.fullname" . }}-client --rm --tty -i --restart='Never' --image {{ template "mssql.client.image" . }} --env MSSQL_SA_PASSWORD=$MSSQL_SA_PASSWORD --command -- bash + + 2. To connect to primary service (read/write): + + sqlcmd -C -S {{ include "mssql.primary.fullname" . }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }} -U sa -P "$MSSQL_SA_PASSWORD" + +{{- if eq .Values.architecture "replication" }} + + 3. To connect to secondary service (read-only): + + sqlcmd -C -S {{ include "mssql.secondary.fullname" . }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }} -U sa -P "$MSSQL_SA_PASSWORD" + +{{- end }} + + +{{- if not .Values.backup.persistence.enabled }} +################################################################################# +###### WARNING: Persistence is disabled for BACKUPs !!! ##### +###### !!! You will lose your backups when ##### +###### the primary pod is terminated. ##### +######## Check @param backup.persistence.enabled to metigate this ######## +################################################################################# +{{- end }} + + +################################################################################# +####################### DISCLAIMER ################################ +################################################################################# +BY DEPLOYING THIS HELM CHART, YOU ARE ACCEPTING THE END-USER Licensing Agreement + of Microsoft SQL Server: + https://go.microsoft.com/fwlink/?LinkId=746388 +IF YOU ARE NOT ACCEPTING THAT LICENSE, YOU MUST DELETE THIS RELEASE IMMEDIATELY: + # helm -n {{ .Release.Namespace }} delete {{ .Release.Name }} +################################################################################# \ No newline at end of file diff --git a/backing-services/mssql/templates/_helpers.tpl b/backing-services/mssql/templates/_helpers.tpl new file mode 100644 index 0000000..c9618c7 --- /dev/null +++ b/backing-services/mssql/templates/_helpers.tpl @@ -0,0 +1,161 @@ +{{/* vim: set filetype=mustache: */}} + +{{- define "mssql.primary.fullname" -}} +{{- if eq .Values.architecture "replication" }} +{{- printf "%s-%s" (include "common.names.fullname" .) .Values.primary.name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- include "common.names.fullname" . -}} +{{- end -}} +{{- end -}} + +{{- define "mssql.primary.hasVolumeClaims" -}} +{{- or (and .Values.primary.persistence.enabled (not .Values.primary.persistence.existingClaim)) (and .Values.backup.persistence.enabled (not .Values.backup.persistence.existingClaim)) -}} +{{- end -}} + +{{- define "mssql.secondary.fullname" -}} +{{- printf "%s-%s" (include "common.names.fullname" .) .Values.secondary.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Return the proper MSSQL image name +*/}} +{{- define "mssql.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) }} +{{- end -}} + + +{{/* +Return the proper MSSQL Client image name +*/}} +{{- define "mssql.client.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.client.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper metrics image name +*/}} +{{- define "mssql.metrics.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.metrics.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper image name (for the init container volume-permissions image) +*/}} +{{- define "mssql.volumePermissions.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.volumePermissions.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "mssql.imagePullSecrets" -}} +{{- include "common.images.pullSecrets" (dict "images" (list .Values.image .Values.metrics.image .Values.volumePermissions.image) "global" .Values.global) }} +{{- end -}} + +{{/* +Get the initialization scripts ConfigMap name. +*/}} +{{- define "mssql.initdbScriptsCM" -}} +{{- if .Values.initdbScriptsConfigMap -}} + {{- printf "%s" (tpl .Values.initdbScriptsConfigMap $) -}} +{{- else -}} + {{- printf "%s-init-scripts" (include "mssql.primary.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* + Returns the proper service account name depending if an explicit service account name is set + in the values file. If the name is not set it will default to either mssql.fullname if serviceAccount.create + is true or default otherwise. +*/}} +{{- define "mssql.serviceAccountName" -}} + {{- if .Values.serviceAccount.create -}} + {{ default (include "common.names.fullname" .) .Values.serviceAccount.name }} + {{- else -}} + {{ default "default" .Values.serviceAccount.name }} + {{- end -}} +{{- end -}} + +{{/* +Return the configmap with the MSSQL Primary configuration +*/}} +{{- define "mssql.primary.configmapName" -}} +{{- if .Values.primary.existingConfigmap -}} + {{- printf "%s" (tpl .Values.primary.existingConfigmap $) -}} +{{- else -}} + {{- printf "%s" (include "mssql.primary.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return the configmap with the MSSQL Primary configuration +*/}} +{{- define "mssql.secondary.configmapName" -}} +{{- if .Values.secondary.existingConfigmap -}} + {{- printf "%s" (tpl .Values.secondary.existingConfigmap $) -}} +{{- else -}} + {{- printf "%s" (include "mssql.secondary.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return the secret with MSSQL credentials +*/}} +{{- define "mssql.secretName" -}} + {{- if .Values.auth.existingSecret -}} + {{- printf "%s" (tpl .Values.auth.existingSecret $) -}} + {{- else -}} + {{- printf "%s" (include "common.names.fullname" .) -}} + {{- end -}} +{{- end -}} + +{{/* +Return true if a secret object should be created for MSSQL +*/}} +{{- define "mssql.createSecret" -}} +{{- if not .Values.auth.existingSecret }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Returns the available value for certain key in an existing secret (if it exists), +otherwise it generates a random value. +*/}} +{{- define "getValueFromSecret" }} + {{- $len := (default 16 .Length) | int -}} + {{- $obj := (lookup "v1" "Secret" .Namespace .Name).data -}} + {{- if $obj }} + {{- index $obj .Key | b64dec -}} + {{- else -}} + {{- randAlphaNum $len -}} + {{- end -}} +{{- end }} + +{{/* Check if there are rolling tags in the images */}} +{{- define "mssql.checkRollingTags" -}} +{{- include "common.warnings.rollingTag" .Values.image }} +{{- include "common.warnings.rollingTag" .Values.metrics.image }} +{{- include "common.warnings.rollingTag" .Values.volumePermissions.image }} +{{- end -}} + +{{/* +Compile all warnings into a single message, and call fail. +*/}} +{{- define "mssql.validateValues" -}} +{{- $messages := list -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}} +{{- end -}} +{{- end -}} + +{{/* +Compute all databases that requires backup +*/}} +{{- define "mssql.backup.databases" -}} +{{- $databases := prepend .Values.backup.databases .Values.auth.database }} +{{- $databases -}} +{{- end -}} \ No newline at end of file diff --git a/backing-services/mssql/templates/backup/cronjob.yaml b/backing-services/mssql/templates/backup/cronjob.yaml new file mode 100644 index 0000000..4c1992f --- /dev/null +++ b/backing-services/mssql/templates/backup/cronjob.yaml @@ -0,0 +1,77 @@ +{{- $databases := .Values.backup.databases -}} +{{- if .Values.backup.enabled }} +{{ range $_, $database := $databases }} +{{- $databaseKebab := (regexReplaceAll "\\W+" $database "-" | lower ) -}} +{{ $databaseKebab = (trimSuffix "-" $databaseKebab ) }} +{{ $databaseKebab = (regexReplaceAll "_" $databaseKebab "-" ) }} +--- +apiVersion: {{ include "common.capabilities.cronjob.apiVersion" $ }} +kind: CronJob +metadata: + name: {{ printf "%s-snapshotter-db-%s" (include "common.names.fullname" $) $databaseKebab }} + labels: {{- include "common.labels.standard" $ | nindent 4 }} + {{- if $.Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" $.Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + concurrencyPolicy: Forbid + schedule: {{ $.Values.backup.cronjob.schedule | quote }} + successfulJobsHistoryLimit: {{ $.Values.backup.cronjob.historyLimit }} + jobTemplate: + spec: + template: + metadata: + labels: {{- include "common.labels.standard" $ | nindent 12 }} + app.kubernetes.io/component: snapshotter + {{- if $.Values.backup.cronjob.podAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.backup.cronjob.podAnnotations "context" $) | nindent 12 }} + {{- end }} + spec: + {{- if $.Values.backup.cronjob.nodeSelector }} + nodeSelector: {{- toYaml $.Values.backup.cronjob.nodeSelector | nindent 12 }} + {{- end }} + {{- if $.Values.backup.cronjob.tolerations }} + tolerations: {{- toYaml $.Values.backup.cronjob.tolerations | nindent 12 }} + {{- end }} + {{- include "mssql.imagePullSecrets" $ | nindent 10 }} + restartPolicy: OnFailure + {{- if $.Values.backup.cronjob.podSecurityContext.enabled }} + securityContext: {{- omit $.Values.backup.cronjob.podSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + containers: + - name: mssql-snapshotter + image: {{ template "mssql.client.image" $ }} + imagePullPolicy: {{ $.Values.image.pullPolicy | quote }} + {{- if $.Values.backup.cronjob.containerSecurityContext.enabled }} + securityContext: {{- omit $.Values.backup.cronjob.containerSecurityContext "enabled" | toYaml | nindent 16 }} + {{- end }} + command: + - /bin/sh + - -c + - | + export now=$(date +%Y-%m-%d_%Hh%Mm%Ssec) + export database="{{ $database }}" + sqlcmd -C -S {{ include "mssql.primary.fullname" $ }}.{{ include "common.names.namespace" $ }}.svc.{{ $.Values.clusterDomain }} \ + -U sa -P "$MSSQL_SA_PASSWORD" \ + -e -Q \ + {{ (include "common.tplvalues.render" ( dict "value" $.Values.backup.cronjob.commandTemplate "context" $ )) | quote }} + + if [ "$?" = "0" ];then + echo "In the primary DB, restore this snapshot by running:" + echo "# bash /tmp/entrypoint-scripts/restore.sh $database $now" + fi + + env: + - name: MSSQL_SA_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "mssql.secretName" $ }} + key: mssql-root-password + {{- if $.Values.backup.cronjob.resources }} + resources: {{- toYaml $.Values.backup.cronjob.resources | nindent 16 }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/backing-services/mssql/templates/backup/persistentvolumeclaim.yaml b/backing-services/mssql/templates/backup/persistentvolumeclaim.yaml new file mode 100644 index 0000000..f03f244 --- /dev/null +++ b/backing-services/mssql/templates/backup/persistentvolumeclaim.yaml @@ -0,0 +1,30 @@ +{{- if and .Values.backup.persistence.enabled (not .Values.backup.persistence.existingClaim) }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ printf "backups-%s" (include "mssql.primary.fullname" .) }} + labels: {{ include "common.labels.matchLabels" . | nindent 4 }} + app.kubernetes.io/component: primary + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" (dict "value" .Values.commonLabels "context" $) | nindent 4 }} + {{- end }} + annotations: + {{- if .Values.backup.persistence.annotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.backup.persistence.annotations "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }} + {{- end }} +spec: + accessModes: + {{- range .Values.backup.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.backup.persistence.size | quote }} + {{- include "common.storage.class" (dict "persistence" .Values.backup.persistence "global" .Values.global) | nindent 2 }} + {{- if .Values.backup.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.backup.persistence.selector "context" $) | nindent 4 }} + {{- end -}} + {{- end }} \ No newline at end of file diff --git a/backing-services/mssql/templates/metrics-svc.yaml b/backing-services/mssql/templates/metrics-svc.yaml new file mode 100644 index 0000000..d370c62 --- /dev/null +++ b/backing-services/mssql/templates/metrics-svc.yaml @@ -0,0 +1,31 @@ + + +{{- if .Values.metrics.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-metrics" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + app.kubernetes.io/component: metrics + {{- if or .Values.metrics.service.annotations .Values.commonAnnotations }} + annotations: + {{- if .Values.metrics.service.annotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.service.annotations "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} +spec: + type: {{ .Values.metrics.service.type }} + ports: + - port: {{ .Values.metrics.service.port }} + targetPort: metrics + protocol: TCP + name: metrics + selector: {{- include "common.labels.matchLabels" $ | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/backing-services/mssql/templates/networkpolicy.yaml b/backing-services/mssql/templates/networkpolicy.yaml new file mode 100644 index 0000000..49b6813 --- /dev/null +++ b/backing-services/mssql/templates/networkpolicy.yaml @@ -0,0 +1,40 @@ +{{- if .Values.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ template "common.capabilities.networkPolicy.apiVersion" . }} +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + {{- include "common.labels.matchLabels" . | nindent 6 }} + ingress: + # Allow inbound connections + - ports: + - port: {{ .Values.primary.service.ports.mssql }} + {{- if not .Values.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: + {{ template "common.names.fullname" . }}-client: "true" + {{- if .Values.networkPolicy.explicitNamespacesSelector }} + namespaceSelector: +{{ toYaml .Values.networkPolicy.explicitNamespacesSelector | indent 12 }} + {{- end }} + - podSelector: + matchLabels: + {{- include "common.labels.matchLabels" . | nindent 14 }} + {{- end }} + {{- if .Values.metrics.enabled }} + # Allow prometheus scrapes + - ports: + - port: {{ .Values.metrics.service.port }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/backing-services/mssql/templates/primary/configmap.yaml b/backing-services/mssql/templates/primary/configmap.yaml new file mode 100644 index 0000000..392a9fa --- /dev/null +++ b/backing-services/mssql/templates/primary/configmap.yaml @@ -0,0 +1,34 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "mssql.primary.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: primary + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + # https://github.com/microsoft/mssql-docker/blob/master/linux/sample-helm-chart/templates/mssqlconfig.yaml + # More params: https://github.com/Microdust/mssqlserver-docker/blob/master/mssql.conf + mssql.conf: | + [EULA] + accepteula = Y + accepteulaml = Y + + [coredump] + captureminiandfull = true + coredumptype = full + + [hadr] + hadrenabled = 1 + + [language] + lcid = 1033 + + [filelocation] + defaultdatadir = {{ .Values.primary.persistence.mount }} + defaultlogdir = /var/opt/mssql/log \ No newline at end of file diff --git a/backing-services/mssql/templates/primary/initialization-configmap.yaml b/backing-services/mssql/templates/primary/initialization-configmap.yaml new file mode 100644 index 0000000..e901644 --- /dev/null +++ b/backing-services/mssql/templates/primary/initialization-configmap.yaml @@ -0,0 +1,19 @@ +{{- if or .Values.auth.database (and .Values.initdbScripts (not .Values.initdbScriptsConfigMap)) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-init-scripts" (include "mssql.primary.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: primary + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: +{{- if .Values.auth.username }} +{{ (tpl (.Files.Glob "files/sql/00_create_db_owner_user.sql").AsConfig .) | indent 2}} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/backing-services/mssql/templates/primary/pdb.yaml b/backing-services/mssql/templates/primary/pdb.yaml new file mode 100644 index 0000000..261b5ec --- /dev/null +++ b/backing-services/mssql/templates/primary/pdb.yaml @@ -0,0 +1,25 @@ +{{- if .Values.primary.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "mssql.primary.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: primary + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.primary.pdb.minAvailable }} + minAvailable: {{ .Values.primary.pdb.minAvailable }} + {{- end }} + {{- if .Values.primary.pdb.maxUnavailable }} + maxUnavailable: {{ .Values.primary.pdb.maxUnavailable }} + {{- end }} + selector: + matchLabels: {{ include "common.labels.matchLabels" . | nindent 6 }} + app.kubernetes.io/component: primary +{{- end }} \ No newline at end of file diff --git a/backing-services/mssql/templates/primary/statefulset.yaml b/backing-services/mssql/templates/primary/statefulset.yaml new file mode 100644 index 0000000..e46ddac --- /dev/null +++ b/backing-services/mssql/templates/primary/statefulset.yaml @@ -0,0 +1,324 @@ +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ include "mssql.primary.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: primary + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + replicas: 1 + podManagementPolicy: {{ .Values.primary.podManagementPolicy | quote }} + selector: + matchLabels: {{ include "common.labels.matchLabels" . | nindent 6 }} + app.kubernetes.io/component: primary + serviceName: {{ include "mssql.primary.fullname" . }} + {{- if .Values.primary.updateStrategy }} + updateStrategy: {{- toYaml .Values.primary.updateStrategy | nindent 4 }} + {{- end }} + template: + metadata: + annotations: + checksum/configuration: {{ include (print $.Template.BasePath "/primary/configmap.yaml") . | sha256sum }} + {{- if .Values.primary.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.podAnnotations "context" $) | nindent 8 }} + {{- end }} + labels: {{- include "common.labels.standard" . | nindent 8 }} + app.kubernetes.io/component: primary + {{- if .Values.primary.podLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.podLabels "context" $ ) | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ template "mssql.serviceAccountName" . }} + {{- include "mssql.imagePullSecrets" . | nindent 6 }} + {{- if .Values.primary.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.primary.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.primary.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.primary.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.primary.podAffinityPreset "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.primary.podAntiAffinityPreset "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.primary.nodeAffinityPreset.type "key" .Values.primary.nodeAffinityPreset.key "values" .Values.primary.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.primary.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.primary.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.primary.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.primary.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.primary.priorityClassName }} + priorityClassName: {{ .Values.primary.priorityClassName | quote }} + {{- end }} + {{- if .Values.primary.schedulerName }} + schedulerName: {{ .Values.primary.schedulerName | quote }} + {{- end }} + {{- if .Values.primary.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.primary.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.primary.podSecurityContext.enabled }} + securityContext: {{- omit .Values.primary.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.primary.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.primary.terminationGracePeriodSeconds }} + {{- end }} + initContainers: + {{- if and .Values.primary.podSecurityContext.enabled .Values.volumePermissions.enabled .Values.primary.persistence.enabled }} + - name: volume-permissions + image: {{ include "mssql.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + - -ec + - | + mkdir -p "{{ .Values.primary.persistence.mount }}" "{{ .Values.backup.persistence.mount }}" + chown "{{ .Values.primary.containerSecurityContext.runAsUser }}:{{ .Values.primary.podSecurityContext.fsGroup }}" "{{ .Values.primary.persistence.mount }}" "{{ .Values.backup.persistence.mount }}" + find "{{ .Values.primary.persistence.mount }}" -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | xargs -r chown -R "{{ .Values.primary.containerSecurityContext.runAsUser }}:{{ .Values.primary.podSecurityContext.fsGroup }}" + find "{{ .Values.backup.persistence.mount }}" -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | xargs -r chown -R "{{ .Values.primary.containerSecurityContext.runAsUser }}:{{ .Values.primary.podSecurityContext.fsGroup }}" + securityContext: + runAsUser: 0 + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: data + mountPath: {{ .Values.primary.persistence.mount }} + - name: backup + mountPath: {{ .Values.backup.persistence.mount }} + {{- end }} + {{- if .Values.primary.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.initContainers "context" $) | nindent 8 }} + {{- end }} + containers: + - name: mssql + image: {{ include "mssql.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.primary.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.primary.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.primary.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.primary.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + env: + # https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-configure-environment-variables?view=sql-server-ver16 + - name: ACCEPT_EULA + value: "Y" + - name: SQLCMD_ACCEPT_EULA + value: "YES" + - name: MSSQL_PID + value: {{ .Values.edition }} + - name: MSSQL_TCP_PORT + value: {{ .Values.primary.service.ports.mssql | quote }} + - name: MSSQL_SA_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "mssql.secretName" . }} + key: mssql-root-password + {{- if not (empty .Values.auth.username) }} + - name: MSSQL_USER + value: {{ .Values.auth.username | quote }} + - name: MSSQL_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "mssql.secretName" . }} + key: mssql-password + - name: SQLCMDPASSWORD + valueFrom: + secretKeyRef: + name: {{ template "mssql.secretName" . }} + key: mssql-password + {{- end }} + {{- if and .Values.auth.createDatabase .Values.auth.database }} + - name: MSSQL_DATABASE + value: {{ .Values.auth.database | quote }} + - name: MSSQL_DATABASE_COLLATE + value: {{ .Values.auth.databaseCollate | quote }} + {{- end }} + - name: MSSQL_COLLATION + value: {{ .Values.auth.databaseCollate | quote }} + - name: MSSQL_DATA_DIR + value: {{ .Values.primary.persistence.mount }} + - name: MSSQL_BACKUP_DIR + value: {{ .Values.backup.persistence.mount }} + {{- if eq .Values.architecture "replication" }} + - name: MSSQL_REPLICATION_MODE + value: "master" + - name: MSSQL_REPLICATION_USER + value: {{ .Values.auth.replicationUser | quote }} + - name: MSSQL_REPLICATION_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "mssql.secretName" . }} + key: mssql-replication-password + {{- end }} + {{- if .Values.primary.extraFlags }} + - name: MSSQL_EXTRA_FLAGS + value: "{{ .Values.primary.extraFlags }}" + {{- end }} + {{- if .Values.primary.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.primary.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.primary.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.primary.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.primary.extraEnvVarsSecret "context" $) }} + {{- end }} + ports: + - name: mssql + containerPort: {{ .Values.primary.service.ports.mssql }} + {{- if .Values.primary.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.primary.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bin/bash + - -ec + - | + sqlcmd -C -S localhost -U sa -P "$MSSQL_SA_PASSWORD" -Q "SELECT 1" + {{- end }} + {{- if .Values.primary.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.primary.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bin/bash + - -ec + - | + sqlcmd -C -S localhost -U sa -P "$MSSQL_SA_PASSWORD" -Q "USE {{ .Values.auth.database }}" + {{- end }} + {{- if .Values.primary.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.primary.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bin/bash + - -ec + - | + sqlcmd -C -S localhost -U sa -P "$MSSQL_SA_PASSWORD" -Q "USE {{ .Values.auth.database }}" + {{- end }} + {{- if .Values.primary.resources }} + resources: {{ toYaml .Values.primary.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: data + mountPath: {{ .Values.primary.persistence.mount }} + - name: backup + mountPath: {{ .Values.backup.persistence.mount }} + - name: init-scripts-configmap + mountPath: /tmp/init-scripts-configmap + {{- if or .Values.primary.configuration .Values.primary.existingConfigmap }} + - name: config + mountPath: /var/opt/mssql/mssql.conf + subPath: mssql.conf + {{- end }} + {{- if .Values.primary.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ include "mssql.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + env: + - name: SERVER + value: localhost + - name: PORT + value: {{ .Values.primary.service.ports.mssql | quote }} + - name: USERNAME + value: sa + - name: PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mssql.secretName" . }} + key: mssql-root-password + ports: + - name: metrics + containerPort: {{ .Values.metrics.service.port }} + {{- if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- omit .Values.metrics.livenessProbe "enabled" | toYaml | nindent 12 }} + httpGet: + path: /metrics + port: metrics + {{- end }} + {{- if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- omit .Values.metrics.readinessProbe "enabled" | toYaml | nindent 12 }} + httpGet: + path: /metrics + port: metrics + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.primary.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + {{- if or .Values.primary.configuration .Values.primary.existingConfigmap }} + - name: config + configMap: + name: {{ include "mssql.primary.configmapName" . }} + {{- end }} + - name: init-scripts-configmap + configMap: + name: {{ printf "%s-init-scripts" (include "mssql.primary.fullname" .) }} + {{- if .Values.primary.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.extraVolumes "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.primary.persistence.enabled .Values.primary.persistence.existingClaim }} + - name: data + persistentVolumeClaim: + claimName: {{ tpl .Values.primary.persistence.existingClaim . }} + {{- else if not .Values.primary.persistence.enabled }} + - name: data + emptyDir: {} + {{- end }} + {{- if and .Values.backup.persistence.enabled .Values.backup.persistence.existingClaim }} + - name: backup + persistentVolumeClaim: + claimName: {{ tpl .Values.backup.persistence.existingClaim . }} + {{- else if and .Values.backup.persistence.enabled (not .Values.backup.persistence.existingClaim)}} + - name: backup + persistentVolumeClaim: + claimName: {{ printf "backups-%s" (include "mssql.primary.fullname" .) }} + {{- else if not .Values.backup.persistence.enabled }} + - name: backup + emptyDir: {} + {{- end }} + {{- if (include "mssql.primary.hasVolumeClaims" .) }} + volumeClaimTemplates: + {{- end }} + {{- if and .Values.primary.persistence.enabled (not .Values.primary.persistence.existingClaim) }} + - metadata: + name: data + labels: {{ include "common.labels.matchLabels" . | nindent 10 }} + app.kubernetes.io/component: primary + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" (dict "value" .Values.commonLabels "context" $) | nindent 10 }} + {{- end }} + annotations: + {{- if .Values.primary.persistence.annotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.persistence.annotations "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.primary.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.primary.persistence.size | quote }} + {{- include "common.storage.class" ( dict "persistence" .Values.primary.persistence ) | nindent 8 }} + {{- if .Values.primary.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.primary.persistence.selector "context" $) | nindent 10 }} + {{- end -}} + {{- end }} diff --git a/backing-services/mssql/templates/primary/svc-headless.yaml b/backing-services/mssql/templates/primary/svc-headless.yaml new file mode 100644 index 0000000..c20be7b --- /dev/null +++ b/backing-services/mssql/templates/primary/svc-headless.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mssql.primary.fullname" . }}-headless + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: primary + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + annotations: + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + publishNotReadyAddresses: true + ports: + - name: mssql + port: {{ .Values.primary.service.ports.mssql }} + targetPort: mssql + selector: {{ include "common.labels.matchLabels" . | nindent 4 }} + app.kubernetes.io/component: primary \ No newline at end of file diff --git a/backing-services/mssql/templates/primary/svc.yaml b/backing-services/mssql/templates/primary/svc.yaml new file mode 100644 index 0000000..60984f0 --- /dev/null +++ b/backing-services/mssql/templates/primary/svc.yaml @@ -0,0 +1,52 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mssql.primary.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: primary + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + annotations: + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.primary.service.annotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.service.annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.primary.service.type }} + {{- if and .Values.primary.service.clusterIP (eq .Values.primary.service.type "ClusterIP") }} + clusterIP: {{ .Values.primary.service.clusterIP }} + {{- end }} + {{- if .Values.primary.service.sessionAffinity }} + sessionAffinity: {{ .Values.primary.service.sessionAffinity }} + {{- end }} + {{- if .Values.primary.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.primary.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + {{- if or (eq .Values.primary.service.type "LoadBalancer") (eq .Values.primary.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.primary.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.primary.service.type "LoadBalancer") (not (empty .Values.primary.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ .Values.primary.service.loadBalancerSourceRanges }} + {{- end }} + {{- if and (eq .Values.primary.service.type "LoadBalancer") (not (empty .Values.primary.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.primary.service.loadBalancerIP }} + {{- end }} + ports: + - name: mssql + port: {{ .Values.primary.service.ports.mssql }} + protocol: TCP + targetPort: mssql + {{- if (and (or (eq .Values.primary.service.type "NodePort") (eq .Values.primary.service.type "LoadBalancer")) .Values.primary.service.nodePorts.mssql) }} + nodePort: {{ .Values.primary.service.nodePorts.mssql }} + {{- else if eq .Values.primary.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.primary.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + selector: {{ include "common.labels.matchLabels" . | nindent 4 }} + app.kubernetes.io/component: primary \ No newline at end of file diff --git a/backing-services/mssql/templates/rolebinding.yaml b/backing-services/mssql/templates/rolebinding.yaml new file mode 100644 index 0000000..94a72cc --- /dev/null +++ b/backing-services/mssql/templates/rolebinding.yaml @@ -0,0 +1,22 @@ +{{- if and .Values.serviceAccount.create .Values.rbac.create }} +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: RoleBinding +metadata: + name: {{ printf "%s-scc-anyuid" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:openshift:scc:anyuid +subjects: +- kind: ServiceAccount + name: {{ include "mssql.serviceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} +{{- end }} \ No newline at end of file diff --git a/backing-services/mssql/templates/secrets.yaml b/backing-services/mssql/templates/secrets.yaml new file mode 100644 index 0000000..e87e572 --- /dev/null +++ b/backing-services/mssql/templates/secrets.yaml @@ -0,0 +1,21 @@ +{{- if eq (include "mssql.createSecret" .) "true" }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + mssql-root-password: {{ include "common.secrets.passwords.manage" (dict "secret" (include "common.names.fullname" .) "key" "mssql-root-password" "length" 10 "providedValues" (list "auth.rootPassword") "context" $) }} + mssql-password: {{ include "common.secrets.passwords.manage" (dict "secret" (include "common.names.fullname" .) "key" "mssql-password" "length" 10 "providedValues" (list "auth.password") "context" $) }} + {{- if eq .Values.architecture "replication" }} + mssql-replication-password: {{ include "common.secrets.passwords.manage" (dict "secret" (include "common.names.fullname" .) "key" "mssql-replication-password" "length" 10 "providedValues" (list "auth.replicationPassword") "context" $) }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/backing-services/mssql/templates/serviceaccount.yaml b/backing-services/mssql/templates/serviceaccount.yaml new file mode 100644 index 0000000..edaeba9 --- /dev/null +++ b/backing-services/mssql/templates/serviceaccount.yaml @@ -0,0 +1,25 @@ + + +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "mssql.serviceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + annotations: + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.serviceAccount.annotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.serviceAccount.annotations "context" $ ) | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +{{- if (not .Values.auth.customPasswordFiles) }} +secrets: + - name: {{ template "mssql.secretName" . }} +{{- end }} +{{- end }} diff --git a/backing-services/mssql/templates/servicemonitor.yaml b/backing-services/mssql/templates/servicemonitor.yaml new file mode 100644 index 0000000..059a6db --- /dev/null +++ b/backing-services/mssql/templates/servicemonitor.yaml @@ -0,0 +1,49 @@ +{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ default (include "common.names.namespace" .) .Values.metrics.serviceMonitor.namespace }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.metrics.serviceMonitor.labels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.labels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + annotations: + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.annotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + jobLabel: {{ .Values.metrics.serviceMonitor.jobLabel | quote }} + endpoints: + - port: metrics + {{- if .Values.metrics.serviceMonitor.interval }} + interval: {{ .Values.metrics.serviceMonitor.interval }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.honorLabels }} + honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.metricRelabelings "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.relabelings }} + relabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.relabelings "context" $) | nindent 8 }} + {{- end }} + namespaceSelector: + matchNames: + - {{ include "common.names.namespace" . | quote }} + selector: + matchLabels: {{- include "common.labels.matchLabels" . | nindent 6 }} + app.kubernetes.io/component: metrics + {{- if .Values.metrics.serviceMonitor.selector }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.serviceMonitor.selector "context" $) | nindent 6 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/backing-services/mssql/tests/test.yaml b/backing-services/mssql/tests/test.yaml new file mode 100644 index 0000000..67e7a6a --- /dev/null +++ b/backing-services/mssql/tests/test.yaml @@ -0,0 +1,10 @@ +--- + +global: + storageClass: "openebs-kernel-nfs" + +auth: + database: test + rootPassword: 'yourStrong(#)Password' + username: test + password: 'yourStrong(#)Password' \ No newline at end of file diff --git a/backing-services/mssql/values.sample.yaml b/backing-services/mssql/values.sample.yaml new file mode 100644 index 0000000..d4db1d0 --- /dev/null +++ b/backing-services/mssql/values.sample.yaml @@ -0,0 +1,32 @@ +auth: + rootPassword: yJHSYfYHD5 + username: demouser + password: bQ7B71VUdz + +### +##### Backup +backup: + enabled: true + databases: ["DemoData", "my_database"] + cronjob: + # every hour + schedule: "0 * * * *" + persistence: + enabled: true +##### Monitoring +metrics: + ## @param metrics.enabled Start a side-car prometheus exporter + ## + enabled: true + serviceMonitor: + # !! Make it false if you don't have Prometheus operator, specifically CRD servicemonitor + enabled: true + # !! namespace wheren prometheus operator is running , where its servicemonitor resources deployed + namespace: monitoring + labels: + ### i.e k -n monitoring get servicemonitor -L release + release: monitoring-service + +ingress: + enabled: true + host: db1.labs.k8s.tn \ No newline at end of file diff --git a/backing-services/mssql/values.yaml b/backing-services/mssql/values.yaml new file mode 100644 index 0000000..2bf7c1e --- /dev/null +++ b/backing-services/mssql/values.yaml @@ -0,0 +1,1175 @@ +## @section Global parameters +## 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, imagePullSecrets and storageClass + +## @param global.imageRegistry Global Docker image registry +## @param global.imagePullSecrets Global Docker registry secret names as an array +## @param global.storageClass Global StorageClass for Persistent Volume(s) +## +global: + imageRegistry: "" + ## E.g. + ## imagePullSecrets: + ## - myRegistryKeySecretName + ## + imagePullSecrets: [] + storageClass: "local-path" + +## @section Common parameters + +## @param nameOverride String to partially override common.names.fullname template (will maintain the release name) +## +nameOverride: "" +## @param fullnameOverride String to fully override common.names.fullname template +## +fullnameOverride: "" +## @param namespaceOverride String to fully override common.names.namespace +## +namespaceOverride: "" +## @param clusterDomain Cluster domain +## +clusterDomain: cluster.local +## @param commonAnnotations Common annotations to add to all MSSQL resources (sub-charts are not considered). Evaluated as a template +## +commonAnnotations: {} +## @param commonLabels Common labels to add to all MSSQL resources (sub-charts are not considered). Evaluated as a template +## +commonLabels: {} + +## @section MSSQL common parameters + +## MSSQL image +## ref: https://hub.docker.com/_/microsoft-mssql-server +## @param image.registry MSSQL image registry +## @param image.repository MSSQL image repository +## @param image.tag MSSQL image tag (immutable tags are recommended) +## @param image.digest MSSQL image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag +## @param image.pullPolicy MSSQL image pull policy +## @param image.pullSecrets Specify docker-registry secret names as an array +## @param image.debug Specify if debug logs should be enabled +## +image: + registry: registry.gitlab.com + repository: xrow-public/helm-mssql/mssql + # @param image.tag MSSQL image tag https://hub.docker.com/_/microsoft-mssql-server#Full%20Tag%20Listing + ## GA = General Availability - when the version is officially available and supported. + ## CU = Cumulative Update - a periodic release that includes bug fixes, security fixes, and occasionally a small feature. + ## CTP = Community Technology Preview - a preview release that precedes the GA of an upcoming new version. + ## GDR = General Distribution Release - a release that contains ONLY security fixes. + + tag: 1.1.3 + digest: "" + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://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/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Set to true if you would like to see extra information on logs + ## It turns BASH and/or NAMI debugging in the image + ## + debug: false +## @param architecture MSSQL architecture (`standalone` or `replication`) +## ( `replication` is on the roadmap) +architecture: standalone +## @param edition MSSQL edition : +## Developer : This will run the container using the Developer Edition (this is the default if no MSSQL_PID environment variable is supplied) +## Express : This will run the container using the Express Edition +## Standard : This will run the container using the Standard Edition +## Enterprise : This will run the container using the Enterprise Edition +## EnterpriseCore : This will run the container using the Enterprise Edition Core +## Product ID: This will run the container with the edition that is associated with the PID +edition: Express +## MSSQL Authentication parameters +## +auth: + ## @param auth.rootPassword Password for the `root` user. Ignored if existing secret is provided + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/mssql#setting-the-root-password-on-first-run + ## + rootPassword: "" + ## @param auth.createDatabase Wheter to create the .Values.auth.database or not + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/mssql#creating-a-database-on-first-run + ## + createDatabase: true + ## @param auth.database Name for a custom database to create + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/mssql#creating-a-database-on-first-run + ## + database: "database" + ## @param auth.databaseCollate COLLATE for a custom database to create + ## examples: Latin1_General_CI_AS + databaseCollate: Latin1_General_CI_AS + ## @param auth.username Name for a custom user to create on master db as well as in [.Values.auth.database] + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/mssql#creating-a-database-user-on-first-run + ## + username: "" + ## @param auth.password Password for the new user. Ignored if existing secret is provided + ## + password: "" + ## @param auth.replicationUser MSSQL replication user + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/mssql#setting-up-a-replication-cluster + ## + ## @param auth.createLogin + ## if Yes, the .Values.auth.username is a local user.. + ## IF No, the .Values.auth.username is a domain user + ## If .Values.auth.username not defined, .this param has no effect + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/mssql#creating-a-database-user-on-first-run + ## + createLogin: true + replicationUser: replicator + ## @param auth.replicationPassword MSSQL replication user password. Ignored if existing secret is provided + ## + replicationPassword: "" + ## @param auth.existingSecret Use existing secret for password details. The secret has to contain the keys `mssql-root-password`, `mssql-replication-password` and `mssql-password` + ## NOTE: When it's set the auth.rootPassword, auth.password, auth.replicationPassword are ignored. + ## + existingSecret: "" + + +## @section MSSQL Primary parameters + +primary: + ## @param primary.name Name of the primary database (eg primary, master, leader, ...) + ## + name: primary + lifecycleHooks: {} + + ## @param primary.hostAliases Deployment pod host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + + ## @param primary.existingConfigmap Name of existing ConfigMap with MSSQL Primary configuration. + ## NOTE: When it's set the 'configuration' parameter is ignored + ## + existingConfigmap: "" + ## @param primary.updateStrategy.type Update strategy type for the MSSQL primary statefulset + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## + updateStrategy: + type: RollingUpdate + ## @param primary.podAnnotations Additional pod annotations for MSSQL primary pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param primary.podAffinityPreset MSSQL primary pod affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param primary.podAntiAffinityPreset MSSQL primary pod anti-affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## MSSQL Primary node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param primary.nodeAffinityPreset.type MSSQL primary node affinity preset type. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param primary.nodeAffinityPreset.key MSSQL primary node label key to match Ignored if `primary.affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param primary.nodeAffinityPreset.values MSSQL primary node label values to match. Ignored if `primary.affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param primary.affinity Affinity for MSSQL primary pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## Note: podAffinityPreset, podAntiAffinityPreset, and nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## @param primary.nodeSelector Node labels for MSSQL primary pods assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: + kubernetes.io/os: linux + ## @param primary.tolerations Tolerations for MSSQL primary pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param primary.priorityClassName MSSQL primary pods' priorityClassName + ## + priorityClassName: "" + ## @param primary.schedulerName Name of the k8s scheduler (other than default) + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param primary.terminationGracePeriodSeconds In seconds, time the given to the MSSQL primary pod needs to terminate gracefully + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods + ## + terminationGracePeriodSeconds: "" + ## @param primary.topologySpreadConstraints Topology Spread Constraints for pod assignment + ## https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## The value is evaluated as a template + ## + topologySpreadConstraints: [] + ## @param primary.podManagementPolicy podManagementPolicy to manage scaling operation of MSSQL primary pods + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#pod-management-policies + ## + podManagementPolicy: "" + ## MSSQL primary Pod security context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param primary.podSecurityContext.enabled Enable security context for MSSQL primary pods + ## @param primary.podSecurityContext.fsGroup Group ID for the mounted volumes' filesystem + ## + podSecurityContext: + enabled: true + fsGroup: 1001 + ## MSSQL primary container security context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param primary.containerSecurityContext.enabled MSSQL primary container securityContext + ## @param primary.containerSecurityContext.runAsUser User ID for the MSSQL primary container + ## @param primary.containerSecurityContext.runAsNonRoot Set MSSQL primary container's Security Context runAsNonRoot + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + + resources: + requests: + memory: "2G" + cpu: "2000m" + limits: + memory: "4G" + + livenessProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 3 + successThreshold: 1 + + readinessProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 3 + successThreshold: 1 + ## Configure extra options for startupProbe probe + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param primary.startupProbe.enabled Enable startupProbe + ## @param primary.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param primary.startupProbe.periodSeconds Period seconds for startupProbe + ## @param primary.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param primary.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param primary.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 10 + successThreshold: 1 + + ## @param primary.extraFlags MSSQL primary additional command line flags + ## Can be used to specify command line flags, for example: + ## E.g. + ## extraFlags: "--max-connect-errors=1000 --max_connections=155" + ## + extraFlags: "" + ## @param primary.extraEnvVars Extra environment variables to be set on MSSQL primary containers + ## E.g. + ## extraEnvVars: + ## - name: TZ + ## value: "Europe/Paris" + ## + extraEnvVars: [] + ## @param primary.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for MSSQL primary containers + ## + extraEnvVarsCM: "" + ## @param primary.extraEnvVarsSecret Name of existing Secret containing extra env vars for MSSQL primary containers + ## + extraEnvVarsSecret: "" + ## Enable persistence using Persistent Volume Claims + ## ref: https://kubernetes.io/docs/user-guide/persistent-volumes/ + ## + persistence: + ## @param primary.persistence.enabled Enable persistence on MSSQL primary replicas using a `PersistentVolumeClaim`. If false, use emptyDir + ## + enabled: true + ## @param primary.persistence.mount Path of Data inside container + ## + mount: /var/opt/mssql + ## @param primary.persistence.existingClaim Name of an existing `PersistentVolumeClaim` for MSSQL primary replicas + ## NOTE: When it's set the rest of persistence parameters are ignored + ## + existingClaim: "" + ## @param primary.persistence.storageClass MSSQL primary persistent volume storage Class + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + storageClass: "local-path" + ## @param primary.persistence.annotations MSSQL primary persistent volume claim annotations + ## + annotations: {} + ## @param primary.persistence.accessModes MSSQL primary persistent volume access Modes + ## + accessModes: + - ReadWriteOnce + ## @param primary.persistence.size MSSQL primary persistent volume size + ## + size: 8Gi + ## @param primary.persistence.selector Selector to match an existing Persistent Volume + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## @param primary.extraVolumes Optionally specify extra list of additional volumes to the MSSQL Primary pod(s) + ## + extraVolumes: [] + ## @param primary.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the MSSQL Primary container(s) + ## + extraVolumeMounts: [] + ## @param primary.initContainers Add additional init containers for the MSSQL Primary pod(s) + ## + initContainers: [] + ## @param primary.sidecars Add additional sidecar containers for the MSSQL Primary pod(s) + ## + sidecars: [] + ## MSSQL Primary Service parameters + ## + service: + ## @param primary.service.type MSSQL Primary K8s service type + ## + type: ClusterIP + ## @param primary.service.ports.mssql MSSQL Primary K8s service port + ## + ports: + mssql: 1433 + ## @param primary.service.nodePorts.mssql MSSQL Primary K8s service node port + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + nodePorts: + mssql: "" + ## @param primary.service.clusterIP MSSQL Primary K8s service clusterIP IP + ## e.g: + ## clusterIP: None + ## + clusterIP: "" + ## @param primary.service.loadBalancerIP MSSQL Primary loadBalancerIP if service type is `LoadBalancer` + ## Set the LoadBalancer service type to internal only + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param primary.service.externalTrafficPolicy Enable client source IP preservation + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param primary.service.loadBalancerSourceRanges Addresses that are allowed when MSSQL Primary service is LoadBalancer + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## E.g. + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param primary.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param primary.service.annotations Additional custom annotations for MSSQL primary service + ## + annotations: {} + ## @param primary.service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param primary.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## MSSQL primary Pod Disruption Budget configuration + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ + ## + pdb: + ## @param primary.pdb.create Enable/disable a Pod Disruption Budget creation for MSSQL primary pods + ## + create: false + ## @param primary.pdb.minAvailable Minimum number/percentage of MSSQL primary pods that should remain scheduled + ## + minAvailable: 1 + ## @param primary.pdb.maxUnavailable Maximum number/percentage of MSSQL primary pods that may be made unavailable + ## + maxUnavailable: "" + ## @param primary.podLabels MSSQL Primary pod label. If labels are same as commonLabels , this will take precedence + ## + podLabels: {} + +## @section MSSQL Secondary parameters + +secondary: + ## @param secondary.name Name of the secondary database (eg secondary, slave, ...) + ## + name: secondary + ## @param secondary.replicaCount Number of MSSQL secondary replicas + ## + replicaCount: 1 + ## @param secondary.hostAliases Deployment pod host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param secondary.command Override default container command on MSSQL Secondary container(s) (useful when using custom images) + ## + command: [] + ## @param secondary.args Override default container args on MSSQL Secondary container(s) (useful when using custom images) + ## + args: [] + ## @param secondary.lifecycleHooks for the MSSQL Secondary container(s) to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param secondary.configuration [string] Configure MSSQL Secondary with a custom my.cnf file + ## ref: https://mssql.com/kb/en/mssql/configuring-mssql-with-mycnf/#example-of-configuration-file + ## + + ## @param secondary.existingConfigmap Name of existing ConfigMap with MSSQL Secondary configuration. + ## NOTE: When it's set the 'configuration' parameter is ignored + ## + existingConfigmap: "" + ## @param secondary.updateStrategy.type Update strategy type for the MSSQL secondary statefulset + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## + updateStrategy: + type: RollingUpdate + ## @param secondary.podAnnotations Additional pod annotations for MSSQL secondary pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param secondary.podAffinityPreset MSSQL secondary pod affinity preset. Ignored if `secondary.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param secondary.podAntiAffinityPreset MSSQL secondary pod anti-affinity preset. Ignored if `secondary.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## Allowed values: soft, hard + ## + podAntiAffinityPreset: soft + ## MSSQL Secondary node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param secondary.nodeAffinityPreset.type MSSQL secondary node affinity preset type. Ignored if `secondary.affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param secondary.nodeAffinityPreset.key MSSQL secondary node label key to match Ignored if `secondary.affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param secondary.nodeAffinityPreset.values MSSQL secondary node label values to match. Ignored if `secondary.affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param secondary.affinity Affinity for MSSQL secondary pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## Note: podAffinityPreset, podAntiAffinityPreset, and nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## @param secondary.nodeSelector Node labels for MSSQL secondary pods assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: + kubernetes.io/os: linux + ## @param secondary.tolerations Tolerations for MSSQL secondary pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param secondary.priorityClassName MSSQL secondary pods' priorityClassName + ## + priorityClassName: "" + ## @param secondary.schedulerName Name of the k8s scheduler (other than default) + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param secondary.terminationGracePeriodSeconds In seconds, time the given to the MSSQL secondary pod needs to terminate gracefully + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods + ## + terminationGracePeriodSeconds: "" + ## @param secondary.topologySpreadConstraints Topology Spread Constraints for pod assignment + ## https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## The value is evaluated as a template + ## + topologySpreadConstraints: [] + ## @param secondary.podManagementPolicy podManagementPolicy to manage scaling operation of MSSQL secondary pods + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#pod-management-policies + ## + podManagementPolicy: "" + ## MSSQL secondary Pod security context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param secondary.podSecurityContext.enabled Enable security context for MSSQL secondary pods + ## @param secondary.podSecurityContext.fsGroup Group ID for the mounted volumes' filesystem + ## + podSecurityContext: + enabled: true + fsGroup: 1001 + ## MSSQL secondary container security context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param secondary.containerSecurityContext.enabled MSSQL secondary container securityContext + ## @param secondary.containerSecurityContext.runAsUser User ID for the MSSQL secondary container + ## @param secondary.containerSecurityContext.runAsNonRoot Set MSSQL secondary container's Security Context runAsNonRoot + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + ## MSSQL secondary container's resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-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:'. + ## @param secondary.resources.limits The resources limits for MSSQL secondary containers + ## @param secondary.resources.requests The requested resources for MSSQL secondary containers + ## + resources: + ## Example: + ## limits: + ## cpu: 250m + ## memory: 256Mi + limits: {} + ## Examples: + ## requests: + ## cpu: 250m + ## memory: 256Mi + requests: {} + ## Configure extra options for liveness probe + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param secondary.livenessProbe.enabled Enable livenessProbe + ## @param secondary.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param secondary.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param secondary.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param secondary.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param secondary.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 3 + successThreshold: 1 + ## Configure extra options for readiness probe + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param secondary.readinessProbe.enabled Enable readinessProbe + ## @param secondary.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param secondary.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param secondary.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param secondary.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param secondary.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 3 + successThreshold: 1 + ## Configure extra options for startupProbe probe + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param secondary.startupProbe.enabled Enable startupProbe + ## @param secondary.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param secondary.startupProbe.periodSeconds Period seconds for startupProbe + ## @param secondary.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param secondary.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param secondary.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 15 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 15 + successThreshold: 1 + ## @param secondary.customLivenessProbe Override default liveness probe for MSSQL secondary containers + ## + customLivenessProbe: {} + ## @param secondary.customReadinessProbe Override default readiness probe for MSSQL secondary containers + ## + customReadinessProbe: {} + ## @param secondary.customStartupProbe Override default startup probe for MSSQL secondary containers + ## + customStartupProbe: {} + ## @param secondary.extraFlags MSSQL secondary additional command line flags + ## Can be used to specify command line flags, for example: + ## E.g. + ## extraFlags: "--max-connect-errors=1000 --max_connections=155" + ## + extraFlags: "" + ## @param secondary.extraEnvVars An array to add extra environment variables on MSSQL secondary containers + ## E.g. + ## extraEnvVars: + ## - name: TZ + ## value: "Europe/Paris" + ## + extraEnvVars: [] + ## @param secondary.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for MSSQL secondary containers + ## + extraEnvVarsCM: "" + ## @param secondary.extraEnvVarsSecret Name of existing Secret containing extra env vars for MSSQL secondary containers + ## + extraEnvVarsSecret: "" + ## Enable persistence using Persistent Volume Claims + ## ref: https://kubernetes.io/docs/user-guide/persistent-volumes/ + ## + persistence: + ## @param secondary.persistence.enabled Enable persistence on MSSQL secondary replicas using a `PersistentVolumeClaim` + ## + enabled: true + ## @param secondary.persistence.storageClass MSSQL secondary persistent volume storage Class + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + storageClass: "local-path" + ## @param secondary.persistence.annotations MSSQL secondary persistent volume claim annotations + ## + annotations: {} + ## @param secondary.persistence.accessModes MSSQL secondary persistent volume access Modes + ## + accessModes: + - ReadWriteOnce + ## @param secondary.persistence.size MSSQL secondary persistent volume size + ## + size: 8Gi + ## @param secondary.persistence.selector Selector to match an existing Persistent Volume + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## @param secondary.extraVolumes Optionally specify extra list of additional volumes to the MSSQL secondary pod(s) + ## + extraVolumes: [] + ## @param secondary.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the MSSQL secondary container(s) + ## + extraVolumeMounts: [] + ## @param secondary.initContainers Add additional init containers for the MSSQL secondary pod(s) + ## + initContainers: [] + ## @param secondary.sidecars Add additional sidecar containers for the MSSQL secondary pod(s) + ## + sidecars: [] + ## MSSQL Secondary Service parameters + ## + service: + ## @param secondary.service.type MSSQL secondary Kubernetes service type + ## + type: ClusterIP + ## @param secondary.service.ports.mssql MSSQL secondary Kubernetes service port + ## + ports: + mssql: 1433 + ## @param secondary.service.nodePorts.mssql MSSQL secondary Kubernetes service node port + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + nodePorts: + mssql: "" + ## @param secondary.service.clusterIP MSSQL secondary Kubernetes service clusterIP IP + ## e.g: + ## clusterIP: None + ## + clusterIP: "" + ## @param secondary.service.loadBalancerIP MSSQL secondary loadBalancerIP if service type is `LoadBalancer` + ## Set the LoadBalancer service type to internal only + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param secondary.service.externalTrafficPolicy Enable client source IP preservation + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param secondary.service.loadBalancerSourceRanges Addresses that are allowed when MSSQL secondary service is LoadBalancer + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## E.g. + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param secondary.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param secondary.service.annotations Additional custom annotations for MSSQL secondary service + ## + annotations: {} + ## @param secondary.service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param secondary.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## MSSQL secondary Pod Disruption Budget configuration + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ + ## + pdb: + ## @param secondary.pdb.create Enable/disable a Pod Disruption Budget creation for MSSQL secondary pods + ## + create: false + ## @param secondary.pdb.minAvailable Minimum number/percentage of MSSQL secondary pods that should remain scheduled + ## + minAvailable: 1 + ## @param secondary.pdb.maxUnavailable Maximum number/percentage of MSSQL secondary pods that may be made unavailable + ## + maxUnavailable: "" + ## @param secondary.podLabels Additional pod labels for MSSQL secondary pods + ## + podLabels: {} + +## @section MSSQL Client parameters +client: + image: + registry: mcr.microsoft.com + repository: mssql-tools + tag: latest + +## @section RBAC parameters + +## MSSQL pods ServiceAccount +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ +## +serviceAccount: + ## @param serviceAccount.create Enable the creation of a ServiceAccount for MSSQL pods + ## + create: true + ## @param serviceAccount.name Name of the created ServiceAccount + ## If not set and create is true, a name is generated using the mssql.fullname template + ## + name: "" + ## @param serviceAccount.annotations Annotations for MSSQL Service Account + ## + annotations: {} + ## @param serviceAccount.automountServiceAccountToken Automount service account token for the server service account + ## + automountServiceAccountToken: true + +## Role Based Access +## ref: https://kubernetes.io/docs/admin/authorization/rbac/ +## +rbac: + ## @param rbac.create Whether to create & use RBAC resources or not + ## + create: true + ## @param rbac.rules Custom RBAC rules to set + ## e.g: + ## rules: + ## - apiGroups: + ## - "" + ## resources: + ## - pods + ## verbs: + ## - get + ## - list + ## + rules: [] + +## @section Network Policy + +## MSSQL Nework Policy configuration +## +networkPolicy: + ## @param networkPolicy.enabled Enable creation of NetworkPolicy resources + ## + enabled: false + ## @param networkPolicy.allowExternal The Policy model to apply. + ## When set to false, only pods with the correct + ## client label will have network access to the port MSSQL is listening + ## on. When true, MSSQL will accept connections from any source + ## (with the correct destination port). + ## + allowExternal: true + ## @param networkPolicy.explicitNamespacesSelector A Kubernetes LabelSelector to explicitly select namespaces from which ingress traffic could be allowed to MSSQL + ## 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. + ## + ## Example: + ## explicitNamespacesSelector: + ## matchLabels: + ## role: frontend + ## matchExpressions: + ## - {key: role, operator: In, values: [frontend]} + ## + explicitNamespacesSelector: {} + +## @section Volume Permissions parameters + +## Init containers parameters: +## volumePermissions: Change the owner and group of the persistent volume mountpoint to runAsUser:fsGroup values from the securityContext section. +## +volumePermissions: + ## @param volumePermissions.enabled Enable init container that changes the owner and group of the persistent volume(s) mountpoint to `runAsUser:fsGroup` + ## + enabled: false + ## @param volumePermissions.image.registry Init container volume-permissions image registry + ## @param volumePermissions.image.repository Init container volume-permissions image repository + ## @param volumePermissions.image.tag Init container volume-permissions image tag (immutable tags are recommended) + ## @param volumePermissions.image.digest Init container volume-permissions image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param volumePermissions.image.pullPolicy Init container volume-permissions image pull policy + ## @param volumePermissions.image.pullSecrets Specify docker-registry secret names as an array + ## + image: + registry: registry.access.redhat.com + repository: ubi9/ubi + tag: 9.4-947.1714667021 + digest: "" + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## @param volumePermissions.resources Init container volume-permissions resources + ## + resources: {} + +## @section MSSQL Backup parameters +## ref: https://docs.microsoft.com/en-us/sql/linux/tutorial-restore-backup-in-sql-server-container?view=sql-server-ver16 +backup: + ## @param backup.enabled Enable backup features + ## + enabled: true + ## @param.backup.databases list of databases target for backup every .Values.backup.cronjob.schedule + ## + databases: [] + cronjob: + ## @param backup.cronjob.schedule TODO Enable auto backup every specific period of time - TODO !!! + ## defaults to every day at At 01:00 + schedule: "0 1 * * *" + ## @param backup.cronjob.commandTemplate TODO backup command template to be run by "sqlcmd -C" every .Values.backup.schedule - TODO !!! + ## it is a template that can interpolate: + ## 1. Any Values of this chart + ## 2. The following env vars: + ## - $database : database as it was mentioned in .Values.backup.databases[i] + ## - $now: current time in this format %Y-%m-%d_%Hh%Mm%Ssec + ## + ## !!!! NOTE !!!! + ## Recommended to not override this value as the restore script is + ## developed based on this default value of @param backup.cronjob.commandTemplate. + ## !!!!!!!!!!!!!! + ## ref: https://learn.microsoft.com/en-us/sql/t-sql/statements/backup-transact-sql?view=sql-server-ver16 + ## ref: https://docs.microsoft.com/en-us/sql/linux/tutorial-restore-backup-in-sql-server-container?view=sql-server-ver16#create-a-new-backup + ## + commandTemplate: BACKUP DATABASE [$database] TO DISK = N'{{ .Values.backup.persistence.mount }}/$database-$now.bak' WITH NOFORMAT, NOINIT, NAME = '${database}Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10 + ## @param backup.cronjob.historyLimit Number of successful finished jobs to retain + ## + historyLimit: 1 + ## @param backup.cronjob.snapshotHistoryLimit Number of etcd snapshots to retain, tagged by date + ## + snapshotHistoryLimit: 1 + ## @param backup.cronjob.podAnnotations [object] Pod annotations for cronjob pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param backup.cronjob.podSecurityContext [object] + ## + podSecurityContext: {} + ## MSSQL backup.cronjob container security context + ## + containerSecurityContext: {} + ## Configure resource requests and limits for snapshotter containers + ## ref: https://kubernetes.io/docs/user-guide/compute-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:'. + ## @param backup.cronjob.resources.limits [object] Cronjob container resource limits + ## @param backup.cronjob.resources.requests [object] Cronjob container resource requests + ## + resources: + ## Example: + ## limits: + ## cpu: 500m + ## memory: 1Gi + ## + limits: {} + requests: {} + + ## @param backup.cronjob.nodeSelector Node labels for cronjob pods assignment + ## Ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: + kubernetes.io/os: linux + ## @param backup.cronjob.tolerations Tolerations for cronjob pods assignment + ## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + + + ## Persistence for Backup files + ## + persistence: + ## @param backup.persistence.enabled Enable persisting Backups on MSSQL primary replicas using a `PersistentVolumeClaim`. If false, use emptyDir + ## + enabled: false + ## @param backup.persistence.mount Path of Data inside container + ## + mount: /var/opt/mssql/backup + ## @param backup.persistence.existingClaim Name of an existing `PersistentVolumeClaim` for Backups on MSSQL primary replicas + ## NOTE: When it's set the rest of persistence parameters are ignored + ## + existingClaim: "" + ## @param backup.persistence.storageClass Backup MSSQL primary persistent volume storage Class + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + storageClass: "local-path" + ## @param backup.persistence.annotations Backup MSSQL primary persistent volume claim annotations + ## + annotations: {} + ## @param backup.persistence.accessModes Backup MSSQL primary persistent volume access Modes + ## + accessModes: + - ReadWriteMany + ## @param backup.persistence.size Backup MSSQL primary persistent volume size + ## + size: 20Gi + ## @param backup.persistence.selector Selector to match an existing Persistent Volume + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} +## @section Metrics parameters + +## MsSQLd Prometheus exporter parameters +## Grafana Dashboard is available here: https://grafana.com/grafana/dashboards/13919-microsoft-sql-server/ +metrics: + ## @param metrics.enabled Start a side-car prometheus exporter + ## + enabled: false + ## @param metrics.image.registry Exporter image registry + ## @param metrics.image.repository Exporter image repository + ## @param metrics.image.tag Exporter image tag (immutable tags are recommended) + ## @param metrics.image.digest Exporter image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param metrics.image.pullPolicy Exporter image pull policy + ## @param metrics.image.pullSecrets Specify docker-registry secret names as an array + ## + image: + registry: docker.io + # https://github.com/awaragi/prometheus-mssql-exporter + repository: awaragi/prometheus-mssql-exporter + tag: v1.3.0 + digest: "" + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## MSSQL Prometheus exporter service parameters + ## Mssqld Prometheus exporter liveness and readiness probes + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param metrics.service.type Kubernetes service type for MSSQL Prometheus Exporter + ## @param metrics.service.port MSSQL Prometheus Exporter service port + ## @param metrics.service.annotations [object] Prometheus exporter service annotations + ## + service: + type: ClusterIP + port: 4000 + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "{{ .Values.metrics.service.port }}" + ## @param metrics.extraArgs.primary Extra args to be passed to mssqld_exporter on Primary pods + ## @param metrics.extraArgs.secondary Extra args to be passed to mssqld_exporter on Secondary pods + ## ref: https://github.com/prometheus/mssqld_exporter/ + ## E.g. + ## - --collect.auto_increment.columns + ## - --collect.binlog_size + ## - --collect.engine_innodb_status + ## - --collect.engine_tokudb_status + ## - --collect.global_status + ## - --collect.global_variables + ## - --collect.info_schema.clientstats + ## - --collect.info_schema.innodb_metrics + ## - --collect.info_schema.innodb_tablespaces + ## - --collect.info_schema.innodb_cmp + ## - --collect.info_schema.innodb_cmpmem + ## - --collect.info_schema.processlist + ## - --collect.info_schema.processlist.min_time + ## - --collect.info_schema.query_response_time + ## - --collect.info_schema.tables + ## - --collect.info_schema.tables.databases + ## - --collect.info_schema.tablestats + ## - --collect.info_schema.userstats + ## - --collect.perf_schema.eventsstatements + ## - --collect.perf_schema.eventsstatements.digest_text_limit + ## - --collect.perf_schema.eventsstatements.limit + ## - --collect.perf_schema.eventsstatements.timelimit + ## - --collect.perf_schema.eventswaits + ## - --collect.perf_schema.file_events + ## - --collect.perf_schema.file_instances + ## - --collect.perf_schema.indexiowaits + ## - --collect.perf_schema.tableiowaits + ## - --collect.perf_schema.tablelocks + ## - --collect.perf_schema.replication_group_member_stats + ## - --collect.slave_status + ## - --collect.slave_hosts + ## - --collect.heartbeat + ## - --collect.heartbeat.database + ## - --collect.heartbeat.table + ## + extraArgs: + primary: [] + secondary: [] + ## Mssqld Prometheus exporter resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-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:'. + ## @param metrics.resources.limits The resources limits for MSSQL prometheus exporter containers + ## @param metrics.resources.requests The requested resources for MSSQL prometheus exporter containers + ## + resources: + ## Example: + ## limits: + ## cpu: 100m + ## memory: 256Mi + limits: {} + ## Examples: + ## requests: + ## cpu: 100m + ## memory: 256Mi + requests: {} + ## Mssqld Prometheus exporter liveness probe + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param metrics.livenessProbe.enabled Enable livenessProbe + ## @param metrics.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param metrics.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param metrics.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param metrics.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param metrics.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 120 + periodSeconds: 10 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 3 + ## Mssqld Prometheus exporter readiness probe + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param metrics.readinessProbe.enabled Enable readinessProbe + ## @param metrics.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param metrics.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param metrics.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param metrics.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param metrics.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 3 + ## Prometheus Service Monitor + ## ref: https://github.com/coreos/prometheus-operator + ## + serviceMonitor: + ## @param metrics.serviceMonitor.enabled Create ServiceMonitor Resource for scraping metrics using PrometheusOperator + ## + enabled: false + ## @param metrics.serviceMonitor.namespace Specify the namespace in which the serviceMonitor resource will be created + ## + namespace: "" + ## @param metrics.serviceMonitor.jobLabel The name of the label on the target service to use as the job name in prometheus. + ## + jobLabel: "" + ## @param metrics.serviceMonitor.interval Specify the interval at which metrics should be scraped + ## + interval: 30s + ## @param metrics.serviceMonitor.scrapeTimeout Specify the timeout after which the scrape is ended + ## e.g: + ## scrapeTimeout: 30s + ## + scrapeTimeout: "" + ## @param metrics.serviceMonitor.relabelings RelabelConfigs to apply to samples before scraping + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#relabelconfig + ## + relabelings: [] + ## @param metrics.serviceMonitor.metricRelabelings MetricRelabelConfigs to apply to samples before ingestion + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#relabelconfig + ## + metricRelabelings: [] + ## @param metrics.serviceMonitor.selector ServiceMonitor selector labels + ## ref: https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#prometheus-configuration + ## + ## selector: + ## prometheus: my-prometheus + ## + selector: {} + ## @param metrics.serviceMonitor.honorLabels Specify honorLabels parameter to add the scrape endpoint + ## + honorLabels: false + ## @param metrics.serviceMonitor.labels Used to pass Labels that are used by the Prometheus installed in your cluster to select Service Monitors to work with + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#prometheusspec + ## + labels: {} + ## @param metrics.serviceMonitor.annotations ServiceMonitor annotations + ## + annotations: {} + + ## Prometheus Operator prometheusRule configuration + ## + prometheusRule: + ## @param metrics.prometheusRule.enabled Creates a Prometheus Operator prometheusRule (also requires `metrics.enabled` to be `true` and `metrics.prometheusRule.rules`) + ## + enabled: false + ## @param metrics.prometheusRule.namespace Namespace for the prometheusRule Resource (defaults to the Release Namespace) + ## + namespace: "" + ## @param metrics.prometheusRule.additionalLabels Additional labels that can be used so prometheusRule will be discovered by Prometheus + ## + additionalLabels: {} + ## @param metrics.prometheusRule.rules Prometheus Rule definitions + ## - alert: Mssql-Down + ## expr: absent(up{job="mssql"} == 1) + ## for: 5m + ## labels: + ## severity: warning + ## service: mariadb + ## annotations: + ## message: 'MariaDB instance {{`{{`}} $labels.instance {{`}}`}} is down' + ## summary: MariaDB instance is down + ## + rules: [] \ No newline at end of file diff --git a/backing-services/mysql/.helmignore b/backing-services/mysql/.helmignore new file mode 100644 index 0000000..f0c1319 --- /dev/null +++ b/backing-services/mysql/.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/backing-services/mysql/Chart.lock b/backing-services/mysql/Chart.lock new file mode 100644 index 0000000..06c81d6 --- /dev/null +++ b/backing-services/mysql/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + version: 2.14.1 +digest: sha256:5ccbe5f1fe4459864a8c9d7329c400b678666b6cfb1450818a830bda81995bc3 +generated: "2024-01-17T16:56:27.869448297Z" diff --git a/backing-services/mysql/Chart.yaml b/backing-services/mysql/Chart.yaml new file mode 100644 index 0000000..f519ce3 --- /dev/null +++ b/backing-services/mysql/Chart.yaml @@ -0,0 +1,37 @@ +# Copyright VMware, Inc. +# SPDX-License-Identifier: APACHE-2.0 + +annotations: + category: Database + licenses: Apache-2.0 + images: | + - name: mysql + image: docker.io/bitnami/mysql:8.0.35-debian-11-r2 + - name: mysqld-exporter + image: docker.io/bitnami/mysqld-exporter:0.15.1-debian-11-r0 + - name: os-shell + image: docker.io/bitnami/os-shell:11-debian-11-r93 +apiVersion: v2 +appVersion: 8.0.35 +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + tags: + - bitnami-common + version: 2.x.x +description: MySQL is a fast, reliable, scalable, and easy to use open source relational database system. Designed to handle mission-critical, heavy-load production applications. +home: https://bitnami.com +icon: https://bitnami.com/assets/stacks/mysql/img/mysql-stack-220x234.png +keywords: +- mysql +- database +- sql +- cluster +- high availability +maintainers: +- name: VMware, Inc. + url: https://github.com/bitnami/charts +name: mysql +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/mysql +version: 9.16.1 diff --git a/backing-services/mysql/README.md b/backing-services/mysql/README.md new file mode 100644 index 0000000..6fdd4a8 --- /dev/null +++ b/backing-services/mysql/README.md @@ -0,0 +1,575 @@ + + +# Bitnami package for MySQL + +MySQL is a fast, reliable, scalable, and easy to use open source relational database system. Designed to handle mission-critical, heavy-load production applications. + +[Overview of MySQL](http://www.mysql.com) + +Trademarks: This software listing is packaged by Bitnami. The respective trademarks mentioned in the offering are owned by the respective companies, and use of them does not imply any affiliation or endorsement. + +## TL;DR + +```console +helm install my-release oci://registry-1.docker.io/bitnamicharts/mysql +``` + +Looking to use MySQL in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the enterprise edition of Bitnami Application Catalog. + +## Introduction + +This chart bootstraps a [MySQL](https://github.com/bitnami/containers/tree/main/bitnami/mysql) replication cluster deployment on a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ +- 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 oci://REGISTRY_NAME/REPOSITORY_NAME/mysql +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +These commands deploy MySQL 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 + +### Global parameters + +| Name | Description | Value | +| ------------------------- | ----------------------------------------------- | ----- | +| `global.imageRegistry` | Global Docker image registry | `""` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | +| `global.storageClass` | Global StorageClass for Persistent Volume(s) | `""` | + +### Common parameters + +| Name | Description | Value | +| ------------------------- | --------------------------------------------------------------------------------------------------------- | --------------- | +| `kubeVersion` | Force target Kubernetes version (using Helm capabilities if not set) | `""` | +| `nameOverride` | String to partially override common.names.fullname template (will maintain the release name) | `""` | +| `fullnameOverride` | String to fully override common.names.fullname template | `""` | +| `namespaceOverride` | String to fully override common.names.namespace | `""` | +| `clusterDomain` | Cluster domain | `cluster.local` | +| `commonAnnotations` | Common annotations to add to all MySQL resources (sub-charts are not considered). Evaluated as a template | `{}` | +| `commonLabels` | Common labels to add to all MySQL resources (sub-charts are not considered). Evaluated as a template | `{}` | +| `extraDeploy` | Array with extra yaml to deploy with the chart. Evaluated as a template | `[]` | +| `serviceBindings.enabled` | Create secret for service binding (Experimental) | `false` | +| `diagnosticMode.enabled` | Enable diagnostic mode (all probes will be disabled and the command will be overridden) | `false` | +| `diagnosticMode.command` | Command to override all containers in the deployment | `["sleep"]` | +| `diagnosticMode.args` | Args to override all containers in the deployment | `["infinity"]` | + +### MySQL common parameters + +| Name | Description | Value | +| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | +| `image.registry` | MySQL image registry | `REGISTRY_NAME` | +| `image.repository` | MySQL image repository | `REPOSITORY_NAME/mysql` | +| `image.digest` | MySQL image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `image.pullPolicy` | MySQL image pull policy | `IfNotPresent` | +| `image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `image.debug` | Specify if debug logs should be enabled | `false` | +| `architecture` | MySQL architecture (`standalone` or `replication`) | `standalone` | +| `auth.rootPassword` | Password for the `root` user. Ignored if existing secret is provided | `""` | +| `auth.createDatabase` | Whether to create the .Values.auth.database or not | `true` | +| `auth.database` | Name for a custom database to create | `my_database` | +| `auth.username` | Name for a custom user to create | `""` | +| `auth.password` | Password for the new user. Ignored if existing secret is provided | `""` | +| `auth.replicationUser` | MySQL replication user | `replicator` | +| `auth.replicationPassword` | MySQL replication user password. Ignored if existing secret is provided | `""` | +| `auth.existingSecret` | Use existing secret for password details. The secret has to contain the keys `mysql-root-password`, `mysql-replication-password` and `mysql-password` | `""` | +| `auth.usePasswordFiles` | Mount credentials as files instead of using an environment variable | `false` | +| `auth.customPasswordFiles` | Use custom password files when `auth.usePasswordFiles` is set to `true`. Define path for keys `root` and `user`, also define `replicator` if `architecture` is set to `replication` | `{}` | +| `auth.defaultAuthenticationPlugin` | Sets the default authentication plugin, by default it will use `mysql_native_password` | `""` | +| `initdbScripts` | Dictionary of initdb scripts | `{}` | +| `initdbScriptsConfigMap` | ConfigMap with the initdb scripts (Note: Overrides `initdbScripts`) | `""` | +| `startdbScripts` | Dictionary of startdb scripts | `{}` | +| `startdbScriptsConfigMap` | ConfigMap with the startdb scripts (Note: Overrides `startdbScripts`) | `""` | + +### MySQL Primary parameters + +| Name | Description | Value | +| ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------- | +| `primary.name` | Name of the primary database (eg primary, master, leader, ...) | `primary` | +| `primary.command` | Override default container command on MySQL Primary container(s) (useful when using custom images) | `[]` | +| `primary.args` | Override default container args on MySQL Primary container(s) (useful when using custom images) | `[]` | +| `primary.lifecycleHooks` | for the MySQL Primary container(s) to automate configuration before or after startup | `{}` | +| `primary.hostAliases` | Deployment pod host aliases | `[]` | +| `primary.configuration` | Configure MySQL Primary with a custom my.cnf file | `""` | +| `primary.existingConfigmap` | Name of existing ConfigMap with MySQL Primary configuration. | `""` | +| `primary.updateStrategy.type` | Update strategy type for the MySQL primary statefulset | `RollingUpdate` | +| `primary.podAnnotations` | Additional pod annotations for MySQL primary pods | `{}` | +| `primary.podAffinityPreset` | MySQL primary pod affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `primary.podAntiAffinityPreset` | MySQL primary pod anti-affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `primary.nodeAffinityPreset.type` | MySQL primary node affinity preset type. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `primary.nodeAffinityPreset.key` | MySQL primary node label key to match Ignored if `primary.affinity` is set. | `""` | +| `primary.nodeAffinityPreset.values` | MySQL primary node label values to match. Ignored if `primary.affinity` is set. | `[]` | +| `primary.affinity` | Affinity for MySQL primary pods assignment | `{}` | +| `primary.nodeSelector` | Node labels for MySQL primary pods assignment | `{}` | +| `primary.tolerations` | Tolerations for MySQL primary pods assignment | `[]` | +| `primary.priorityClassName` | MySQL primary pods' priorityClassName | `""` | +| `primary.runtimeClassName` | MySQL primary pods' runtimeClassName | `""` | +| `primary.schedulerName` | Name of the k8s scheduler (other than default) | `""` | +| `primary.terminationGracePeriodSeconds` | In seconds, time the given to the MySQL primary pod needs to terminate gracefully | `""` | +| `primary.topologySpreadConstraints` | Topology Spread Constraints for pod assignment | `[]` | +| `primary.podManagementPolicy` | podManagementPolicy to manage scaling operation of MySQL primary pods | `""` | +| `primary.podSecurityContext.enabled` | Enable security context for MySQL primary pods | `true` | +| `primary.podSecurityContext.fsGroup` | Group ID for the mounted volumes' filesystem | `1001` | +| `primary.containerSecurityContext.enabled` | MySQL primary container securityContext | `true` | +| `primary.containerSecurityContext.runAsUser` | User ID for the MySQL primary container | `1001` | +| `primary.containerSecurityContext.runAsNonRoot` | Set MySQL primary container's Security Context runAsNonRoot | `true` | +| `primary.containerSecurityContext.allowPrivilegeEscalation` | Set container's privilege escalation | `false` | +| `primary.containerSecurityContext.capabilities.drop` | Set container's Security Context runAsNonRoot | `["ALL"]` | +| `primary.containerSecurityContext.seccompProfile.type` | Set Client container's Security Context seccomp profile | `RuntimeDefault` | +| `primary.resources.limits` | The resources limits for MySQL primary containers | `{}` | +| `primary.resources.requests` | The requested resources for MySQL primary containers | `{}` | +| `primary.livenessProbe.enabled` | Enable livenessProbe | `true` | +| `primary.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `5` | +| `primary.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `primary.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `1` | +| `primary.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `3` | +| `primary.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `primary.readinessProbe.enabled` | Enable readinessProbe | `true` | +| `primary.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `primary.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `primary.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `1` | +| `primary.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `3` | +| `primary.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `primary.startupProbe.enabled` | Enable startupProbe | `true` | +| `primary.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `15` | +| `primary.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `primary.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `1` | +| `primary.startupProbe.failureThreshold` | Failure threshold for startupProbe | `10` | +| `primary.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `primary.customLivenessProbe` | Override default liveness probe for MySQL primary containers | `{}` | +| `primary.customReadinessProbe` | Override default readiness probe for MySQL primary containers | `{}` | +| `primary.customStartupProbe` | Override default startup probe for MySQL primary containers | `{}` | +| `primary.extraFlags` | MySQL primary additional command line flags | `""` | +| `primary.extraEnvVars` | Extra environment variables to be set on MySQL primary containers | `[]` | +| `primary.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for MySQL primary containers | `""` | +| `primary.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for MySQL primary containers | `""` | +| `primary.extraPodSpec` | Optionally specify extra PodSpec for the MySQL Primary pod(s) | `{}` | +| `primary.extraPorts` | Extra ports to expose | `[]` | +| `primary.persistence.enabled` | Enable persistence on MySQL primary replicas using a `PersistentVolumeClaim`. If false, use emptyDir | `true` | +| `primary.persistence.existingClaim` | Name of an existing `PersistentVolumeClaim` for MySQL primary replicas | `""` | +| `primary.persistence.subPath` | The name of a volume's sub path to mount for persistence | `""` | +| `primary.persistence.storageClass` | MySQL primary persistent volume storage Class | `""` | +| `primary.persistence.annotations` | MySQL primary persistent volume claim annotations | `{}` | +| `primary.persistence.accessModes` | MySQL primary persistent volume access Modes | `["ReadWriteOnce"]` | +| `primary.persistence.size` | MySQL primary persistent volume size | `8Gi` | +| `primary.persistence.selector` | Selector to match an existing Persistent Volume | `{}` | +| `primary.persistentVolumeClaimRetentionPolicy.enabled` | Enable Persistent volume retention policy for Primary StatefulSet | `false` | +| `primary.persistentVolumeClaimRetentionPolicy.whenScaled` | Volume retention behavior when the replica count of the StatefulSet is reduced | `Retain` | +| `primary.persistentVolumeClaimRetentionPolicy.whenDeleted` | Volume retention behavior that applies when the StatefulSet is deleted | `Retain` | +| `primary.extraVolumes` | Optionally specify extra list of additional volumes to the MySQL Primary pod(s) | `[]` | +| `primary.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the MySQL Primary container(s) | `[]` | +| `primary.initContainers` | Add additional init containers for the MySQL Primary pod(s) | `[]` | +| `primary.sidecars` | Add additional sidecar containers for the MySQL Primary pod(s) | `[]` | +| `primary.service.type` | MySQL Primary K8s service type | `ClusterIP` | +| `primary.service.ports.mysql` | MySQL Primary K8s service port | `3306` | +| `primary.service.nodePorts.mysql` | MySQL Primary K8s service node port | `""` | +| `primary.service.clusterIP` | MySQL Primary K8s service clusterIP IP | `""` | +| `primary.service.loadBalancerIP` | MySQL Primary loadBalancerIP if service type is `LoadBalancer` | `""` | +| `primary.service.externalTrafficPolicy` | Enable client source IP preservation | `Cluster` | +| `primary.service.loadBalancerSourceRanges` | Addresses that are allowed when MySQL Primary service is LoadBalancer | `[]` | +| `primary.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `primary.service.annotations` | Additional custom annotations for MySQL primary service | `{}` | +| `primary.service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` | +| `primary.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `primary.service.headless.annotations` | Additional custom annotations for headless MySQL primary service. | `{}` | +| `primary.pdb.create` | Enable/disable a Pod Disruption Budget creation for MySQL primary pods | `false` | +| `primary.pdb.minAvailable` | Minimum number/percentage of MySQL primary pods that should remain scheduled | `1` | +| `primary.pdb.maxUnavailable` | Maximum number/percentage of MySQL primary pods that may be made unavailable | `""` | +| `primary.podLabels` | MySQL Primary pod label. If labels are same as commonLabels , this will take precedence | `{}` | + +### MySQL Secondary parameters + +| Name | Description | Value | +| ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------- | +| `secondary.name` | Name of the secondary database (eg secondary, slave, ...) | `secondary` | +| `secondary.replicaCount` | Number of MySQL secondary replicas | `1` | +| `secondary.hostAliases` | Deployment pod host aliases | `[]` | +| `secondary.command` | Override default container command on MySQL Secondary container(s) (useful when using custom images) | `[]` | +| `secondary.args` | Override default container args on MySQL Secondary container(s) (useful when using custom images) | `[]` | +| `secondary.lifecycleHooks` | for the MySQL Secondary container(s) to automate configuration before or after startup | `{}` | +| `secondary.configuration` | Configure MySQL Secondary with a custom my.cnf file | `""` | +| `secondary.existingConfigmap` | Name of existing ConfigMap with MySQL Secondary configuration. | `""` | +| `secondary.updateStrategy.type` | Update strategy type for the MySQL secondary statefulset | `RollingUpdate` | +| `secondary.podAnnotations` | Additional pod annotations for MySQL secondary pods | `{}` | +| `secondary.podAffinityPreset` | MySQL secondary pod affinity preset. Ignored if `secondary.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `secondary.podAntiAffinityPreset` | MySQL secondary pod anti-affinity preset. Ignored if `secondary.affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `secondary.nodeAffinityPreset.type` | MySQL secondary node affinity preset type. Ignored if `secondary.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `secondary.nodeAffinityPreset.key` | MySQL secondary node label key to match Ignored if `secondary.affinity` is set. | `""` | +| `secondary.nodeAffinityPreset.values` | MySQL secondary node label values to match. Ignored if `secondary.affinity` is set. | `[]` | +| `secondary.affinity` | Affinity for MySQL secondary pods assignment | `{}` | +| `secondary.nodeSelector` | Node labels for MySQL secondary pods assignment | `{}` | +| `secondary.tolerations` | Tolerations for MySQL secondary pods assignment | `[]` | +| `secondary.priorityClassName` | MySQL secondary pods' priorityClassName | `""` | +| `secondary.runtimeClassName` | MySQL secondary pods' runtimeClassName | `""` | +| `secondary.schedulerName` | Name of the k8s scheduler (other than default) | `""` | +| `secondary.terminationGracePeriodSeconds` | In seconds, time the given to the MySQL secondary pod needs to terminate gracefully | `""` | +| `secondary.topologySpreadConstraints` | Topology Spread Constraints for pod assignment | `[]` | +| `secondary.podManagementPolicy` | podManagementPolicy to manage scaling operation of MySQL secondary pods | `""` | +| `secondary.podSecurityContext.enabled` | Enable security context for MySQL secondary pods | `true` | +| `secondary.podSecurityContext.fsGroup` | Group ID for the mounted volumes' filesystem | `1001` | +| `secondary.containerSecurityContext.enabled` | MySQL secondary container securityContext | `true` | +| `secondary.containerSecurityContext.runAsUser` | User ID for the MySQL secondary container | `1001` | +| `secondary.containerSecurityContext.runAsNonRoot` | Set MySQL secondary container's Security Context runAsNonRoot | `true` | +| `secondary.containerSecurityContext.allowPrivilegeEscalation` | Set container's privilege escalation | `false` | +| `secondary.containerSecurityContext.capabilities.drop` | Set container's Security Context runAsNonRoot | `["ALL"]` | +| `secondary.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `secondary.resources.limits` | The resources limits for MySQL secondary containers | `{}` | +| `secondary.resources.requests` | The requested resources for MySQL secondary containers | `{}` | +| `secondary.livenessProbe.enabled` | Enable livenessProbe | `true` | +| `secondary.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `5` | +| `secondary.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `secondary.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `1` | +| `secondary.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `3` | +| `secondary.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `secondary.readinessProbe.enabled` | Enable readinessProbe | `true` | +| `secondary.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `secondary.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `secondary.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `1` | +| `secondary.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `3` | +| `secondary.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `secondary.startupProbe.enabled` | Enable startupProbe | `true` | +| `secondary.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `15` | +| `secondary.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `secondary.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `1` | +| `secondary.startupProbe.failureThreshold` | Failure threshold for startupProbe | `15` | +| `secondary.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `secondary.customLivenessProbe` | Override default liveness probe for MySQL secondary containers | `{}` | +| `secondary.customReadinessProbe` | Override default readiness probe for MySQL secondary containers | `{}` | +| `secondary.customStartupProbe` | Override default startup probe for MySQL secondary containers | `{}` | +| `secondary.extraFlags` | MySQL secondary additional command line flags | `""` | +| `secondary.extraEnvVars` | An array to add extra environment variables on MySQL secondary containers | `[]` | +| `secondary.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for MySQL secondary containers | `""` | +| `secondary.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for MySQL secondary containers | `""` | +| `secondary.extraPodSpec` | Optionally specify extra PodSpec for the MySQL Secondary pod(s) | `{}` | +| `secondary.extraPorts` | Extra ports to expose | `[]` | +| `secondary.persistence.enabled` | Enable persistence on MySQL secondary replicas using a `PersistentVolumeClaim` | `true` | +| `secondary.persistence.existingClaim` | Name of an existing `PersistentVolumeClaim` for MySQL secondary replicas | `""` | +| `secondary.persistence.subPath` | The name of a volume's sub path to mount for persistence | `""` | +| `secondary.persistence.storageClass` | MySQL secondary persistent volume storage Class | `""` | +| `secondary.persistence.annotations` | MySQL secondary persistent volume claim annotations | `{}` | +| `secondary.persistence.accessModes` | MySQL secondary persistent volume access Modes | `["ReadWriteOnce"]` | +| `secondary.persistence.size` | MySQL secondary persistent volume size | `8Gi` | +| `secondary.persistence.selector` | Selector to match an existing Persistent Volume | `{}` | +| `secondary.persistentVolumeClaimRetentionPolicy.enabled` | Enable Persistent volume retention policy for read only StatefulSet | `false` | +| `secondary.persistentVolumeClaimRetentionPolicy.whenScaled` | Volume retention behavior when the replica count of the StatefulSet is reduced | `Retain` | +| `secondary.persistentVolumeClaimRetentionPolicy.whenDeleted` | Volume retention behavior that applies when the StatefulSet is deleted | `Retain` | +| `secondary.extraVolumes` | Optionally specify extra list of additional volumes to the MySQL secondary pod(s) | `[]` | +| `secondary.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the MySQL secondary container(s) | `[]` | +| `secondary.initContainers` | Add additional init containers for the MySQL secondary pod(s) | `[]` | +| `secondary.sidecars` | Add additional sidecar containers for the MySQL secondary pod(s) | `[]` | +| `secondary.service.type` | MySQL secondary Kubernetes service type | `ClusterIP` | +| `secondary.service.ports.mysql` | MySQL secondary Kubernetes service port | `3306` | +| `secondary.service.nodePorts.mysql` | MySQL secondary Kubernetes service node port | `""` | +| `secondary.service.clusterIP` | MySQL secondary Kubernetes service clusterIP IP | `""` | +| `secondary.service.loadBalancerIP` | MySQL secondary loadBalancerIP if service type is `LoadBalancer` | `""` | +| `secondary.service.externalTrafficPolicy` | Enable client source IP preservation | `Cluster` | +| `secondary.service.loadBalancerSourceRanges` | Addresses that are allowed when MySQL secondary service is LoadBalancer | `[]` | +| `secondary.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `secondary.service.annotations` | Additional custom annotations for MySQL secondary service | `{}` | +| `secondary.service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` | +| `secondary.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `secondary.service.headless.annotations` | Additional custom annotations for headless MySQL secondary service. | `{}` | +| `secondary.pdb.create` | Enable/disable a Pod Disruption Budget creation for MySQL secondary pods | `false` | +| `secondary.pdb.minAvailable` | Minimum number/percentage of MySQL secondary pods that should remain scheduled | `1` | +| `secondary.pdb.maxUnavailable` | Maximum number/percentage of MySQL secondary pods that may be made unavailable | `""` | +| `secondary.podLabels` | Additional pod labels for MySQL secondary pods | `{}` | + +### RBAC parameters + +| Name | Description | Value | +| --------------------------------------------- | -------------------------------------------------------------- | ------- | +| `serviceAccount.create` | Enable the creation of a ServiceAccount for MySQL pods | `true` | +| `serviceAccount.name` | Name of the created ServiceAccount | `""` | +| `serviceAccount.annotations` | Annotations for MySQL Service Account | `{}` | +| `serviceAccount.automountServiceAccountToken` | Automount service account token for the server service account | `true` | +| `rbac.create` | Whether to create & use RBAC resources or not | `false` | +| `rbac.rules` | Custom RBAC rules to set | `[]` | + +### Network Policy + +| Name | Description | Value | +| ------------------------------------------ | --------------------------------------------------------------------------------------------------------------- | ------- | +| `networkPolicy.enabled` | Enable creation of NetworkPolicy resources | `false` | +| `networkPolicy.allowExternal` | The Policy model to apply. | `true` | +| `networkPolicy.explicitNamespacesSelector` | A Kubernetes LabelSelector to explicitly select namespaces from which ingress traffic could be allowed to MySQL | `{}` | + +### Volume Permissions parameters + +| Name | Description | Value | +| ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | +| `volumePermissions.enabled` | Enable init container that changes the owner and group of the persistent volume(s) mountpoint to `runAsUser:fsGroup` | `false` | +| `volumePermissions.image.registry` | Init container volume-permissions image registry | `REGISTRY_NAME` | +| `volumePermissions.image.repository` | Init container volume-permissions image repository | `REPOSITORY_NAME/os-shell` | +| `volumePermissions.image.digest` | Init container volume-permissions image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `volumePermissions.image.pullPolicy` | Init container volume-permissions image pull policy | `IfNotPresent` | +| `volumePermissions.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `volumePermissions.resources` | Init container volume-permissions resources | `{}` | + +### Metrics parameters + +| Name | Description | Value | +| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | --------------------------------- | +| `metrics.enabled` | Start a side-car prometheus exporter | `false` | +| `metrics.image.registry` | Exporter image registry | `REGISTRY_NAME` | +| `metrics.image.repository` | Exporter image repository | `REPOSITORY_NAME/mysqld-exporter` | +| `metrics.image.digest` | Exporter image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `metrics.image.pullPolicy` | Exporter image pull policy | `IfNotPresent` | +| `metrics.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `metrics.containerSecurityContext.enabled` | MySQL metrics container securityContext | `true` | +| `metrics.containerSecurityContext.runAsUser` | User ID for the MySQL metrics container | `1001` | +| `metrics.containerSecurityContext.runAsNonRoot` | Set MySQL metrics container's Security Context runAsNonRoot | `true` | +| `metrics.service.type` | Kubernetes service type for MySQL Prometheus Exporter | `ClusterIP` | +| `metrics.service.clusterIP` | Kubernetes service clusterIP for MySQL Prometheus Exporter | `""` | +| `metrics.service.port` | MySQL Prometheus Exporter service port | `9104` | +| `metrics.service.annotations` | Prometheus exporter service annotations | `{}` | +| `metrics.extraArgs.primary` | Extra args to be passed to mysqld_exporter on Primary pods | `[]` | +| `metrics.extraArgs.secondary` | Extra args to be passed to mysqld_exporter on Secondary pods | `[]` | +| `metrics.resources.limits` | The resources limits for MySQL prometheus exporter containers | `{}` | +| `metrics.resources.requests` | The requested resources for MySQL prometheus exporter containers | `{}` | +| `metrics.livenessProbe.enabled` | Enable livenessProbe | `true` | +| `metrics.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `120` | +| `metrics.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `metrics.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `1` | +| `metrics.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `3` | +| `metrics.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `metrics.readinessProbe.enabled` | Enable readinessProbe | `true` | +| `metrics.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `30` | +| `metrics.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `metrics.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `1` | +| `metrics.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `3` | +| `metrics.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `metrics.serviceMonitor.enabled` | Create ServiceMonitor Resource for scraping metrics using PrometheusOperator | `false` | +| `metrics.serviceMonitor.namespace` | Specify the namespace in which the serviceMonitor resource will be created | `""` | +| `metrics.serviceMonitor.jobLabel` | The name of the label on the target service to use as the job name in prometheus. | `""` | +| `metrics.serviceMonitor.interval` | Specify the interval at which metrics should be scraped | `30s` | +| `metrics.serviceMonitor.scrapeTimeout` | Specify the timeout after which the scrape is ended | `""` | +| `metrics.serviceMonitor.relabelings` | RelabelConfigs to apply to samples before scraping | `[]` | +| `metrics.serviceMonitor.metricRelabelings` | MetricRelabelConfigs to apply to samples before ingestion | `[]` | +| `metrics.serviceMonitor.selector` | ServiceMonitor selector labels | `{}` | +| `metrics.serviceMonitor.honorLabels` | Specify honorLabels parameter to add the scrape endpoint | `false` | +| `metrics.serviceMonitor.labels` | Used to pass Labels that are used by the Prometheus installed in your cluster to select Service Monitors to work with | `{}` | +| `metrics.serviceMonitor.annotations` | ServiceMonitor annotations | `{}` | +| `metrics.prometheusRule.enabled` | Creates a Prometheus Operator prometheusRule (also requires `metrics.enabled` to be `true` and `metrics.prometheusRule.rules`) | `false` | +| `metrics.prometheusRule.namespace` | Namespace for the prometheusRule Resource (defaults to the Release Namespace) | `""` | +| `metrics.prometheusRule.additionalLabels` | Additional labels that can be used so prometheusRule will be discovered by Prometheus | `{}` | +| `metrics.prometheusRule.rules` | Prometheus Rule definitions | `[]` | + +The above parameters map to the env variables defined in [bitnami/mysql](https://github.com/bitnami/containers/tree/main/bitnami/mysql). For more information please refer to the [bitnami/mysql](https://github.com/bitnami/containers/tree/main/bitnami/mysql) image documentation. + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +helm install my-release \ + --set auth.rootPassword=secretpassword,auth.database=app_database \ + oci://REGISTRY_NAME/REPOSITORY_NAME/mysql +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The above command sets the MySQL `root` account password to `secretpassword`. Additionally it creates a database named `app_database`. + +> NOTE: Once this chart is deployed, it is not possible to change the application's access credentials, such as usernames or passwords, using Helm. To change these application credentials after deployment, delete any persistent volumes (PVs) used by the chart and re-deploy it, or use the application's built-in administrative tools if available. + +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 oci://REGISTRY_NAME/REPOSITORY_NAME/mysql +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> **Tip**: You can use the default [values.yaml](https://github.com/bitnami/charts/tree/main/bitnami/mysql/values.yaml) + +## Configuration and installation details + +### [Rolling VS Immutable tags](https://docs.bitnami.com/tutorials/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. + +### Use a different MySQL version + +To modify the application version used in this chart, specify a different version of the image using the `image.tag` parameter and/or a different repository using the `image.repository` parameter. Refer to the [chart documentation for more information on these parameters and how to use them with images from a private registry](https://docs.bitnami.com/kubernetes/infrastructure/mysql/configuration/change-image-version/). + +### Customize a new MySQL instance + +The [Bitnami MySQL](https://github.com/bitnami/containers/tree/main/bitnami/mysql) image allows you to use your custom scripts to initialize a fresh instance. Custom scripts may be specified using the `initdbScripts` parameter. Alternatively, an external ConfigMap may be created with all the initialization scripts and the ConfigMap passed to the chart via the `initdbScriptsConfigMap` parameter. Note that this will override the `initdbScripts` parameter. + +The allowed extensions are `.sh`, `.sql` and `.sql.gz`. + +These scripts are treated differently depending on their extension. While `.sh` scripts are executed on all the nodes, `.sql` and `.sql.gz` scripts are only executed on the primary nodes. This is because `.sh` scripts support conditional tests to identify the type of node they are running on, while such tests are not supported in `.sql` or `sql.gz` files. + +Refer to the [chart documentation for more information and a usage example](https://docs.bitnami.com/kubernetes/infrastructure/mysql/configuration/customize-new-instance/). + +### Sidecars and Init Containers + +If you have a need for additional containers to run within the same pod as MySQL, you can do so via the `sidecars` config parameter. Simply define your container according to the Kubernetes container spec. + +```yaml +sidecars: + - name: your-image-name + image: your-image + imagePullPolicy: Always + ports: + - name: portname + containerPort: 1234 +``` + +Similarly, you can add extra init containers using the `initContainers` parameter. + +```yaml +initContainers: + - name: your-image-name + image: your-image + imagePullPolicy: Always + ports: + - name: portname + containerPort: 1234 +``` + +## Persistence + +The [Bitnami MySQL](https://github.com/bitnami/containers/tree/main/bitnami/mysql) image stores the MySQL data and configurations at the `/bitnami/mysql` path of the container. + +The chart mounts a [Persistent Volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) volume at this location. The volume is created using dynamic volume provisioning by default. An existing PersistentVolumeClaim can also be defined for this purpose. + +If you encounter errors when working with persistent volumes, refer to our [troubleshooting guide for persistent volumes](https://docs.bitnami.com/kubernetes/faq/troubleshooting/troubleshooting-persistence-volumes/). + +## Network Policy config + +To enable network policy for MySQL, 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 3306. + +For more precise policy, set `networkPolicy.allowExternal=false`. This will only allow pods with the generated client label to connect to MySQL. +This label will be displayed in the output of a successful install. + +## Pod affinity + +This chart allows you to set your custom affinity using the `XXX.affinity` parameter(s). Find more information about Pod affinity in the [Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). + +As an alternative, you can use the preset configurations for pod affinity, pod anti-affinity, and node affinity available at the [bitnami/common](https://github.com/bitnami/charts/tree/main/bitnami/common#affinities) chart. To do so, set the `XXX.podAffinityPreset`, `XXX.podAntiAffinityPreset`, or `XXX.nodeAffinityPreset` parameters. + +## Troubleshooting + +Find more information about how to deal with common errors related to Bitnami's Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues). + +## Upgrading + +It's necessary to set the `auth.rootPassword` parameter when upgrading for readiness/liveness probes to work properly. When you install this chart for the first time, some notes will be displayed providing the credentials you must use under the 'Administrator credentials' section. Please note down the password and run the command below to upgrade your chart: + +```console +helm upgrade my-release oci://REGISTRY_NAME/REPOSITORY_NAME/mysql --set auth.rootPassword=[ROOT_PASSWORD] +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +| Note: you need to substitute the placeholder _[ROOT_PASSWORD]_ with the value obtained in the installation notes. + +### To 9.0.0 + +This major release renames several values in this chart and adds missing features, in order to be aligned with the rest of the assets in the Bitnami charts repository. + +Affected values: + +- `schedulerName` was renamed as `primary.schedulerName` and `secondary.schedulerName`. +- The way how passwords are handled has been refactored and value `auth.forcePassword` has been removed. Now, the password configuration will have the following priority: + 1. Search for an already existing 'Secret' resource and reuse previous password. + 2. Password provided via the values.yaml + 3. If no secret existed, and no password was provided, the bitnami/mysql chart will set a randomly generated password. +- `primary.service.port` was renamed as `primary.service.ports.mysql`. +- `secondary.service.port` was renamed as `secondary.service.ports.mysql`. +- `primary.service.nodePort` was renamed as `primary.service.nodePorts.mysql`. +- `secondary.service.nodePort` was renamed as `secondary.service.nodePorts.mysql`. +- `primary.updateStrategy` and `secondary.updateStrategy` are now interpreted as an object and not a string. +- Values `primary.rollingUpdatePartition` and `secondary.rollingUpdatePartition` have been removed. In cases were they are needed, they can be set inside `.*updateStrategy`. +- `primary.pdb.enabled` was renamed as `primary.pdb.create`. +- `secondary.pdb.enabled` was renamed as `secondary.pdb.create`. +- `metrics.serviceMonitor.additionalLabels` was renamed as `metrics.serviceMonitor.labels` +- `metrics.serviceMonitor.relabellings` was removed, previously used to configured `metricRelabelings` field. We introduced two new values: `metrics.serviceMonitor.relabelings` and `metrics.serviceMonitor.metricRelabelings` that can be used to configured the serviceMonitor homonimous field. + +### To 8.0.0 + +- Several parameters were renamed or disappeared in favor of new ones on this major version: + - The terms _master_ and _slave_ have been replaced by the terms _primary_ and _secondary_. Therefore, parameters prefixed with `master` or `slave` are now prefixed with `primary` or `secondary`, respectively. + - Credentials parameters are reorganized under the `auth` parameter. + - `replication.enabled` parameter is deprecated in favor of `architecture` parameter that accepts two values: `standalone` and `replication`. +- Chart labels were adapted to follow the [Helm charts standard labels](https://helm.sh/docs/chart_best_practices/labels/#standard-labels). +- This version also introduces `bitnami/common`, a [library chart](https://helm.sh/docs/topics/library_charts/#helm) as a dependency. More documentation about this new utility could be found [here](https://github.com/bitnami/charts/tree/main/bitnami/common#bitnami-common-library-chart). Please, make sure that you have updated the chart dependencies before executing any upgrade. + +Consequences: + +- Backwards compatibility is not guaranteed. To upgrade to `8.0.0`, install a new release of the MySQL chart, and migrate the data from your previous release. You have 2 alternatives to do so: + - Create a backup of the database, and restore it on the new release using tools such as [mysqldump](https://dev.mysql.com/doc/refman/8.0/en/mysqldump.html). + - Reuse the PVC used to hold the master data on your previous release. To do so, use the `primary.persistence.existingClaim` parameter. The following example assumes that the release name is `mysql`: + +```console +helm install mysql oci://REGISTRY_NAME/REPOSITORY_NAME/mysql --set auth.rootPassword=[ROOT_PASSWORD] --set primary.persistence.existingClaim=[EXISTING_PVC] +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +| Note: you need to substitute the placeholder _[EXISTING_PVC]_ with the name of the PVC used on your previous release, and _[ROOT_PASSWORD]_ with the root password used in your previous release. + +### To 7.0.0 + +[On November 13, 2020, Helm v2 support formally ended](https://github.com/helm/charts#status-of-the-project). This major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +[Learn more about this change and related upgrade considerations](https://docs.bitnami.com/kubernetes/infrastructure/mysql/administration/upgrade-helm3/). + +### To 3.0.0 + +Backwards compatibility is not guaranteed unless you modify the labels used on the chart's deployments. +Use the workaround below to upgrade from versions previous to 3.0.0. The following example assumes that the release name is mysql: + +```console +kubectl delete statefulset mysql-master --cascade=false +kubectl delete statefulset mysql-slave --cascade=false +``` + +## License + +Copyright © 2024 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/backing-services/mysql/auction-onsite-alpha.values.yaml b/backing-services/mysql/auction-onsite-alpha.values.yaml new file mode 100644 index 0000000..7fb07ca --- /dev/null +++ b/backing-services/mysql/auction-onsite-alpha.values.yaml @@ -0,0 +1,17 @@ +global: + imageRegistry: "" + imagePullSecrets: [] + storageClass: "" + +auth: + rootPassword: "secret123" + createDatabase: true + database: "my_database" + username: "admin" + password: "secret123" + replicationUser: replicator + replicationPassword: "" + existingSecret: "" + usePasswordFiles: false + customPasswordFiles: {} + defaultAuthenticationPlugin: "" \ No newline at end of file diff --git a/backing-services/mysql/auction-stage-eks.values.yaml b/backing-services/mysql/auction-stage-eks.values.yaml new file mode 100644 index 0000000..43fb07c --- /dev/null +++ b/backing-services/mysql/auction-stage-eks.values.yaml @@ -0,0 +1,32 @@ +global: + imageRegistry: "" + imagePullSecrets: [] + storageClass: "" + +auth: + rootPassword: "secret123" + createDatabase: true + database: "my_database" + username: "admin" + password: "secret123" + replicationUser: replicator + replicationPassword: "" + existingSecret: "" + usePasswordFiles: false + customPasswordFiles: {} + defaultAuthenticationPlugin: "" + +primary: + service: + type: LoadBalancer + annotations: + service.beta.kubernetes.io/aws-load-balancer-type: "nlb" + service.beta.kubernetes.io/aws-load-balancer-type: external + service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing + service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: instance + +serviceAccount: + create: true + name: "mysqlserviceaccount" + annotations: + eks.amazonaws.com/role-arn: "arn:aws:iam::667294666490:role/auction-cluster-20241126163757775000000001" \ No newline at end of file diff --git a/backing-services/mysql/charts/common-2.14.1.tgz b/backing-services/mysql/charts/common-2.14.1.tgz new file mode 100644 index 0000000..f443a7c Binary files /dev/null and b/backing-services/mysql/charts/common-2.14.1.tgz differ diff --git a/backing-services/mysql/hospital-afta.yaml b/backing-services/mysql/hospital-afta.yaml new file mode 100644 index 0000000..03ebbf7 --- /dev/null +++ b/backing-services/mysql/hospital-afta.yaml @@ -0,0 +1,30 @@ +image: + registry: docker.io + repository: bitnami/mysql + tag: 8.0.35-debian-11-r2 + pullPolicy: IfNotPresent + +global: + imageRegistry: "" + imagePullSecrets: [] + storageClass: "" + resources: + limits: + cpu: 1000m + memory: 512Mi + requests: + cpu: 1000m + memory: 512Mi + +auth: + rootPassword: "secret123" + createDatabase: true + database: "my_database" + username: "admin" + password: "secret123" + replicationUser: replicator + replicationPassword: "" + existingSecret: "" + usePasswordFiles: false + customPasswordFiles: {} + defaultAuthenticationPlugin: "" \ No newline at end of file diff --git a/backing-services/mysql/hospital-bahman-production.values.yaml b/backing-services/mysql/hospital-bahman-production.values.yaml new file mode 100644 index 0000000..b82e5b3 --- /dev/null +++ b/backing-services/mysql/hospital-bahman-production.values.yaml @@ -0,0 +1,23 @@ +image: + registry: 172.16.16.1:30516 + repository: bitnami/mysql + tag: 8.0.35-debian-11-r2 + pullPolicy: IfNotPresent + +global: + imageRegistry: "" + imagePullSecrets: [] + storageClass: "" + +auth: + rootPassword: "secret123" + createDatabase: true + database: "my_database" + username: "admin" + password: "secret123" + replicationUser: replicator + replicationPassword: "" + existingSecret: "" + usePasswordFiles: false + customPasswordFiles: {} + defaultAuthenticationPlugin: "" \ No newline at end of file diff --git a/backing-services/mysql/hospital-bahman.values.yaml b/backing-services/mysql/hospital-bahman.values.yaml new file mode 100644 index 0000000..7fb07ca --- /dev/null +++ b/backing-services/mysql/hospital-bahman.values.yaml @@ -0,0 +1,17 @@ +global: + imageRegistry: "" + imagePullSecrets: [] + storageClass: "" + +auth: + rootPassword: "secret123" + createDatabase: true + database: "my_database" + username: "admin" + password: "secret123" + replicationUser: replicator + replicationPassword: "" + existingSecret: "" + usePasswordFiles: false + customPasswordFiles: {} + defaultAuthenticationPlugin: "" \ No newline at end of file diff --git a/backing-services/mysql/ride-stage-tavana.values.yaml b/backing-services/mysql/ride-stage-tavana.values.yaml new file mode 100644 index 0000000..5393f04 --- /dev/null +++ b/backing-services/mysql/ride-stage-tavana.values.yaml @@ -0,0 +1,22 @@ +global: + imageRegistry: "" + imagePullSecrets: [] + storageClass: "" + +auth: + rootPassword: "secret123" + createDatabase: true + database: "my_database" + username: "admin" + password: "secret123" + replicationUser: replicator + replicationPassword: "" + existingSecret: "" + usePasswordFiles: false + customPasswordFiles: {} + defaultAuthenticationPlugin: "" + +primary: + service: + nodePorts: + mysql: 30307 \ No newline at end of file diff --git a/backing-services/mysql/schoobus-onsite.values.yaml b/backing-services/mysql/schoobus-onsite.values.yaml new file mode 100644 index 0000000..65c26bb --- /dev/null +++ b/backing-services/mysql/schoobus-onsite.values.yaml @@ -0,0 +1,37 @@ +global: + imageRegistry: "" + imagePullSecrets: [] + storageClass: "" + +image: + registry: 192.168.2.43:31898 + +architecture: replication +clusterDomain: mysql-school-onsite-headless + +auth: + rootPassword: "secret123" + createDatabase: true + database: "my_database" + username: "admin" + password: "secret123" + replicationUser: replicator + replicationPassword: "secret123" + existingSecret: "" + usePasswordFiles: false + customPasswordFiles: {} + defaultAuthenticationPlugin: "" + +replication: + enabled: true + replicaCount: 2 + +primary: + service: + nodePorts: + mysql: 30336 + +secondary: + service: + nodePorts: + mysql: 30337 \ No newline at end of file diff --git a/backing-services/mysql/school-stage-tavana.values.yaml b/backing-services/mysql/school-stage-tavana.values.yaml new file mode 100644 index 0000000..a16877a --- /dev/null +++ b/backing-services/mysql/school-stage-tavana.values.yaml @@ -0,0 +1,34 @@ +global: + imageRegistry: "" + imagePullSecrets: [] + storageClass: "" + +architecture: replication +clusterDomain: mysql-school-stage-headless + +auth: + rootPassword: "secret123" + createDatabase: true + database: "my_database" + username: "admin" + password: "secret123" + replicationUser: replicator + replicationPassword: "secret123" + existingSecret: "" + usePasswordFiles: false + customPasswordFiles: {} + defaultAuthenticationPlugin: "" + +replication: + enabled: false + replicaCount: 2 + +primary: + service: + nodePorts: + mysql: 30336 + +secondary: + service: + nodePorts: + mysql: 30337 \ No newline at end of file diff --git a/backing-services/mysql/schoolbus-demo.values.yaml b/backing-services/mysql/schoolbus-demo.values.yaml new file mode 100644 index 0000000..a3f1b97 --- /dev/null +++ b/backing-services/mysql/schoolbus-demo.values.yaml @@ -0,0 +1,41 @@ +global: + imageRegistry: "" + imagePullSecrets: [] + storageClass: "" + +architecture: standalone #replication +clusterDomain: mysql-school-stage-headless + +auth: + rootPassword: "secret123" + createDatabase: true + database: "my_database" + username: "admin" + password: "secret123" + replicationUser: replicator + replicationPassword: "secret123" + existingSecret: "" + usePasswordFiles: false + customPasswordFiles: {} + defaultAuthenticationPlugin: "" + +replication: + enabled: false + replicaCount: 1 + +primary: + service: + nodePorts: + mysql: 30336 + resources: + limits: + cpu: 1000m + memory: 1G + requests: + cpu: 1000m + memory: 1G + +secondary: + service: + nodePorts: + mysql: 30337 \ No newline at end of file diff --git a/backing-services/mysql/templates/NOTES.txt b/backing-services/mysql/templates/NOTES.txt new file mode 100644 index 0000000..ecf604c --- /dev/null +++ b/backing-services/mysql/templates/NOTES.txt @@ -0,0 +1,75 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +** Please be patient while the chart is being deployed ** + +{{- if .Values.diagnosticMode.enabled }} +The chart has been deployed in diagnostic mode. All probes have been disabled and the command has been overwritten with: + + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 4 }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 4 }} + +Get the list of pods by executing: + + kubectl get pods --namespace {{ include "common.names.namespace" . }} -l app.kubernetes.io/instance={{ .Release.Name }} + +Access the pod you want to debug by executing + + kubectl exec --namespace {{ include "common.names.namespace" . }} -ti -- bash + +In order to replicate the container startup scripts execute this command: + + /opt/bitnami/scripts/mysql/entrypoint.sh /opt/bitnami/scripts/mysql/run.sh + +{{- else }} + +Tip: + + Watch the deployment status using the command: kubectl get pods -w --namespace {{ include "common.names.namespace" . }} + +Services: + + echo Primary: {{ include "mysql.primary.fullname" . }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}:{{ .Values.primary.service.ports.mysql }} +{{- if eq .Values.architecture "replication" }} + echo Secondary: {{ include "mysql.secondary.fullname" . }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}:{{ .Values.secondary.service.ports.mysql }} +{{- end }} + +Execute the following to get the administrator credentials: + + echo Username: root + MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace {{ include "common.names.namespace" . }} {{ template "mysql.secretName" . }} -o jsonpath="{.data.mysql-root-password}" | base64 -d) + +To connect to your database: + + 1. Run a pod that you can use as a client: + + kubectl run {{ include "common.names.fullname" . }}-client --rm --tty -i --restart='Never' --image {{ template "mysql.image" . }} --namespace {{ include "common.names.namespace" . }} --env MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD --command -- bash + + 2. To connect to primary service (read/write): + + mysql -h {{ include "mysql.primary.fullname" . }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }} -uroot -p"$MYSQL_ROOT_PASSWORD" + +{{- if eq .Values.architecture "replication" }} + + 3. To connect to secondary service (read-only): + + mysql -h {{ include "mysql.secondary.fullname" . }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }} -uroot -p"$MYSQL_ROOT_PASSWORD" +{{- end }} + +{{ if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }} +Note: Since NetworkPolicy is enabled, only pods with label {{ template "common.names.fullname" . }}-client=true" will be able to connect to MySQL. +{{- end }} + +{{- if .Values.metrics.enabled }} + +To access the MySQL Prometheus metrics from outside the cluster execute the following commands: + + kubectl port-forward --namespace {{ include "common.names.namespace" . }} svc/{{ printf "%s-metrics" (include "common.names.fullname" .) }} {{ .Values.metrics.service.port }}:{{ .Values.metrics.service.port }} & + curl http://127.0.0.1:{{ .Values.metrics.service.port }}/metrics + +{{- end }} + +{{ include "mysql.validateValues" . }} +{{ include "mysql.checkRollingTags" . }} +{{- end }} diff --git a/backing-services/mysql/templates/_helpers.tpl b/backing-services/mysql/templates/_helpers.tpl new file mode 100644 index 0000000..6cad524 --- /dev/null +++ b/backing-services/mysql/templates/_helpers.tpl @@ -0,0 +1,177 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{- define "mysql.primary.fullname" -}} +{{- if eq .Values.architecture "replication" }} +{{- printf "%s-%s" (include "common.names.fullname" .) .Values.primary.name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- include "common.names.fullname" . -}} +{{- end -}} +{{- end -}} + +{{- define "mysql.secondary.fullname" -}} +{{- printf "%s-%s" (include "common.names.fullname" .) .Values.secondary.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Return the proper MySQL image name +*/}} +{{- define "mysql.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper metrics image name +*/}} +{{- define "mysql.metrics.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.metrics.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper image name (for the init container volume-permissions image) +*/}} +{{- define "mysql.volumePermissions.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.volumePermissions.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "mysql.imagePullSecrets" -}} +{{- include "common.images.pullSecrets" (dict "images" (list .Values.image .Values.metrics.image .Values.volumePermissions.image) "global" .Values.global) }} +{{- end -}} + +{{/* +Get the initialization scripts ConfigMap name. +*/}} +{{- define "mysql.initdbScriptsCM" -}} +{{- if .Values.initdbScriptsConfigMap -}} + {{- printf "%s" (tpl .Values.initdbScriptsConfigMap $) -}} +{{- else -}} + {{- printf "%s-init-scripts" (include "mysql.primary.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Get the startdb scripts ConfigMap name. +*/}} +{{- define "mysql.startdbScriptsCM" -}} +{{- if .Values.startdbScriptsConfigMap -}} + {{- printf "%s" (tpl .Values.startdbScriptsConfigMap $) -}} +{{- else -}} + {{- printf "%s-start-scripts" (include "mysql.primary.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* + Returns the proper service account name depending if an explicit service account name is set + in the values file. If the name is not set it will default to either mysql.fullname if serviceAccount.create + is true or default otherwise. +*/}} +{{- define "mysql.serviceAccountName" -}} + {{- if .Values.serviceAccount.create -}} + {{ default (include "common.names.fullname" .) .Values.serviceAccount.name }} + {{- else -}} + {{ default "default" .Values.serviceAccount.name }} + {{- end -}} +{{- end -}} + +{{/* +Return the configmap with the MySQL Primary configuration +*/}} +{{- define "mysql.primary.configmapName" -}} +{{- if .Values.primary.existingConfigmap -}} + {{- printf "%s" (tpl .Values.primary.existingConfigmap $) -}} +{{- else -}} + {{- printf "%s" (include "mysql.primary.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a configmap object should be created for MySQL Secondary +*/}} +{{- define "mysql.primary.createConfigmap" -}} +{{- if and .Values.primary.configuration (not .Values.primary.existingConfigmap) }} + {{- true -}} +{{- else -}} +{{- end -}} +{{- end -}} + +{{/* +Return the configmap with the MySQL Primary configuration +*/}} +{{- define "mysql.secondary.configmapName" -}} +{{- if .Values.secondary.existingConfigmap -}} + {{- printf "%s" (tpl .Values.secondary.existingConfigmap $) -}} +{{- else -}} + {{- printf "%s" (include "mysql.secondary.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a configmap object should be created for MySQL Secondary +*/}} +{{- define "mysql.secondary.createConfigmap" -}} +{{- if and (eq .Values.architecture "replication") .Values.secondary.configuration (not .Values.secondary.existingConfigmap) }} + {{- true -}} +{{- else -}} +{{- end -}} +{{- end -}} + +{{/* +Return the secret with MySQL credentials +*/}} +{{- define "mysql.secretName" -}} + {{- if .Values.auth.existingSecret -}} + {{- printf "%s" (tpl .Values.auth.existingSecret $) -}} + {{- else -}} + {{- printf "%s" (include "common.names.fullname" .) -}} + {{- end -}} +{{- end -}} + +{{/* +Return true if a secret object should be created for MySQL +*/}} +{{- define "mysql.createSecret" -}} +{{- if and (not .Values.auth.existingSecret) (not .Values.auth.customPasswordFiles) }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Returns the available value for certain key in an existing secret (if it exists), +otherwise it generates a random value. +*/}} +{{- define "getValueFromSecret" }} + {{- $len := (default 16 .Length) | int -}} + {{- $obj := (lookup "v1" "Secret" .Namespace .Name).data -}} + {{- if $obj }} + {{- index $obj .Key | b64dec -}} + {{- else -}} + {{- randAlphaNum $len -}} + {{- end -}} +{{- end }} + +{{/* Check if there are rolling tags in the images */}} +{{- define "mysql.checkRollingTags" -}} +{{- include "common.warnings.rollingTag" .Values.image }} +{{- include "common.warnings.rollingTag" .Values.metrics.image }} +{{- include "common.warnings.rollingTag" .Values.volumePermissions.image }} +{{- end -}} + +{{/* +Compile all warnings into a single message, and call fail. +*/}} +{{- define "mysql.validateValues" -}} +{{- $messages := list -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/mysql/templates/extra-list.yaml b/backing-services/mysql/templates/extra-list.yaml new file mode 100644 index 0000000..2d35a58 --- /dev/null +++ b/backing-services/mysql/templates/extra-list.yaml @@ -0,0 +1,9 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/backing-services/mysql/templates/metrics-svc.yaml b/backing-services/mysql/templates/metrics-svc.yaml new file mode 100644 index 0000000..7b49ef1 --- /dev/null +++ b/backing-services/mysql/templates/metrics-svc.yaml @@ -0,0 +1,29 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.metrics.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-metrics" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: metrics + {{- if or .Values.metrics.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.metrics.service.type }} + {{- if and .Values.metrics.service.clusterIP (eq .Values.metrics.service.type "ClusterIP") }} + clusterIP: {{ .Values.metrics.service.clusterIP }} + {{- end }} + ports: + - port: {{ .Values.metrics.service.port }} + targetPort: metrics + protocol: TCP + name: metrics + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} +{{- end }} diff --git a/backing-services/mysql/templates/networkpolicy.yaml b/backing-services/mysql/templates/networkpolicy.yaml new file mode 100644 index 0000000..2b076bd --- /dev/null +++ b/backing-services/mysql/templates/networkpolicy.yaml @@ -0,0 +1,40 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ template "common.capabilities.networkPolicy.apiVersion" . }} +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + ingress: + # Allow inbound connections + - ports: + - port: {{ .Values.primary.service.ports.mysql }} + {{- if not .Values.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: + {{ template "common.names.fullname" . }}-client: "true" + {{- if .Values.networkPolicy.explicitNamespacesSelector }} + namespaceSelector: +{{ toYaml .Values.networkPolicy.explicitNamespacesSelector | indent 12 }} + {{- end }} + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }} + {{- end }} + {{- if .Values.metrics.enabled }} + # Allow prometheus scrapes + - ports: + - port: 9104 + {{- end }} +{{- end }} diff --git a/backing-services/mysql/templates/primary/configmap.yaml b/backing-services/mysql/templates/primary/configmap.yaml new file mode 100644 index 0000000..5acefa1 --- /dev/null +++ b/backing-services/mysql/templates/primary/configmap.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mysql.primary.createConfigmap" .) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "mysql.primary.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: primary + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + my.cnf: |- + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.configuration "context" $ ) | nindent 4 }} +{{- end -}} diff --git a/backing-services/mysql/templates/primary/initialization-configmap.yaml b/backing-services/mysql/templates/primary/initialization-configmap.yaml new file mode 100644 index 0000000..cae5cef --- /dev/null +++ b/backing-services/mysql/templates/primary/initialization-configmap.yaml @@ -0,0 +1,19 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.initdbScripts (not .Values.initdbScriptsConfigMap) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-init-scripts" (include "mysql.primary.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: primary + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: +{{- include "common.tplvalues.render" (dict "value" .Values.initdbScripts "context" .) | nindent 2 }} +{{- end }} diff --git a/backing-services/mysql/templates/primary/pdb.yaml b/backing-services/mysql/templates/primary/pdb.yaml new file mode 100644 index 0000000..91c2f73 --- /dev/null +++ b/backing-services/mysql/templates/primary/pdb.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.primary.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "mysql.primary.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: primary + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.primary.pdb.minAvailable }} + minAvailable: {{ .Values.primary.pdb.minAvailable }} + {{- end }} + {{- if .Values.primary.pdb.maxUnavailable }} + maxUnavailable: {{ .Values.primary.pdb.maxUnavailable }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: primary +{{- end }} diff --git a/backing-services/mysql/templates/primary/startdb-configmap.yaml b/backing-services/mysql/templates/primary/startdb-configmap.yaml new file mode 100644 index 0000000..cc8464a --- /dev/null +++ b/backing-services/mysql/templates/primary/startdb-configmap.yaml @@ -0,0 +1,21 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.startdbScripts (not .Values.startdbScriptsConfigMap) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-start-scripts" (include "mysql.primary.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: +{{- include "common.tplvalues.render" (dict "value" .Values.startdbScripts "context" .) | nindent 2 }} +{{- end }} diff --git a/backing-services/mysql/templates/primary/statefulset.yaml b/backing-services/mysql/templates/primary/statefulset.yaml new file mode 100644 index 0000000..b6702b7 --- /dev/null +++ b/backing-services/mysql/templates/primary/statefulset.yaml @@ -0,0 +1,399 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ include "mysql.primary.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: primary + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + replicas: 1 + podManagementPolicy: {{ .Values.primary.podManagementPolicy | quote }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: primary + serviceName: {{ include "mysql.primary.fullname" . }} + {{- if .Values.primary.updateStrategy }} + updateStrategy: {{- toYaml .Values.primary.updateStrategy | nindent 4 }} + {{- end }} + template: + metadata: + annotations: + {{- if (include "mysql.primary.createConfigmap" .) }} + checksum/configuration: {{ include (print $.Template.BasePath "/primary/configmap.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.primary.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.podAnnotations "context" $) | nindent 8 }} + {{- end }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: primary + spec: + {{- if .Values.primary.extraPodSpec }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.extraPodSpec "context" $) | nindent 6 }} + {{- end }} + serviceAccountName: {{ template "mysql.serviceAccountName" . }} + {{- include "mysql.imagePullSecrets" . | nindent 6 }} + {{- if .Values.primary.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.primary.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.primary.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.primary.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.primary.podAffinityPreset "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.primary.podAntiAffinityPreset "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.primary.nodeAffinityPreset.type "key" .Values.primary.nodeAffinityPreset.key "values" .Values.primary.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.primary.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.primary.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.primary.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.primary.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.primary.priorityClassName }} + priorityClassName: {{ .Values.primary.priorityClassName | quote }} + {{- end }} + {{- if .Values.primary.runtimeClassName }} + runtimeClassName: {{ .Values.primary.runtimeClassName | quote }} + {{- end }} + {{- if .Values.primary.schedulerName }} + schedulerName: {{ .Values.primary.schedulerName | quote }} + {{- end }} + {{- if .Values.primary.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.primary.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.primary.podSecurityContext.enabled }} + securityContext: {{- omit .Values.primary.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.primary.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.primary.terminationGracePeriodSeconds }} + {{- end }} + initContainers: + {{- if and .Values.primary.podSecurityContext.enabled .Values.volumePermissions.enabled .Values.primary.persistence.enabled }} + - name: volume-permissions + image: {{ include "mysql.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + - -ec + - | + mkdir -p "/bitnami/mysql" + chown "{{ .Values.primary.containerSecurityContext.runAsUser }}:{{ .Values.primary.podSecurityContext.fsGroup }}" "/bitnami/mysql" + find "/bitnami/mysql" -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | xargs -r chown -R "{{ .Values.primary.containerSecurityContext.runAsUser }}:{{ .Values.primary.podSecurityContext.fsGroup }}" + securityContext: + runAsUser: 0 + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: data + mountPath: /bitnami/mysql + {{- if .Values.primary.persistence.subPath }} + subPath: {{ .Values.primary.persistence.subPath }} + {{- end }} + {{- end }} + {{- if .Values.primary.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.initContainers "context" $) | nindent 8 }} + {{- end }} + containers: + - name: mysql + image: {{ include "mysql.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.primary.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.primary.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.primary.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.primary.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.primary.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.primary.args "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.primary.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.primary.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + {{- if .Values.auth.usePasswordFiles }} + - name: MYSQL_ROOT_PASSWORD_FILE + value: {{ default "/opt/bitnami/mysql/secrets/mysql-root-password" .Values.auth.customPasswordFiles.root }} + {{- else }} + - name: MYSQL_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "mysql.secretName" . }} + key: mysql-root-password + {{- end }} + {{- if not (empty .Values.auth.username) }} + - name: MYSQL_USER + value: {{ .Values.auth.username | quote }} + {{- if .Values.auth.usePasswordFiles }} + - name: MYSQL_PASSWORD_FILE + value: {{ default "/opt/bitnami/mysql/secrets/mysql-password" .Values.auth.customPasswordFiles.user }} + {{- else }} + - name: MYSQL_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "mysql.secretName" . }} + key: mysql-password + {{- end }} + {{- end }} + {{- if and .Values.auth.createDatabase .Values.auth.database }} + - name: MYSQL_DATABASE + value: {{ .Values.auth.database | quote }} + {{- end }} + {{- if eq .Values.architecture "replication" }} + - name: MYSQL_REPLICATION_MODE + value: "master" + - name: MYSQL_REPLICATION_USER + value: {{ .Values.auth.replicationUser | quote }} + {{- if .Values.auth.usePasswordFiles }} + - name: MYSQL_REPLICATION_PASSWORD_FILE + value: {{ default "/opt/bitnami/mysql/secrets/mysql-replication-password" .Values.auth.customPasswordFiles.replicator }} + {{- else }} + - name: MYSQL_REPLICATION_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "mysql.secretName" . }} + key: mysql-replication-password + {{- end }} + {{- end }} + {{- if .Values.primary.extraFlags }} + - name: MYSQL_EXTRA_FLAGS + value: "{{ .Values.primary.extraFlags }}" + {{- end }} + {{- if .Values.primary.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.primary.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.primary.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.primary.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.primary.extraEnvVarsSecret "context" $) }} + {{- end }} + ports: + - name: mysql + containerPort: 3306 + {{- if .Values.primary.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.extraPorts "context" $) | nindent 12 }} + {{- end }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.primary.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.primary.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.primary.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.primary.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bin/bash + - -ec + - | + password_aux="${MYSQL_ROOT_PASSWORD:-}" + if [[ -f "${MYSQL_ROOT_PASSWORD_FILE:-}" ]]; then + password_aux=$(cat "$MYSQL_ROOT_PASSWORD_FILE") + fi + mysqladmin status -uroot -p"${password_aux}" + {{- end }} + {{- if .Values.primary.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.primary.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.primary.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.primary.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bin/bash + - -ec + - | + password_aux="${MYSQL_ROOT_PASSWORD:-}" + if [[ -f "${MYSQL_ROOT_PASSWORD_FILE:-}" ]]; then + password_aux=$(cat "$MYSQL_ROOT_PASSWORD_FILE") + fi + mysqladmin status -uroot -p"${password_aux}" + {{- end }} + {{- if .Values.primary.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.primary.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.primary.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.primary.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bin/bash + - -ec + - | + password_aux="${MYSQL_ROOT_PASSWORD:-}" + if [[ -f "${MYSQL_ROOT_PASSWORD_FILE:-}" ]]; then + password_aux=$(cat "$MYSQL_ROOT_PASSWORD_FILE") + fi + mysqladmin status -uroot -p"${password_aux}" + {{- end }} + {{- end }} + {{- if .Values.primary.resources }} + resources: {{ toYaml .Values.primary.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: data + mountPath: /bitnami/mysql + {{- if .Values.primary.persistence.subPath }} + subPath: {{ .Values.primary.persistence.subPath }} + {{- end }} + {{- if or .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + mountPath: /docker-entrypoint-initdb.d + {{- end }} + {{- if or .Values.startdbScriptsConfigMap .Values.startdbScripts }} + - name: custom-start-scripts + mountPath: /docker-entrypoint-startdb.d + {{- end }} + {{- if or .Values.primary.configuration .Values.primary.existingConfigmap }} + - name: config + mountPath: /opt/bitnami/mysql/conf/my.cnf + subPath: my.cnf + {{- end }} + {{- if and .Values.auth.usePasswordFiles (not .Values.auth.customPasswordFiles) }} + - name: mysql-credentials + mountPath: /opt/bitnami/mysql/secrets/ + {{- end }} + {{- if .Values.primary.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ include "mysql.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.metrics.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.metrics.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + env: + {{- if .Values.auth.usePasswordFiles }} + - name: MYSQL_ROOT_PASSWORD_FILE + value: {{ default "/opt/bitnami/mysqld-exporter/secrets/mysql-root-password" .Values.auth.customPasswordFiles.root }} + {{- else }} + - name: MYSQL_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mysql.secretName" . }} + key: mysql-root-password + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -ec + - | + password_aux="${MYSQL_ROOT_PASSWORD:-}" + if [[ -f "${MYSQL_ROOT_PASSWORD_FILE:-}" ]]; then + password_aux=$(cat "$MYSQL_ROOT_PASSWORD_FILE") + fi + MYSQLD_EXPORTER_PASSWORD=${password_aux} /bin/mysqld_exporter --mysqld.address=localhost:3306 --mysqld.username=root {{- range .Values.metrics.extraArgs.primary }} {{ . }} {{- end }} + {{- end }} + ports: + - name: metrics + containerPort: 9104 + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- omit .Values.metrics.livenessProbe "enabled" | toYaml | nindent 12 }} + httpGet: + path: /metrics + port: metrics + {{- end }} + {{- if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- omit .Values.metrics.readinessProbe "enabled" | toYaml | nindent 12 }} + httpGet: + path: /metrics + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- end }} + {{- if and .Values.auth.usePasswordFiles (not .Values.auth.customPasswordFiles) }} + volumeMounts: + - name: mysql-credentials + mountPath: /opt/bitnami/mysqld-exporter/secrets/ + {{- end }} + {{- end }} + {{- if .Values.primary.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + {{- if or .Values.primary.configuration .Values.primary.existingConfigmap }} + - name: config + configMap: + name: {{ include "mysql.primary.configmapName" . }} + {{- end }} + {{- if or .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + configMap: + name: {{ include "mysql.initdbScriptsCM" . }} + {{- end }} + {{- if or .Values.startdbScriptsConfigMap .Values.startdbScripts }} + - name: custom-start-scripts + configMap: + name: {{ include "mysql.startdbScriptsCM" . }} + {{- end }} + {{- if and .Values.auth.usePasswordFiles (not .Values.auth.customPasswordFiles) }} + - name: mysql-credentials + secret: + secretName: {{ include "mysql.secretName" . }} + items: + - key: mysql-root-password + path: mysql-root-password + - key: mysql-password + path: mysql-password + {{- if eq .Values.architecture "replication" }} + - key: mysql-replication-password + path: mysql-replication-password + {{- end }} + {{- end }} + {{- if .Values.primary.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.extraVolumes "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.primary.persistence.enabled .Values.primary.persistence.existingClaim }} + - name: data + persistentVolumeClaim: + claimName: {{ tpl .Values.primary.persistence.existingClaim . }} + {{- else if not .Values.primary.persistence.enabled }} + - name: data + emptyDir: {} + {{- else if and .Values.primary.persistence.enabled (not .Values.primary.persistence.existingClaim) }} + {{- if .Values.primary.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.primary.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.primary.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + volumeClaimTemplates: + - metadata: + name: data + labels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 10 }} + app.kubernetes.io/component: primary + {{- if or .Values.primary.persistence.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.persistence.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.primary.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.primary.persistence.size | quote }} + {{- include "common.storage.class" (dict "persistence" .Values.primary.persistence "global" .Values.global) | nindent 8 }} + {{- if .Values.primary.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.primary.persistence.selector "context" $) | nindent 10 }} + {{- end -}} + {{- end }} diff --git a/backing-services/mysql/templates/primary/svc-headless.yaml b/backing-services/mysql/templates/primary/svc-headless.yaml new file mode 100644 index 0000000..7e55bad --- /dev/null +++ b/backing-services/mysql/templates/primary/svc-headless.yaml @@ -0,0 +1,27 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mysql.primary.fullname" . }}-headless + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: primary + {{- if or .Values.primary.service.headless.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.service.headless.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + publishNotReadyAddresses: true + ports: + - name: mysql + port: {{ .Values.primary.service.ports.mysql }} + targetPort: mysql + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: primary diff --git a/backing-services/mysql/templates/primary/svc.yaml b/backing-services/mysql/templates/primary/svc.yaml new file mode 100644 index 0000000..407696d --- /dev/null +++ b/backing-services/mysql/templates/primary/svc.yaml @@ -0,0 +1,52 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mysql.primary.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: primary + {{- if or .Values.primary.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.primary.service.type }} + {{- if and .Values.primary.service.clusterIP (eq .Values.primary.service.type "ClusterIP") }} + clusterIP: {{ .Values.primary.service.clusterIP }} + {{- end }} + {{- if .Values.primary.service.sessionAffinity }} + sessionAffinity: {{ .Values.primary.service.sessionAffinity }} + {{- end }} + {{- if .Values.primary.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.primary.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + {{- if or (eq .Values.primary.service.type "LoadBalancer") (eq .Values.primary.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.primary.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.primary.service.type "LoadBalancer") (not (empty .Values.primary.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{- toYaml .Values.primary.service.loadBalancerSourceRanges | nindent 4}} + {{- end }} + {{- if and (eq .Values.primary.service.type "LoadBalancer") (not (empty .Values.primary.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.primary.service.loadBalancerIP }} + {{- end }} + ports: + - name: mysql + port: {{ .Values.primary.service.ports.mysql }} + protocol: TCP + targetPort: mysql + {{- if (and (or (eq .Values.primary.service.type "NodePort") (eq .Values.primary.service.type "LoadBalancer")) .Values.primary.service.nodePorts.mysql) }} + nodePort: {{ .Values.primary.service.nodePorts.mysql }} + {{- else if eq .Values.primary.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.primary.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: primary diff --git a/backing-services/mysql/templates/prometheusrule.yaml b/backing-services/mysql/templates/prometheusrule.yaml new file mode 100644 index 0000000..1facb08 --- /dev/null +++ b/backing-services/mysql/templates/prometheusrule.yaml @@ -0,0 +1,24 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ default .Release.Namespace .Values.metrics.prometheusRule.namespace }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: metrics + {{- if .Values.metrics.prometheusRule.additionalLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.prometheusRule.additionalLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + groups: + - name: {{ include "common.names.fullname" . }} + rules: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.prometheusRule.rules "context" $ ) | nindent 6 }} +{{- end }} diff --git a/backing-services/mysql/templates/role.yaml b/backing-services/mysql/templates/role.yaml new file mode 100644 index 0000000..66973f6 --- /dev/null +++ b/backing-services/mysql/templates/role.yaml @@ -0,0 +1,26 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.serviceAccount.create .Values.rbac.create }} +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: Role +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: + - apiGroups: + - "" + resources: + - endpoints + verbs: + - get + {{- if .Values.rbac.rules }} + {{- include "common.tplvalues.render" ( dict "value" .Values.rbac.rules "context" $ ) | nindent 2 }} + {{- end }} +{{- end }} diff --git a/backing-services/mysql/templates/rolebinding.yaml b/backing-services/mysql/templates/rolebinding.yaml new file mode 100644 index 0000000..28e0657 --- /dev/null +++ b/backing-services/mysql/templates/rolebinding.yaml @@ -0,0 +1,23 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.serviceAccount.create .Values.rbac.create }} +kind: RoleBinding +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +subjects: + - kind: ServiceAccount + name: {{ include "mysql.serviceAccountName" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "common.names.fullname" . -}} +{{- end }} diff --git a/backing-services/mysql/templates/secondary/configmap.yaml b/backing-services/mysql/templates/secondary/configmap.yaml new file mode 100644 index 0000000..ad4be47 --- /dev/null +++ b/backing-services/mysql/templates/secondary/configmap.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mysql.secondary.createConfigmap" .) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "mysql.secondary.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: secondary + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + my.cnf: |- + {{- include "common.tplvalues.render" ( dict "value" .Values.secondary.configuration "context" $ ) | nindent 4 }} +{{- end -}} diff --git a/backing-services/mysql/templates/secondary/pdb.yaml b/backing-services/mysql/templates/secondary/pdb.yaml new file mode 100644 index 0000000..390d153 --- /dev/null +++ b/backing-services/mysql/templates/secondary/pdb.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replication") .Values.secondary.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "mysql.secondary.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: secondary + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.secondary.pdb.minAvailable }} + minAvailable: {{ .Values.secondary.pdb.minAvailable }} + {{- end }} + {{- if .Values.secondary.pdb.maxUnavailable }} + maxUnavailable: {{ .Values.secondary.pdb.maxUnavailable }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.secondary.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: secondary +{{- end }} diff --git a/backing-services/mysql/templates/secondary/statefulset.yaml b/backing-services/mysql/templates/secondary/statefulset.yaml new file mode 100644 index 0000000..c22e5e6 --- /dev/null +++ b/backing-services/mysql/templates/secondary/statefulset.yaml @@ -0,0 +1,380 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if eq .Values.architecture "replication" }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ include "mysql.secondary.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: secondary + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.secondary.replicaCount }} + podManagementPolicy: {{ .Values.secondary.podManagementPolicy | quote }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.secondary.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: secondary + serviceName: {{ include "mysql.secondary.fullname" . }} + {{- if .Values.secondary.updateStrategy }} + updateStrategy: {{- toYaml .Values.secondary.updateStrategy | nindent 4 }} + {{- end }} + template: + metadata: + annotations: + {{- if (include "mysql.secondary.createConfigmap" .) }} + checksum/configuration: {{ include (print $.Template.BasePath "/secondary/configmap.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.secondary.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.secondary.podAnnotations "context" $) | nindent 8 }} + {{- end }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: secondary + spec: + {{- if .Values.secondary.extraPodSpec }} + {{- include "common.tplvalues.render" (dict "value" .Values.secondary.extraPodSpec "context" $) | nindent 6 }} + {{- end }} + serviceAccountName: {{ include "mysql.serviceAccountName" . }} + {{- include "mysql.imagePullSecrets" . | nindent 6 }} + {{- if .Values.secondary.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.secondary.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.secondary.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.secondary.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.secondary.podAffinityPreset "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.secondary.podAntiAffinityPreset "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.secondary.nodeAffinityPreset.type "key" .Values.secondary.nodeAffinityPreset.key "values" .Values.secondary.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.secondary.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.secondary.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.secondary.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.secondary.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.secondary.priorityClassName }} + priorityClassName: {{ .Values.secondary.priorityClassName | quote }} + {{- end }} + {{- if .Values.secondary.runtimeClassName }} + runtimeClassName: {{ .Values.secondary.runtimeClassName | quote }} + {{- end }} + {{- if .Values.secondary.schedulerName }} + schedulerName: {{ .Values.secondary.schedulerName | quote }} + {{- end }} + {{- if .Values.secondary.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.secondary.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.secondary.podSecurityContext.enabled }} + securityContext: {{- omit .Values.secondary.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.secondary.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.secondary.terminationGracePeriodSeconds }} + {{- end }} + initContainers: + {{- if and .Values.secondary.podSecurityContext.enabled .Values.volumePermissions.enabled .Values.secondary.persistence.enabled }} + - name: volume-permissions + image: {{ include "mysql.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + - -ec + - | + mkdir -p "/bitnami/mysql" + chown "{{ .Values.secondary.containerSecurityContext.runAsUser }}:{{ .Values.secondary.podSecurityContext.fsGroup }}" "/bitnami/mysql" + find "/bitnami/mysql" -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | xargs -r chown -R "{{ .Values.secondary.containerSecurityContext.runAsUser }}:{{ .Values.secondary.podSecurityContext.fsGroup }}" + securityContext: + runAsUser: 0 + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: data + mountPath: /bitnami/mysql + {{- if .Values.secondary.persistence.subPath }} + subPath: {{ .Values.secondary.persistence.subPath }} + {{- end }} + {{- end }} + {{- if .Values.secondary.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.secondary.initContainers "context" $) | nindent 8 }} + {{- end }} + containers: + - name: mysql + image: {{ include "mysql.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.secondary.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.secondary.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.secondary.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.secondary.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.secondary.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.secondary.args "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.secondary.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.secondary.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + - name: MYSQL_REPLICATION_MODE + value: "slave" + - name: MYSQL_MASTER_HOST + value: {{ include "mysql.primary.fullname" . }} + - name: MYSQL_MASTER_PORT_NUMBER + value: {{ .Values.primary.service.ports.mysql | quote }} + - name: MYSQL_MASTER_ROOT_USER + value: "root" + - name: MYSQL_REPLICATION_USER + value: {{ .Values.auth.replicationUser | quote }} + {{- if .Values.auth.usePasswordFiles }} + - name: MYSQL_MASTER_ROOT_PASSWORD_FILE + value: {{ default "/opt/bitnami/mysql/secrets/mysql-root-password" .Values.auth.customPasswordFiles.root }} + - name: MYSQL_REPLICATION_PASSWORD_FILE + value: {{ default "/opt/bitnami/mysql/secrets/mysql-replication-password" .Values.auth.customPasswordFiles.replicator }} + {{- else }} + - name: MYSQL_MASTER_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "mysql.secretName" . }} + key: mysql-root-password + - name: MYSQL_REPLICATION_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "mysql.secretName" . }} + key: mysql-replication-password + {{- end }} + {{- if .Values.secondary.extraFlags }} + - name: MYSQL_EXTRA_FLAGS + value: "{{ .Values.secondary.extraFlags }}" + {{- end }} + {{- if .Values.secondary.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.secondary.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.secondary.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.secondary.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.secondary.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.secondary.extraEnvVarsSecret "context" $) }} + {{- end }} + ports: + - name: mysql + containerPort: 3306 + {{- if .Values.secondary.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.secondary.extraPorts "context" $) | nindent 12 }} + {{- end }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.secondary.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.secondary.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.secondary.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.secondary.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bin/bash + - -ec + - | + password_aux="${MYSQL_MASTER_ROOT_PASSWORD:-}" + if [[ -f "${MYSQL_MASTER_ROOT_PASSWORD_FILE:-}" ]]; then + password_aux=$(cat "$MYSQL_MASTER_ROOT_PASSWORD_FILE") + fi + mysqladmin status -uroot -p"${password_aux}" + {{- end }} + {{- if .Values.secondary.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.secondary.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.secondary.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.secondary.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bin/bash + - -ec + - | + password_aux="${MYSQL_MASTER_ROOT_PASSWORD:-}" + if [[ -f "${MYSQL_MASTER_ROOT_PASSWORD_FILE:-}" ]]; then + password_aux=$(cat "$MYSQL_MASTER_ROOT_PASSWORD_FILE") + fi + mysqladmin status -uroot -p"${password_aux}" + {{- end }} + {{- if .Values.secondary.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.secondary.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.secondary.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.secondary.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bin/bash + - -ec + - | + password_aux="${MYSQL_MASTER_ROOT_PASSWORD:-}" + if [[ -f "${MYSQL_MASTER_ROOT_PASSWORD_FILE:-}" ]]; then + password_aux=$(cat "$MYSQL_MASTER_ROOT_PASSWORD_FILE") + fi + mysqladmin status -uroot -p"${password_aux}" + {{- end }} + {{- end }} + {{- if .Values.secondary.resources }} + resources: {{ toYaml .Values.secondary.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: data + mountPath: /bitnami/mysql + {{- if .Values.secondary.persistence.subPath }} + subPath: {{ .Values.secondary.persistence.subPath }} + {{- end }} + {{- if or .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + mountPath: /docker-entrypoint-initdb.d + {{- end }} + {{- if or .Values.startdbScriptsConfigMap .Values.startdbScripts }} + - name: custom-start-scripts + mountPath: /docker-entrypoint-startdb.d + {{- end }} + {{- if or .Values.secondary.configuration .Values.secondary.existingConfigmap }} + - name: config + mountPath: /opt/bitnami/mysql/conf/my.cnf + subPath: my.cnf + {{- end }} + {{- if and .Values.auth.usePasswordFiles (not .Values.auth.customPasswordFiles) }} + - name: mysql-credentials + mountPath: /opt/bitnami/mysql/secrets/ + {{- end }} + {{- if .Values.secondary.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.secondary.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ include "mysql.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.metrics.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.metrics.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + env: + {{- if .Values.auth.usePasswordFiles }} + - name: MYSQL_ROOT_PASSWORD_FILE + value: {{ default "/opt/bitnami/mysqld-exporter/secrets/mysql-root-password" .Values.auth.customPasswordFiles.root }} + {{- else }} + - name: MYSQL_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "mysql.secretName" . }} + key: mysql-root-password + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -ec + - | + password_aux="${MYSQL_ROOT_PASSWORD:-}" + if [[ -f "${MYSQL_ROOT_PASSWORD_FILE:-}" ]]; then + password_aux=$(cat "$MYSQL_ROOT_PASSWORD_FILE") + fi + MYSQLD_EXPORTER_PASSWORD=${password_aux} /bin/mysqld_exporter --mysqld.address=localhost:3306 --mysqld.username=root {{- range .Values.metrics.extraArgs.primary }} {{ . }} {{- end }} + {{- end }} + ports: + - name: metrics + containerPort: 9104 + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- omit .Values.metrics.livenessProbe "enabled" | toYaml | nindent 12 }} + httpGet: + path: /metrics + port: metrics + {{- end }} + {{- if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- omit .Values.metrics.readinessProbe "enabled" | toYaml | nindent 12 }} + httpGet: + path: /metrics + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- end }} + {{- if and .Values.auth.usePasswordFiles (not .Values.auth.customPasswordFiles) }} + volumeMounts: + - name: mysql-credentials + mountPath: /opt/bitnami/mysqld-exporter/secrets/ + {{- end }} + {{- end }} + {{- if .Values.secondary.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.secondary.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + {{- if or .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + configMap: + name: {{ include "mysql.initdbScriptsCM" . }} + {{- end }} + {{- if or .Values.startdbScriptsConfigMap .Values.startdbScripts }} + - name: custom-start-scripts + configMap: + name: {{ include "mysql.startdbScriptsCM" . }} + {{- end }} + {{- if or .Values.secondary.configuration .Values.secondary.existingConfigmap }} + - name: config + configMap: + name: {{ include "mysql.secondary.configmapName" . }} + {{- end }} + {{- if and .Values.auth.usePasswordFiles (not .Values.auth.customPasswordFiles) }} + - name: mysql-credentials + secret: + secretName: {{ template "mysql.secretName" . }} + items: + - key: mysql-root-password + path: mysql-root-password + - key: mysql-replication-password + path: mysql-replication-password + {{- end }} + {{- if .Values.secondary.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.secondary.extraVolumes "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.secondary.persistence.enabled .Values.secondary.persistence.existingClaim }} + - name: data + persistentVolumeClaim: + claimName: {{ tpl .Values.secondary.persistence.existingClaim . }} + {{- else if not .Values.secondary.persistence.enabled }} + - name: data + emptyDir: {} + {{- else }} + {{- if .Values.secondary.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.secondary.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.secondary.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + volumeClaimTemplates: + - metadata: + name: data + labels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 10 }} + app.kubernetes.io/component: secondary + {{- if or .Values.secondary.persistence.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.secondary.persistence.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.secondary.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.secondary.persistence.size | quote }} + {{- include "common.storage.class" (dict "persistence" .Values.secondary.persistence "global" .Values.global) | nindent 8 }} + {{- if .Values.secondary.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.secondary.persistence.selector "context" $) | nindent 10 }} + {{- end -}} + {{- end }} +{{- end }} diff --git a/backing-services/mysql/templates/secondary/svc-headless.yaml b/backing-services/mysql/templates/secondary/svc-headless.yaml new file mode 100644 index 0000000..067e8d6 --- /dev/null +++ b/backing-services/mysql/templates/secondary/svc-headless.yaml @@ -0,0 +1,29 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if eq .Values.architecture "replication" }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mysql.secondary.fullname" . }}-headless + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: secondary + {{- if or .Values.secondary.service.headless.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.secondary.service.headless.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + publishNotReadyAddresses: true + ports: + - name: mysql + port: {{ .Values.secondary.service.ports.mysql }} + targetPort: mysql + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.secondary.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: secondary +{{- end }} diff --git a/backing-services/mysql/templates/secondary/svc.yaml b/backing-services/mysql/templates/secondary/svc.yaml new file mode 100644 index 0000000..87724b0 --- /dev/null +++ b/backing-services/mysql/templates/secondary/svc.yaml @@ -0,0 +1,54 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if eq .Values.architecture "replication" }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mysql.secondary.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: secondary + {{- if or .Values.secondary.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.secondary.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.secondary.service.type }} + {{- if and .Values.secondary.service.clusterIP (eq .Values.secondary.service.type "ClusterIP") }} + clusterIP: {{ .Values.secondary.service.clusterIP }} + {{- end }} + {{- if .Values.secondary.service.sessionAffinity }} + sessionAffinity: {{ .Values.secondary.service.sessionAffinity }} + {{- end }} + {{- if .Values.secondary.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.secondary.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + {{- if or (eq .Values.secondary.service.type "LoadBalancer") (eq .Values.secondary.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.secondary.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.secondary.service.type "LoadBalancer") (not (empty .Values.secondary.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{- toYaml .Values.secondary.service.loadBalancerSourceRanges | nindent 4}} + {{- end }} + {{- if and (eq .Values.secondary.service.type "LoadBalancer") (not (empty .Values.secondary.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.secondary.service.loadBalancerIP }} + {{- end }} + ports: + - name: mysql + port: {{ .Values.secondary.service.ports.mysql }} + protocol: TCP + targetPort: mysql + {{- if (and (or (eq .Values.secondary.service.type "NodePort") (eq .Values.secondary.service.type "LoadBalancer")) .Values.secondary.service.nodePorts.mysql) }} + nodePort: {{ .Values.secondary.service.nodePorts.mysql }} + {{- else if eq .Values.secondary.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.secondary.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.secondary.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.secondary.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: secondary +{{- end }} diff --git a/backing-services/mysql/templates/secrets.yaml b/backing-services/mysql/templates/secrets.yaml new file mode 100644 index 0000000..530a12c --- /dev/null +++ b/backing-services/mysql/templates/secrets.yaml @@ -0,0 +1,74 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- $host := include "mysql.primary.fullname" . }} +{{- $port := print .Values.primary.service.ports.mysql }} +{{- $rootPassword := include "common.secrets.passwords.manage" (dict "secret" (include "mysql.secretName" .) "key" "mysql-root-password" "length" 10 "providedValues" (list "auth.rootPassword") "context" $) | trimAll "\"" | b64dec }} +{{- $password := include "common.secrets.passwords.manage" (dict "secret" (include "mysql.secretName" .) "key" "mysql-password" "length" 10 "providedValues" (list "auth.password") "context" $) | trimAll "\"" | b64dec }} +{{- if eq (include "mysql.createSecret" .) "true" }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + mysql-root-password: {{ print $rootPassword | b64enc | quote }} + mysql-password: {{ print $password | b64enc | quote }} + {{- if eq .Values.architecture "replication" }} + mysql-replication-password: {{ include "common.secrets.passwords.manage" (dict "secret" (include "common.names.fullname" .) "key" "mysql-replication-password" "length" 10 "providedValues" (list "auth.replicationPassword") "context" $) }} + {{- end }} +{{- end }} +{{- if .Values.serviceBindings.enabled }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }}-svcbind-root + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: servicebinding.io/mysql +data: + provider: {{ print "bitnami" | b64enc | quote }} + type: {{ print "mysql" | b64enc | quote }} + host: {{ print $host | b64enc | quote }} + port: {{ print $port | b64enc | quote }} + username: {{ print "root" | b64enc | quote }} + password: {{ print $rootPassword | b64enc | quote }} + uri: {{ printf "mysql://root:%s@%s:%s" $rootPassword $host $port | b64enc | quote }} + +{{- if .Values.auth.username }} +{{- $database := .Values.auth.database }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }}-svcbind-custom-user + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: servicebinding.io/mysql +data: + provider: {{ print "bitnami" | b64enc | quote }} + type: {{ print "mysql" | b64enc | quote }} + host: {{ print $host | b64enc | quote }} + port: {{ print $port | b64enc | quote }} + username: {{ print .Values.auth.username | b64enc | quote }} + {{- if $database }} + database: {{ print $database | b64enc | quote }} + {{- end }} + password: {{ print $password | b64enc | quote }} + uri: {{ printf "mysql://%s:%s@%s:%s/%s" .Values.auth.username $password $host $port $database | b64enc | quote }} +{{- end }} +{{- end }} diff --git a/backing-services/mysql/templates/serviceaccount.yaml b/backing-services/mysql/templates/serviceaccount.yaml new file mode 100644 index 0000000..69705b5 --- /dev/null +++ b/backing-services/mysql/templates/serviceaccount.yaml @@ -0,0 +1,22 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "mysql.serviceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +{{- if (not .Values.auth.customPasswordFiles) }} +secrets: + - name: {{ template "mysql.secretName" . }} +{{- end }} +{{- end }} diff --git a/backing-services/mysql/templates/servicemonitor.yaml b/backing-services/mysql/templates/servicemonitor.yaml new file mode 100644 index 0000000..3390be8 --- /dev/null +++ b/backing-services/mysql/templates/servicemonitor.yaml @@ -0,0 +1,46 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ default (include "common.names.namespace" .) .Values.metrics.serviceMonitor.namespace }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.serviceMonitor.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + {{- if or .Values.metrics.serviceMonitor.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.serviceMonitor.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + jobLabel: {{ .Values.metrics.serviceMonitor.jobLabel | quote }} + endpoints: + - port: metrics + {{- if .Values.metrics.serviceMonitor.interval }} + interval: {{ .Values.metrics.serviceMonitor.interval }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.honorLabels }} + honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.metricRelabelings "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.relabelings }} + relabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.relabelings "context" $) | nindent 8 }} + {{- end }} + namespaceSelector: + matchNames: + - {{ include "common.names.namespace" . | quote }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: metrics + {{- if .Values.metrics.serviceMonitor.selector }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.serviceMonitor.selector "context" $) | nindent 6 }} + {{- end }} +{{- end }} diff --git a/backing-services/mysql/values.schema.json b/backing-services/mysql/values.schema.json new file mode 100644 index 0000000..df59156 --- /dev/null +++ b/backing-services/mysql/values.schema.json @@ -0,0 +1,195 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "architecture": { + "type": "string", + "title": "MySQL architecture", + "form": true, + "description": "Allowed values: `standalone` or `replication`", + "enum": ["standalone", "replication"] + }, + "auth": { + "type": "object", + "title": "Authentication configuration", + "form": true, + "required": ["username", "password"], + "if": { + "properties": { + "createDatabase": { "enum": [ true ] } + } + }, + "then": { + "properties": { + "database": { + "pattern": "[a-zA-Z0-9]{1,64}" + } + } + }, + "properties": { + "rootPassword": { + "type": "string", + "title": "MySQL root password", + "description": "Defaults to a random 10-character alphanumeric string if not set" + }, + "database": { + "type": "string", + "title": "MySQL custom database name", + "maxLength": 64 + }, + "username": { + "type": "string", + "title": "MySQL custom username" + }, + "password": { + "type": "string", + "title": "MySQL custom password" + }, + "replicationUser": { + "type": "string", + "title": "MySQL replication username" + }, + "replicationPassword": { + "type": "string", + "title": "MySQL replication password" + }, + "createDatabase": { + "type": "boolean", + "title": "MySQL create custom database" + } + } + }, + "primary": { + "type": "object", + "title": "Primary database configuration", + "form": true, + "properties": { + "podSecurityContext": { + "type": "object", + "title": "MySQL primary Pod security context", + "properties": { + "enabled": { + "type": "boolean", + "default": false + }, + "fsGroup": { + "type": "integer", + "default": 1001, + "hidden": { + "value": false, + "path": "primary/podSecurityContext/enabled" + } + } + } + }, + "containerSecurityContext": { + "type": "object", + "title": "MySQL primary container security context", + "properties": { + "enabled": { + "type": "boolean", + "default": false + }, + "runAsUser": { + "type": "integer", + "default": 1001, + "hidden": { + "value": false, + "path": "primary/containerSecurityContext/enabled" + } + } + } + }, + "persistence": { + "type": "object", + "title": "Enable persistence using Persistent Volume Claims", + "properties": { + "enabled": { + "type": "boolean", + "default": true, + "title": "If true, use a Persistent Volume Claim, If false, use emptyDir" + }, + "size": { + "type": "string", + "title": "Persistent Volume Size", + "form": true, + "render": "slider", + "sliderMin": 1, + "sliderUnit": "Gi", + "hidden": { + "value": false, + "path": "primary/persistence/enabled" + } + } + } + } + } + }, + "secondary": { + "type": "object", + "title": "Secondary database configuration", + "form": true, + "properties": { + "podSecurityContext": { + "type": "object", + "title": "MySQL secondary Pod security context", + "properties": { + "enabled": { + "type": "boolean", + "default": false + }, + "fsGroup": { + "type": "integer", + "default": 1001, + "hidden": { + "value": false, + "path": "secondary/podSecurityContext/enabled" + } + } + } + }, + "containerSecurityContext": { + "type": "object", + "title": "MySQL secondary container security context", + "properties": { + "enabled": { + "type": "boolean", + "default": false + }, + "runAsUser": { + "type": "integer", + "default": 1001, + "hidden": { + "value": false, + "path": "secondary/containerSecurityContext/enabled" + } + } + } + }, + "persistence": { + "type": "object", + "title": "Enable persistence using Persistent Volume Claims", + "properties": { + "enabled": { + "type": "boolean", + "default": true, + "title": "If true, use a Persistent Volume Claim, If false, use emptyDir" + }, + "size": { + "type": "string", + "title": "Persistent Volume Size", + "form": true, + "render": "slider", + "sliderMin": 1, + "sliderUnit": "Gi", + "hidden": { + "value": false, + "path": "secondary/persistence/enabled" + } + } + } + } + } + } + } +} diff --git a/backing-services/mysql/values.yaml b/backing-services/mysql/values.yaml new file mode 100644 index 0000000..69f8689 --- /dev/null +++ b/backing-services/mysql/values.yaml @@ -0,0 +1,1165 @@ +global: + imageRegistry: "" + imagePullSecrets: [] + storageClass: "" + +kubeVersion: "" +nameOverride: "" +fullnameOverride: "" +namespaceOverride: "" +clusterDomain: cluster.local + +commonAnnotations: {} + +commonLabels: {} + +extraDeploy: [] + +serviceBindings: + enabled: false + +diagnosticMode: + enabled: false + command: + - sleep + args: + - infinity + +image: + registry: docker.io + repository: bitnami/mysql + tag: 8.0.35-debian-11-r2 + digest: "" + pullPolicy: IfNotPresent + + pullSecrets: [] + + debug: false + +architecture: standalone + +auth: + rootPassword: "secret123" + createDatabase: true + database: "my_database" + username: "admin" + password: "secret123" + replicationUser: replicator + replicationPassword: "" + existingSecret: "" + usePasswordFiles: false + customPasswordFiles: {} + defaultAuthenticationPlugin: "" +## @param initdbScripts Dictionary of initdb scripts +## Specify dictionary of scripts to be run at first boot +## Example: +## initdbScripts: +## my_init_script.sh: | +## #!/bin/bash +## echo "Do something." +## +initdbScripts: + my_init_script.sql: | + SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY','')); + FLUSH PRIVILEGES; + SET group_concat_max_len = 10000; + SET GLOBAL mysqlx_max_connections=500; + SET GLOBAL max_connections=500; + SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED; +initdbScriptsConfigMap: "" +## @param startdbScripts Dictionary of startdb scripts +## Specify dictionary of scripts to be run every time the container is started +## Example: +## startdbScripts: +## my_start_script.sh: | +## #!/bin/bash +## echo "Do something." +## +startdbScripts: {} +startdbScriptsConfigMap: "" +primary: + name: primary + command: [] + args: [] + lifecycleHooks: {} + hostAliases: [] + configuration: |- + [mysqld] + default_authentication_plugin={{- .Values.auth.defaultAuthenticationPlugin | default "mysql_native_password" }} + skip-name-resolve + explicit_defaults_for_timestamp + basedir=/opt/bitnami/mysql + plugin_dir=/opt/bitnami/mysql/lib/plugin + port=3306 + socket=/opt/bitnami/mysql/tmp/mysql.sock + datadir=/bitnami/mysql/data + tmpdir=/opt/bitnami/mysql/tmp + max_allowed_packet=16M + bind-address=* + pid-file=/opt/bitnami/mysql/tmp/mysqld.pid + log-error=/opt/bitnami/mysql/logs/mysqld.log + character-set-server=UTF8 + slow_query_log=0 + long_query_time=10.0 + group_concat_max_len=4294967295 + sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES + + [client] + port=3306 + socket=/opt/bitnami/mysql/tmp/mysql.sock + default-character-set=UTF8 + plugin_dir=/opt/bitnami/mysql/lib/plugin + + [manager] + port=3306 + socket=/opt/bitnami/mysql/tmp/mysql.sock + pid-file=/opt/bitnami/mysql/tmp/mysqld.pid + + existingConfigmap: "" + + updateStrategy: + type: RollingUpdate + + podAnnotations: {} + + podAffinityPreset: "" + + podAntiAffinityPreset: soft + + nodeAffinityPreset: + + type: "" + key: "" + values: [] + + affinity: {} + + nodeSelector: {} + ## @param primary.tolerations Tolerations for MySQL primary pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param primary.priorityClassName MySQL primary pods' priorityClassName + ## + priorityClassName: "" + ## @param primary.runtimeClassName MySQL primary pods' runtimeClassName + ## + runtimeClassName: "" + ## @param primary.schedulerName Name of the k8s scheduler (other than default) + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param primary.terminationGracePeriodSeconds In seconds, time the given to the MySQL primary pod needs to terminate gracefully + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods + ## + terminationGracePeriodSeconds: "" + ## @param primary.topologySpreadConstraints Topology Spread Constraints for pod assignment + ## https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## The value is evaluated as a template + ## + topologySpreadConstraints: [] + ## @param primary.podManagementPolicy podManagementPolicy to manage scaling operation of MySQL primary pods + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#pod-management-policies + ## + podManagementPolicy: "" + ## MySQL primary Pod security context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param primary.podSecurityContext.enabled Enable security context for MySQL primary pods + ## @param primary.podSecurityContext.fsGroup Group ID for the mounted volumes' filesystem + ## + podSecurityContext: + enabled: true + fsGroup: 1001 + ## MySQL primary container security context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param primary.containerSecurityContext.enabled MySQL primary container securityContext + ## @param primary.containerSecurityContext.runAsUser User ID for the MySQL primary container + ## @param primary.containerSecurityContext.runAsNonRoot Set MySQL primary container's Security Context runAsNonRoot + ## @param primary.containerSecurityContext.allowPrivilegeEscalation Set container's privilege escalation + ## @param primary.containerSecurityContext.capabilities.drop Set container's Security Context runAsNonRoot + ## @param primary.containerSecurityContext.seccompProfile.type Set Client container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## MySQL primary container's resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-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:'. + ## @param primary.resources.limits The resources limits for MySQL primary containers + ## @param primary.resources.requests The requested resources for MySQL primary containers + ## + resources: + ## Example: + ## limits: + ## cpu: 250m + ## memory: 256Mi + ## + limits: {} + ## Examples: + ## requests: + ## cpu: 250m + ## memory: 256Mi + ## + requests: {} + ## Configure extra options for liveness probe + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param primary.livenessProbe.enabled Enable livenessProbe + ## @param primary.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param primary.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param primary.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param primary.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param primary.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 3 + successThreshold: 1 + ## Configure extra options for readiness probe + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param primary.readinessProbe.enabled Enable readinessProbe + ## @param primary.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param primary.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param primary.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param primary.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param primary.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 3 + successThreshold: 1 + ## Configure extra options for startupProbe probe + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param primary.startupProbe.enabled Enable startupProbe + ## @param primary.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param primary.startupProbe.periodSeconds Period seconds for startupProbe + ## @param primary.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param primary.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param primary.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: true + initialDelaySeconds: 15 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 10 + successThreshold: 1 + ## @param primary.customLivenessProbe Override default liveness probe for MySQL primary containers + ## + customLivenessProbe: {} + ## @param primary.customReadinessProbe Override default readiness probe for MySQL primary containers + ## + customReadinessProbe: {} + ## @param primary.customStartupProbe Override default startup probe for MySQL primary containers + ## + customStartupProbe: {} + ## @param primary.extraFlags MySQL primary additional command line flags + ## Can be used to specify command line flags, for example: + ## E.g. + ## extraFlags: "--max-connect-errors=1000 --max_connections=155" + ## + extraFlags: "" + ## @param primary.extraEnvVars Extra environment variables to be set on MySQL primary containers + ## E.g. + ## extraEnvVars: + ## - name: TZ + ## value: "Europe/Paris" + ## + extraEnvVars: [] + ## @param primary.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for MySQL primary containers + ## + extraEnvVarsCM: "" + ## @param primary.extraEnvVarsSecret Name of existing Secret containing extra env vars for MySQL primary containers + ## + extraEnvVarsSecret: "" + ## @param primary.extraPodSpec Optionally specify extra PodSpec for the MySQL Primary pod(s) + ## + extraPodSpec: {} + ## @param primary.extraPorts Extra ports to expose + ## + extraPorts: [] + ## Enable persistence using Persistent Volume Claims + ## ref: https://kubernetes.io/docs/user-guide/persistent-volumes/ + ## + persistence: + ## @param primary.persistence.enabled Enable persistence on MySQL primary replicas using a `PersistentVolumeClaim`. If false, use emptyDir + ## + enabled: true + ## @param primary.persistence.existingClaim Name of an existing `PersistentVolumeClaim` for MySQL primary replicas + ## NOTE: When it's set the rest of persistence parameters are ignored + ## + existingClaim: "" + ## @param primary.persistence.subPath The name of a volume's sub path to mount for persistence + ## + subPath: "" + ## @param primary.persistence.storageClass MySQL primary persistent volume storage Class + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + storageClass: "" + ## @param primary.persistence.annotations MySQL primary persistent volume claim annotations + ## + annotations: {} + ## @param primary.persistence.accessModes MySQL primary persistent volume access Modes + ## + accessModes: + - ReadWriteOnce + ## @param primary.persistence.size MySQL primary persistent volume size + ## + size: 8Gi + ## @param primary.persistence.selector Selector to match an existing Persistent Volume + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## Primary Persistent Volume Claim Retention Policy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention + ## + persistentVolumeClaimRetentionPolicy: + ## @param primary.persistentVolumeClaimRetentionPolicy.enabled Enable Persistent volume retention policy for Primary StatefulSet + ## + enabled: false + ## @param primary.persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced + ## + whenScaled: Retain + ## @param primary.persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted + ## + whenDeleted: Retain + ## @param primary.extraVolumes Optionally specify extra list of additional volumes to the MySQL Primary pod(s) + ## + extraVolumes: [] + ## @param primary.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the MySQL Primary container(s) + ## + extraVolumeMounts: [] + ## @param primary.initContainers Add additional init containers for the MySQL Primary pod(s) + ## + initContainers: [] + ## @param primary.sidecars Add additional sidecar containers for the MySQL Primary pod(s) + ## + sidecars: [] + ## MySQL Primary Service parameters + ## + service: + ## @param primary.service.type MySQL Primary K8s service type + ## + type: NodePort + ## @param primary.service.ports.mysql MySQL Primary K8s service port + ## + ports: + mysql: 3306 + ## @param primary.service.nodePorts.mysql MySQL Primary K8s service node port + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + nodePorts: + mysql: 30306 + ## @param primary.service.clusterIP MySQL Primary K8s service clusterIP IP + ## e.g: + ## clusterIP: None + ## + clusterIP: "" + ## @param primary.service.loadBalancerIP MySQL Primary loadBalancerIP if service type is `LoadBalancer` + ## Set the LoadBalancer service type to internal only + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param primary.service.externalTrafficPolicy Enable client source IP preservation + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param primary.service.loadBalancerSourceRanges Addresses that are allowed when MySQL Primary service is LoadBalancer + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## E.g. + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param primary.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param primary.service.annotations Additional custom annotations for MySQL primary service + ## + annotations: {} + ## @param primary.service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param primary.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## Headless service properties + ## + headless: + ## @param primary.service.headless.annotations Additional custom annotations for headless MySQL primary service. + ## + annotations: {} + + ## MySQL primary Pod Disruption Budget configuration + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ + ## + pdb: + ## @param primary.pdb.create Enable/disable a Pod Disruption Budget creation for MySQL primary pods + ## + create: false + ## @param primary.pdb.minAvailable Minimum number/percentage of MySQL primary pods that should remain scheduled + ## + minAvailable: 1 + ## @param primary.pdb.maxUnavailable Maximum number/percentage of MySQL primary pods that may be made unavailable + ## + maxUnavailable: "" + ## @param primary.podLabels MySQL Primary pod label. If labels are same as commonLabels , this will take precedence + ## + podLabels: {} + +## @section MySQL Secondary parameters +## + +secondary: + ## @param secondary.name Name of the secondary database (eg secondary, slave, ...) + ## + name: secondary + ## @param secondary.replicaCount Number of MySQL secondary replicas + ## + replicaCount: 1 + ## @param secondary.hostAliases Deployment pod host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param secondary.command Override default container command on MySQL Secondary container(s) (useful when using custom images) + ## + command: [] + ## @param secondary.args Override default container args on MySQL Secondary container(s) (useful when using custom images) + ## + args: [] + ## @param secondary.lifecycleHooks for the MySQL Secondary container(s) to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param secondary.configuration [string] Configure MySQL Secondary with a custom my.cnf file + ## ref: https://mysql.com/kb/en/mysql/configuring-mysql-with-mycnf/#example-of-configuration-file + ## + configuration: |- + [mysqld] + default_authentication_plugin=mysql_native_password + skip-name-resolve + explicit_defaults_for_timestamp + basedir=/opt/bitnami/mysql + plugin_dir=/opt/bitnami/mysql/lib/plugin + port=3306 + socket=/opt/bitnami/mysql/tmp/mysql.sock + datadir=/bitnami/mysql/data + tmpdir=/opt/bitnami/mysql/tmp + max_allowed_packet=16M + bind-address=* + pid-file=/opt/bitnami/mysql/tmp/mysqld.pid + log-error=/opt/bitnami/mysql/logs/mysqld.log + character-set-server=UTF8 + slow_query_log=0 + long_query_time=10.0 + + [client] + port=3306 + socket=/opt/bitnami/mysql/tmp/mysql.sock + default-character-set=UTF8 + plugin_dir=/opt/bitnami/mysql/lib/plugin + + [manager] + port=3306 + socket=/opt/bitnami/mysql/tmp/mysql.sock + pid-file=/opt/bitnami/mysql/tmp/mysqld.pid + ## @param secondary.existingConfigmap Name of existing ConfigMap with MySQL Secondary configuration. + ## NOTE: When it's set the 'configuration' parameter is ignored + ## + existingConfigmap: "" + ## @param secondary.updateStrategy.type Update strategy type for the MySQL secondary statefulset + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## + updateStrategy: + type: RollingUpdate + ## @param secondary.podAnnotations Additional pod annotations for MySQL secondary pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param secondary.podAffinityPreset MySQL secondary pod affinity preset. Ignored if `secondary.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param secondary.podAntiAffinityPreset MySQL secondary pod anti-affinity preset. Ignored if `secondary.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## Allowed values: soft, hard + ## + podAntiAffinityPreset: soft + ## MySQL Secondary node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param secondary.nodeAffinityPreset.type MySQL secondary node affinity preset type. Ignored if `secondary.affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param secondary.nodeAffinityPreset.key MySQL secondary node label key to match Ignored if `secondary.affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param secondary.nodeAffinityPreset.values MySQL secondary node label values to match. Ignored if `secondary.affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param secondary.affinity Affinity for MySQL secondary pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## Note: podAffinityPreset, podAntiAffinityPreset, and nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## @param secondary.nodeSelector Node labels for MySQL secondary pods assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + ## @param secondary.tolerations Tolerations for MySQL secondary pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param secondary.priorityClassName MySQL secondary pods' priorityClassName + ## + priorityClassName: "" + ## @param secondary.runtimeClassName MySQL secondary pods' runtimeClassName + ## + runtimeClassName: "" + ## @param secondary.schedulerName Name of the k8s scheduler (other than default) + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param secondary.terminationGracePeriodSeconds In seconds, time the given to the MySQL secondary pod needs to terminate gracefully + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods + ## + terminationGracePeriodSeconds: "" + ## @param secondary.topologySpreadConstraints Topology Spread Constraints for pod assignment + ## https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## The value is evaluated as a template + ## + topologySpreadConstraints: [] + ## @param secondary.podManagementPolicy podManagementPolicy to manage scaling operation of MySQL secondary pods + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#pod-management-policies + ## + podManagementPolicy: "" + ## MySQL secondary Pod security context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param secondary.podSecurityContext.enabled Enable security context for MySQL secondary pods + ## @param secondary.podSecurityContext.fsGroup Group ID for the mounted volumes' filesystem + ## + podSecurityContext: + enabled: true + fsGroup: 1001 + ## MySQL secondary container security context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param secondary.containerSecurityContext.enabled MySQL secondary container securityContext + ## @param secondary.containerSecurityContext.runAsUser User ID for the MySQL secondary container + ## @param secondary.containerSecurityContext.runAsNonRoot Set MySQL secondary container's Security Context runAsNonRoot + ## @param secondary.containerSecurityContext.allowPrivilegeEscalation Set container's privilege escalation + ## @param secondary.containerSecurityContext.capabilities.drop Set container's Security Context runAsNonRoot + ## @param secondary.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## MySQL secondary container's resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-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:'. + ## @param secondary.resources.limits The resources limits for MySQL secondary containers + ## @param secondary.resources.requests The requested resources for MySQL secondary containers + ## + resources: + ## Example: + ## limits: + ## cpu: 250m + ## memory: 256Mi + ## + limits: {} + ## Examples: + ## requests: + ## cpu: 250m + ## memory: 256Mi + ## + requests: {} + ## Configure extra options for liveness probe + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param secondary.livenessProbe.enabled Enable livenessProbe + ## @param secondary.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param secondary.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param secondary.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param secondary.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param secondary.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 3 + successThreshold: 1 + ## Configure extra options for readiness probe + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param secondary.readinessProbe.enabled Enable readinessProbe + ## @param secondary.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param secondary.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param secondary.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param secondary.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param secondary.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 3 + successThreshold: 1 + ## Configure extra options for startupProbe probe + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param secondary.startupProbe.enabled Enable startupProbe + ## @param secondary.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param secondary.startupProbe.periodSeconds Period seconds for startupProbe + ## @param secondary.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param secondary.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param secondary.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: true + initialDelaySeconds: 15 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 15 + successThreshold: 1 + ## @param secondary.customLivenessProbe Override default liveness probe for MySQL secondary containers + ## + customLivenessProbe: {} + ## @param secondary.customReadinessProbe Override default readiness probe for MySQL secondary containers + ## + customReadinessProbe: {} + ## @param secondary.customStartupProbe Override default startup probe for MySQL secondary containers + ## + customStartupProbe: {} + ## @param secondary.extraFlags MySQL secondary additional command line flags + ## Can be used to specify command line flags, for example: + ## E.g. + ## extraFlags: "--max-connect-errors=1000 --max_connections=155" + ## + extraFlags: "" + ## @param secondary.extraEnvVars An array to add extra environment variables on MySQL secondary containers + ## E.g. + ## extraEnvVars: + ## - name: TZ + ## value: "Europe/Paris" + ## + extraEnvVars: [] + ## @param secondary.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for MySQL secondary containers + ## + extraEnvVarsCM: "" + ## @param secondary.extraEnvVarsSecret Name of existing Secret containing extra env vars for MySQL secondary containers + ## + extraEnvVarsSecret: "" + ## @param secondary.extraPodSpec Optionally specify extra PodSpec for the MySQL Secondary pod(s) + ## + extraPodSpec: {} + ## @param secondary.extraPorts Extra ports to expose + ## + extraPorts: [] + ## Enable persistence using Persistent Volume Claims + ## ref: https://kubernetes.io/docs/user-guide/persistent-volumes/ + ## + persistence: + ## @param secondary.persistence.enabled Enable persistence on MySQL secondary replicas using a `PersistentVolumeClaim` + ## + enabled: true + ## @param secondary.persistence.existingClaim Name of an existing `PersistentVolumeClaim` for MySQL secondary replicas + ## NOTE: When it's set the rest of persistence parameters are ignored + ## + existingClaim: "" + ## @param secondary.persistence.subPath The name of a volume's sub path to mount for persistence + ## + subPath: "" + ## @param secondary.persistence.storageClass MySQL secondary persistent volume storage Class + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + storageClass: "" + ## @param secondary.persistence.annotations MySQL secondary persistent volume claim annotations + ## + annotations: {} + ## @param secondary.persistence.accessModes MySQL secondary persistent volume access Modes + ## + accessModes: + - ReadWriteOnce + ## @param secondary.persistence.size MySQL secondary persistent volume size + ## + size: 8Gi + ## @param secondary.persistence.selector Selector to match an existing Persistent Volume + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## Secondary Persistent Volume Claim Retention Policy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention + ## + persistentVolumeClaimRetentionPolicy: + ## @param secondary.persistentVolumeClaimRetentionPolicy.enabled Enable Persistent volume retention policy for read only StatefulSet + ## + enabled: false + ## @param secondary.persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced + ## + whenScaled: Retain + ## @param secondary.persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted + ## + whenDeleted: Retain + ## @param secondary.extraVolumes Optionally specify extra list of additional volumes to the MySQL secondary pod(s) + ## + extraVolumes: [] + ## @param secondary.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the MySQL secondary container(s) + ## + extraVolumeMounts: [] + ## @param secondary.initContainers Add additional init containers for the MySQL secondary pod(s) + ## + initContainers: [] + ## @param secondary.sidecars Add additional sidecar containers for the MySQL secondary pod(s) + ## + sidecars: [] + ## MySQL Secondary Service parameters + ## + service: + ## @param secondary.service.type MySQL secondary Kubernetes service type + ## + type: ClusterIP + ## @param secondary.service.ports.mysql MySQL secondary Kubernetes service port + ## + ports: + mysql: 3306 + ## @param secondary.service.nodePorts.mysql MySQL secondary Kubernetes service node port + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + nodePorts: + mysql: "" + ## @param secondary.service.clusterIP MySQL secondary Kubernetes service clusterIP IP + ## e.g: + ## clusterIP: None + ## + clusterIP: "" + ## @param secondary.service.loadBalancerIP MySQL secondary loadBalancerIP if service type is `LoadBalancer` + ## Set the LoadBalancer service type to internal only + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param secondary.service.externalTrafficPolicy Enable client source IP preservation + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param secondary.service.loadBalancerSourceRanges Addresses that are allowed when MySQL secondary service is LoadBalancer + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## E.g. + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param secondary.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param secondary.service.annotations Additional custom annotations for MySQL secondary service + ## + annotations: {} + ## @param secondary.service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param secondary.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## Headless service properties + ## + headless: + ## @param secondary.service.headless.annotations Additional custom annotations for headless MySQL secondary service. + ## + annotations: {} + + ## MySQL secondary Pod Disruption Budget configuration + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ + ## + pdb: + ## @param secondary.pdb.create Enable/disable a Pod Disruption Budget creation for MySQL secondary pods + ## + create: false + ## @param secondary.pdb.minAvailable Minimum number/percentage of MySQL secondary pods that should remain scheduled + ## + minAvailable: 1 + ## @param secondary.pdb.maxUnavailable Maximum number/percentage of MySQL secondary pods that may be made unavailable + ## + maxUnavailable: "" + ## @param secondary.podLabels Additional pod labels for MySQL secondary pods + ## + podLabels: {} + +## @section RBAC parameters +## + +## MySQL pods ServiceAccount +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ +## +serviceAccount: + ## @param serviceAccount.create Enable the creation of a ServiceAccount for MySQL pods + ## + create: true + ## @param serviceAccount.name Name of the created ServiceAccount + ## If not set and create is true, a name is generated using the mysql.fullname template + ## + name: "" + ## @param serviceAccount.annotations Annotations for MySQL Service Account + ## + annotations: {} + ## @param serviceAccount.automountServiceAccountToken Automount service account token for the server service account + ## + automountServiceAccountToken: true + +## Role Based Access +## ref: https://kubernetes.io/docs/admin/authorization/rbac/ +## +rbac: + ## @param rbac.create Whether to create & use RBAC resources or not + ## + create: false + ## @param rbac.rules Custom RBAC rules to set + ## e.g: + ## rules: + ## - apiGroups: + ## - "" + ## resources: + ## - pods + ## verbs: + ## - get + ## - list + ## + rules: [] + +## @section Network Policy +## + +## MySQL Nework Policy configuration +## +networkPolicy: + ## @param networkPolicy.enabled Enable creation of NetworkPolicy resources + ## + enabled: false + ## @param networkPolicy.allowExternal The Policy model to apply. + ## When set to false, only pods with the correct + ## client label will have network access to the port MySQL is listening + ## on. When true, MySQL will accept connections from any source + ## (with the correct destination port). + ## + allowExternal: true + ## @param networkPolicy.explicitNamespacesSelector A Kubernetes LabelSelector to explicitly select namespaces from which ingress traffic could be allowed to MySQL + ## 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. + ## + ## Example: + ## explicitNamespacesSelector: + ## matchLabels: + ## role: frontend + ## matchExpressions: + ## - {key: role, operator: In, values: [frontend]} + ## + explicitNamespacesSelector: {} + +## @section Volume Permissions parameters +## + +## Init containers parameters: +## volumePermissions: Change the owner and group of the persistent volume mountpoint to runAsUser:fsGroup values from the securityContext section. +## +volumePermissions: + ## @param volumePermissions.enabled Enable init container that changes the owner and group of the persistent volume(s) mountpoint to `runAsUser:fsGroup` + ## + enabled: false + ## @param volumePermissions.image.registry [default: REGISTRY_NAME] Init container volume-permissions image registry + ## @param volumePermissions.image.repository [default: REPOSITORY_NAME/os-shell] Init container volume-permissions image repository + ## @skip volumePermissions.image.tag Init container volume-permissions image tag (immutable tags are recommended) + ## @param volumePermissions.image.digest Init container volume-permissions image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param volumePermissions.image.pullPolicy Init container volume-permissions image pull policy + ## @param volumePermissions.image.pullSecrets Specify docker-registry secret names as an array + ## + image: + registry: docker.io + repository: bitnami/os-shell + tag: 11-debian-11-r93 + digest: "" + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## @param volumePermissions.resources Init container volume-permissions resources + ## + resources: {} + +## @section Metrics parameters +## + +## Mysqld Prometheus exporter parameters +## +metrics: + ## @param metrics.enabled Start a side-car prometheus exporter + ## + enabled: false + ## @param metrics.image.registry [default: REGISTRY_NAME] Exporter image registry + ## @param metrics.image.repository [default: REPOSITORY_NAME/mysqld-exporter] Exporter image repository + ## @skip metrics.image.tag Exporter image tag (immutable tags are recommended) + ## @param metrics.image.digest Exporter image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param metrics.image.pullPolicy Exporter image pull policy + ## @param metrics.image.pullSecrets Specify docker-registry secret names as an array + ## + image: + registry: docker.io + repository: bitnami/mysqld-exporter + tag: 0.15.1-debian-11-r0 + digest: "" + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## MySQL metrics container security context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param metrics.containerSecurityContext.enabled MySQL metrics container securityContext + ## @param metrics.containerSecurityContext.runAsUser User ID for the MySQL metrics container + ## @param metrics.containerSecurityContext.runAsNonRoot Set MySQL metrics container's Security Context runAsNonRoot + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + ## MySQL Prometheus exporter service parameters + ## Mysqld Prometheus exporter liveness and readiness probes + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param metrics.service.type Kubernetes service type for MySQL Prometheus Exporter + ## @param metrics.service.clusterIP Kubernetes service clusterIP for MySQL Prometheus Exporter + ## @param metrics.service.port MySQL Prometheus Exporter service port + ## @param metrics.service.annotations [object] Prometheus exporter service annotations + ## + service: + type: ClusterIP + port: 9104 + clusterIP: "" + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "{{ .Values.metrics.service.port }}" + ## @param metrics.extraArgs.primary Extra args to be passed to mysqld_exporter on Primary pods + ## @param metrics.extraArgs.secondary Extra args to be passed to mysqld_exporter on Secondary pods + ## ref: https://github.com/prometheus/mysqld_exporter/ + ## E.g. + ## - --collect.auto_increment.columns + ## - --collect.binlog_size + ## - --collect.engine_innodb_status + ## - --collect.engine_tokudb_status + ## - --collect.global_status + ## - --collect.global_variables + ## - --collect.info_schema.clientstats + ## - --collect.info_schema.innodb_metrics + ## - --collect.info_schema.innodb_tablespaces + ## - --collect.info_schema.innodb_cmp + ## - --collect.info_schema.innodb_cmpmem + ## - --collect.info_schema.processlist + ## - --collect.info_schema.processlist.min_time + ## - --collect.info_schema.query_response_time + ## - --collect.info_schema.tables + ## - --collect.info_schema.tables.databases + ## - --collect.info_schema.tablestats + ## - --collect.info_schema.userstats + ## - --collect.perf_schema.eventsstatements + ## - --collect.perf_schema.eventsstatements.digest_text_limit + ## - --collect.perf_schema.eventsstatements.limit + ## - --collect.perf_schema.eventsstatements.timelimit + ## - --collect.perf_schema.eventswaits + ## - --collect.perf_schema.file_events + ## - --collect.perf_schema.file_instances + ## - --collect.perf_schema.indexiowaits + ## - --collect.perf_schema.tableiowaits + ## - --collect.perf_schema.tablelocks + ## - --collect.perf_schema.replication_group_member_stats + ## - --collect.slave_status + ## - --collect.slave_hosts + ## - --collect.heartbeat + ## - --collect.heartbeat.database + ## - --collect.heartbeat.table + ## + extraArgs: + primary: [] + secondary: [] + ## Mysqld Prometheus exporter resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-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:'. + ## @param metrics.resources.limits The resources limits for MySQL prometheus exporter containers + ## @param metrics.resources.requests The requested resources for MySQL prometheus exporter containers + ## + resources: + ## Example: + ## limits: + ## cpu: 100m + ## memory: 256Mi + ## + limits: {} + ## Examples: + ## requests: + ## cpu: 100m + ## memory: 256Mi + ## + requests: {} + ## Mysqld Prometheus exporter liveness probe + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param metrics.livenessProbe.enabled Enable livenessProbe + ## @param metrics.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param metrics.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param metrics.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param metrics.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param metrics.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 120 + periodSeconds: 10 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 3 + ## Mysqld Prometheus exporter readiness probe + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param metrics.readinessProbe.enabled Enable readinessProbe + ## @param metrics.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param metrics.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param metrics.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param metrics.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param metrics.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 3 + ## Prometheus Service Monitor + ## ref: https://github.com/coreos/prometheus-operator + ## + serviceMonitor: + ## @param metrics.serviceMonitor.enabled Create ServiceMonitor Resource for scraping metrics using PrometheusOperator + ## + enabled: false + ## @param metrics.serviceMonitor.namespace Specify the namespace in which the serviceMonitor resource will be created + ## + namespace: "" + ## @param metrics.serviceMonitor.jobLabel The name of the label on the target service to use as the job name in prometheus. + ## + jobLabel: "" + ## @param metrics.serviceMonitor.interval Specify the interval at which metrics should be scraped + ## + interval: 30s + ## @param metrics.serviceMonitor.scrapeTimeout Specify the timeout after which the scrape is ended + ## e.g: + ## scrapeTimeout: 30s + ## + scrapeTimeout: "" + ## @param metrics.serviceMonitor.relabelings RelabelConfigs to apply to samples before scraping + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#relabelconfig + ## + relabelings: [] + ## @param metrics.serviceMonitor.metricRelabelings MetricRelabelConfigs to apply to samples before ingestion + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#relabelconfig + ## + metricRelabelings: [] + ## @param metrics.serviceMonitor.selector ServiceMonitor selector labels + ## ref: https://github.com/bitnami/charts/tree/main/bitnami/prometheus-operator#prometheus-configuration + ## + ## selector: + ## prometheus: my-prometheus + ## + selector: {} + ## @param metrics.serviceMonitor.honorLabels Specify honorLabels parameter to add the scrape endpoint + ## + honorLabels: false + ## @param metrics.serviceMonitor.labels Used to pass Labels that are used by the Prometheus installed in your cluster to select Service Monitors to work with + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#prometheusspec + ## + labels: {} + ## @param metrics.serviceMonitor.annotations ServiceMonitor annotations + ## + annotations: {} + + ## Prometheus Operator prometheusRule configuration + ## + prometheusRule: + ## @param metrics.prometheusRule.enabled Creates a Prometheus Operator prometheusRule (also requires `metrics.enabled` to be `true` and `metrics.prometheusRule.rules`) + ## + enabled: false + ## @param metrics.prometheusRule.namespace Namespace for the prometheusRule Resource (defaults to the Release Namespace) + ## + namespace: "" + ## @param metrics.prometheusRule.additionalLabels Additional labels that can be used so prometheusRule will be discovered by Prometheus + ## + additionalLabels: {} + ## @param metrics.prometheusRule.rules Prometheus Rule definitions + ## - alert: Mysql-Down + ## expr: absent(up{job="mysql"} == 1) + ## for: 5m + ## labels: + ## severity: warning + ## service: mariadb + ## annotations: + ## message: 'MariaDB instance {{`{{`}} $labels.instance {{`}}`}} is down' + ## summary: MariaDB instance is down + ## + rules: [] diff --git a/backing-services/nginx/.helmignore b/backing-services/nginx/.helmignore new file mode 100644 index 0000000..f0c1319 --- /dev/null +++ b/backing-services/nginx/.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/backing-services/nginx/Chart.lock b/backing-services/nginx/Chart.lock new file mode 100644 index 0000000..ecab3e6 --- /dev/null +++ b/backing-services/nginx/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + version: 2.14.1 +digest: sha256:5ccbe5f1fe4459864a8c9d7329c400b678666b6cfb1450818a830bda81995bc3 +generated: "2023-12-28T09:35:40.844495377Z" diff --git a/backing-services/nginx/Chart.yaml b/backing-services/nginx/Chart.yaml new file mode 100644 index 0000000..7173208 --- /dev/null +++ b/backing-services/nginx/Chart.yaml @@ -0,0 +1,37 @@ +# Copyright VMware, Inc. +# SPDX-License-Identifier: APACHE-2.0 + +annotations: + category: Infrastructure + licenses: Apache-2.0 + images: | + - name: git + image: docker.io/bitnami/git:2.43.0-debian-11-r5 + - name: nginx-exporter + image: docker.io/bitnami/nginx-exporter:1.0.0-debian-11-r0 + - name: nginx + image: docker.io/bitnami/nginx:1.25.3-debian-11-r3 +apiVersion: v2 +appVersion: 1.25.3 +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + tags: + - bitnami-common + version: 2.x.x +description: NGINX Open Source is a web server that can be also used as a reverse proxy, load balancer, and HTTP cache. Recommended for high-demanding sites due to its ability to provide faster content. +home: https://bitnami.com +icon: https://bitnami.com/assets/stacks/nginx/img/nginx-stack-220x234.png +keywords: +- nginx +- http +- web +- www +- reverse proxy +maintainers: +- name: VMware, Inc. + url: https://github.com/bitnami/charts +name: nginx +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/nginx +version: 15.6.0 diff --git a/backing-services/nginx/README.md b/backing-services/nginx/README.md new file mode 100644 index 0000000..b2a2dc5 --- /dev/null +++ b/backing-services/nginx/README.md @@ -0,0 +1,497 @@ + + +# Bitnami package for NGINX Open Source + +NGINX Open Source is a web server that can be also used as a reverse proxy, load balancer, and HTTP cache. Recommended for high-demanding sites due to its ability to provide faster content. + +[Overview of NGINX Open Source](http://nginx.org) + +Trademarks: This software listing is packaged by Bitnami. The respective trademarks mentioned in the offering are owned by the respective companies, and use of them does not imply any affiliation or endorsement. + +## TL;DR + +```console +helm install my-release oci://registry-1.docker.io/bitnamicharts/nginx +``` + +Looking to use NGINX Open Source in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the enterprise edition of Bitnami Application Catalog. + +## Introduction + +Bitnami charts for Helm are carefully engineered, actively maintained and are the quickest and easiest way to deploy containers on a Kubernetes cluster that are ready to handle production workloads. + +This chart bootstraps a [NGINX Open Source](https://github.com/bitnami/containers/tree/main/bitnami/nginx) deployment on a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```console +helm install my-release oci://REGISTRY_NAME/REPOSITORY_NAME/nginx +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +These commands deploy NGINX Open Source on the Kubernetes cluster in the default configuration. + +> **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 + +### Global parameters + +| Name | Description | Value | +| ------------------------- | ----------------------------------------------- | ----- | +| `global.imageRegistry` | Global Docker image registry | `""` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | + +### Common parameters + +| Name | Description | Value | +| ------------------------ | --------------------------------------------------------------------------------------- | --------------- | +| `nameOverride` | String to partially override nginx.fullname template (will maintain the release name) | `""` | +| `fullnameOverride` | String to fully override nginx.fullname template | `""` | +| `namespaceOverride` | String to fully override common.names.namespace | `""` | +| `kubeVersion` | Force target Kubernetes version (using Helm capabilities if not set) | `""` | +| `clusterDomain` | Kubernetes Cluster Domain | `cluster.local` | +| `extraDeploy` | Extra objects to deploy (value evaluated as a template) | `[]` | +| `commonLabels` | Add labels to all the deployed resources | `{}` | +| `commonAnnotations` | Add annotations to all the deployed resources | `{}` | +| `diagnosticMode.enabled` | Enable diagnostic mode (all probes will be disabled and the command will be overridden) | `false` | +| `diagnosticMode.command` | Command to override all containers in the the deployment(s)/statefulset(s) | `["sleep"]` | +| `diagnosticMode.args` | Args to override all containers in the the deployment(s)/statefulset(s) | `["infinity"]` | + +### NGINX parameters + +| Name | Description | Value | +| -------------------- | ----------------------------------------------------------------------------------------------------- | ----------------------- | +| `image.registry` | NGINX image registry | `REGISTRY_NAME` | +| `image.repository` | NGINX image repository | `REPOSITORY_NAME/nginx` | +| `image.digest` | NGINX image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `image.pullPolicy` | NGINX image pull policy | `IfNotPresent` | +| `image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `image.debug` | Set to true if you would like to see extra information on logs | `false` | +| `hostAliases` | Deployment pod host aliases | `[]` | +| `command` | Override default container command (useful when using custom images) | `[]` | +| `args` | Override default container args (useful when using custom images) | `[]` | +| `extraEnvVars` | Extra environment variables to be set on NGINX containers | `[]` | +| `extraEnvVarsCM` | ConfigMap with extra environment variables | `""` | +| `extraEnvVarsSecret` | Secret with extra environment variables | `""` | + +### NGINX deployment parameters + +| Name | Description | Value | +| --------------------------------------------------- | ----------------------------------------------------------------------------------------- | ---------------- | +| `replicaCount` | Number of NGINX replicas to deploy | `1` | +| `revisionHistoryLimit` | The number of old history to retain to allow rollback | `10` | +| `updateStrategy.type` | NGINX deployment strategy type | `RollingUpdate` | +| `updateStrategy.rollingUpdate` | NGINX deployment rolling update configuration parameters | `{}` | +| `podLabels` | Additional labels for NGINX pods | `{}` | +| `podAnnotations` | Annotations for NGINX pods | `{}` | +| `podAffinityPreset` | Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `nodeAffinityPreset.type` | Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `nodeAffinityPreset.key` | Node label key to match Ignored if `affinity` is set. | `""` | +| `nodeAffinityPreset.values` | Node label values to match. Ignored if `affinity` is set. | `[]` | +| `affinity` | Affinity for pod assignment | `{}` | +| `hostNetwork` | Specify if host network should be enabled for NGINX pod | `false` | +| `hostIPC` | Specify if host IPC should be enabled for NGINX pod | `false` | +| `nodeSelector` | Node labels for pod assignment. Evaluated as a template. | `{}` | +| `tolerations` | Tolerations for pod assignment. Evaluated as a template. | `[]` | +| `priorityClassName` | NGINX pods' priorityClassName | `""` | +| `schedulerName` | Name of the k8s scheduler (other than default) | `""` | +| `terminationGracePeriodSeconds` | In seconds, time the given to the NGINX pod needs to terminate gracefully | `""` | +| `topologySpreadConstraints` | Topology Spread Constraints for pod assignment | `[]` | +| `podSecurityContext.enabled` | Enabled NGINX pods' Security Context | `true` | +| `podSecurityContext.fsGroup` | Set NGINX pod's Security Context fsGroup | `1001` | +| `podSecurityContext.sysctls` | sysctl settings of the NGINX pods | `[]` | +| `containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `false` | +| `containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `containerPorts.http` | Sets http port inside NGINX container | `8080` | +| `containerPorts.https` | Sets https port inside NGINX container | `""` | +| `extraContainerPorts` | Array of additional container ports for the Nginx container | `[]` | +| `resources.limits` | The resources limits for the NGINX container | `{}` | +| `resources.requests` | The requested resources for the NGINX container | `{}` | +| `lifecycleHooks` | Optional lifecycleHooks for the NGINX container | `{}` | +| `startupProbe.enabled` | Enable startupProbe | `false` | +| `startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `30` | +| `startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `startupProbe.failureThreshold` | Failure threshold for startupProbe | `6` | +| `startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `livenessProbe.enabled` | Enable livenessProbe | `true` | +| `livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `30` | +| `livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `readinessProbe.enabled` | Enable readinessProbe | `true` | +| `readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `readinessProbe.periodSeconds` | Period seconds for readinessProbe | `5` | +| `readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `3` | +| `readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `3` | +| `readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `customStartupProbe` | Custom liveness probe for the Web component | `{}` | +| `customLivenessProbe` | Override default liveness probe | `{}` | +| `customReadinessProbe` | Override default readiness probe | `{}` | +| `autoscaling.enabled` | Enable autoscaling for NGINX deployment | `false` | +| `autoscaling.minReplicas` | Minimum number of replicas to scale back | `""` | +| `autoscaling.maxReplicas` | Maximum number of replicas to scale out | `""` | +| `autoscaling.targetCPU` | Target CPU utilization percentage | `""` | +| `autoscaling.targetMemory` | Target Memory utilization percentage | `""` | +| `extraVolumes` | Array to add extra volumes | `[]` | +| `extraVolumeMounts` | Array to add extra mount | `[]` | +| `serviceAccount.create` | Enable creation of ServiceAccount for nginx pod | `false` | +| `serviceAccount.name` | The name of the ServiceAccount to use. | `""` | +| `serviceAccount.annotations` | Annotations for service account. Evaluated as a template. | `{}` | +| `serviceAccount.automountServiceAccountToken` | Auto-mount the service account token in the pod | `false` | +| `sidecars` | Sidecar parameters | `[]` | +| `sidecarSingleProcessNamespace` | Enable sharing the process namespace with sidecars | `false` | +| `initContainers` | Extra init containers | `[]` | +| `pdb.create` | Created a PodDisruptionBudget | `false` | +| `pdb.minAvailable` | Min number of pods that must still be available after the eviction. | `1` | +| `pdb.maxUnavailable` | Max number of pods that can be unavailable after the eviction. | `0` | + +### Custom NGINX application parameters + +| Name | Description | Value | +| --------------------------------------------------- | --------------------------------------------------------------------------------------------------- | --------------------- | +| `cloneStaticSiteFromGit.enabled` | Get the server static content from a Git repository | `false` | +| `cloneStaticSiteFromGit.image.registry` | Git image registry | `REGISTRY_NAME` | +| `cloneStaticSiteFromGit.image.repository` | Git image repository | `REPOSITORY_NAME/git` | +| `cloneStaticSiteFromGit.image.digest` | Git image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `cloneStaticSiteFromGit.image.pullPolicy` | Git image pull policy | `IfNotPresent` | +| `cloneStaticSiteFromGit.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `cloneStaticSiteFromGit.repository` | Git Repository to clone static content from | `""` | +| `cloneStaticSiteFromGit.branch` | Git branch to checkout | `""` | +| `cloneStaticSiteFromGit.interval` | Interval for sidecar container pull from the Git repository | `60` | +| `cloneStaticSiteFromGit.gitClone.command` | Override default container command for git-clone-repository | `[]` | +| `cloneStaticSiteFromGit.gitClone.args` | Override default container args for git-clone-repository | `[]` | +| `cloneStaticSiteFromGit.gitSync.command` | Override default container command for git-repo-syncer | `[]` | +| `cloneStaticSiteFromGit.gitSync.args` | Override default container args for git-repo-syncer | `[]` | +| `cloneStaticSiteFromGit.gitSync.resources.limits` | The resources limits for the git-repo-syncer container | `{}` | +| `cloneStaticSiteFromGit.gitSync.resources.requests` | The requested resources for the git-repo-syncer container | `{}` | +| `cloneStaticSiteFromGit.extraEnvVars` | Additional environment variables to set for the in the containers that clone static site from git | `[]` | +| `cloneStaticSiteFromGit.extraEnvVarsSecret` | Secret with extra environment variables | `""` | +| `cloneStaticSiteFromGit.extraVolumeMounts` | Add extra volume mounts for the Git containers | `[]` | +| `serverBlock` | Custom server block to be added to NGINX configuration | `""` | +| `existingServerBlockConfigmap` | ConfigMap with custom server block to be added to NGINX configuration | `""` | +| `staticSiteConfigmap` | Name of existing ConfigMap with the server static site content | `""` | +| `staticSitePVC` | Name of existing PVC with the server static site content | `""` | + +### Traffic Exposure parameters + +| Name | Description | Value | +| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | +| `service.type` | Service type | `LoadBalancer` | +| `service.ports.http` | Service HTTP port | `80` | +| `service.ports.https` | Service HTTPS port | `443` | +| `service.nodePorts` | Specify the nodePort(s) value(s) for the LoadBalancer and NodePort service types. | `{}` | +| `service.targetPort` | Target port reference value for the Loadbalancer service types can be specified explicitly. | `{}` | +| `service.clusterIP` | NGINX service Cluster IP | `""` | +| `service.loadBalancerIP` | LoadBalancer service IP address | `""` | +| `service.loadBalancerSourceRanges` | NGINX service Load Balancer sources | `[]` | +| `service.loadBalancerClass` | service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) | `""` | +| `service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` | +| `service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `service.annotations` | Service annotations | `{}` | +| `service.externalTrafficPolicy` | Enable client source IP preservation | `Cluster` | +| `ingress.enabled` | Set to true to enable ingress record generation | `false` | +| `ingress.selfSigned` | Create a TLS secret for this ingress record using self-signed certificates generated by Helm | `false` | +| `ingress.pathType` | Ingress path type | `ImplementationSpecific` | +| `ingress.apiVersion` | Force Ingress API version (automatically detected if not set) | `""` | +| `ingress.hostname` | Default host for the ingress resource | `nginx.local` | +| `ingress.path` | The Path to Nginx. You may need to set this to '/*' in order to use this with ALB ingress controllers. | `/` | +| `ingress.annotations` | Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. | `{}` | +| `ingress.ingressClassName` | Set the ingerssClassName on the ingress record for k8s 1.18+ | `""` | +| `ingress.tls` | Create TLS Secret | `false` | +| `ingress.extraHosts` | The list of additional hostnames to be covered with this ingress record. | `[]` | +| `ingress.extraPaths` | Any additional arbitrary paths that may need to be added to the ingress under the main host. | `[]` | +| `ingress.extraTls` | The tls configuration for additional hostnames to be covered with this ingress record. | `[]` | +| `ingress.secrets` | If you're providing your own certificates, please use this to add the certificates as secrets | `[]` | +| `ingress.extraRules` | The list of additional rules to be added to this ingress record. Evaluated as a template | `[]` | +| `healthIngress.enabled` | Set to true to enable health ingress record generation | `false` | +| `healthIngress.selfSigned` | Create a TLS secret for this ingress record using self-signed certificates generated by Helm | `false` | +| `healthIngress.pathType` | Ingress path type | `ImplementationSpecific` | +| `healthIngress.hostname` | When the health ingress is enabled, a host pointing to this will be created | `example.local` | +| `healthIngress.path` | Default path for the ingress record | `/` | +| `healthIngress.annotations` | Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. | `{}` | +| `healthIngress.tls` | Enable TLS configuration for the hostname defined at `healthIngress.hostname` parameter | `false` | +| `healthIngress.extraHosts` | An array with additional hostname(s) to be covered with the ingress record | `[]` | +| `healthIngress.extraPaths` | An array with additional arbitrary paths that may need to be added to the ingress under the main host | `[]` | +| `healthIngress.extraTls` | TLS configuration for additional hostnames to be covered | `[]` | +| `healthIngress.secrets` | TLS Secret configuration | `[]` | +| `healthIngress.ingressClassName` | IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+) | `""` | +| `healthIngress.extraRules` | The list of additional rules to be added to this ingress record. Evaluated as a template | `[]` | + +### Metrics parameters + +| Name | Description | Value | +| ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | +| `metrics.enabled` | Start a Prometheus exporter sidecar container | `false` | +| `metrics.image.registry` | NGINX Prometheus exporter image registry | `REGISTRY_NAME` | +| `metrics.image.repository` | NGINX Prometheus exporter image repository | `REPOSITORY_NAME/nginx-exporter` | +| `metrics.image.digest` | NGINX Prometheus exporter image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `metrics.image.pullPolicy` | NGINX Prometheus exporter image pull policy | `IfNotPresent` | +| `metrics.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `metrics.port` | NGINX Container Status Port scraped by Prometheus Exporter | `""` | +| `metrics.extraArgs` | Extra arguments for Prometheus exporter | `[]` | +| `metrics.containerPorts.metrics` | Prometheus exporter container port | `9113` | +| `metrics.podAnnotations` | Additional annotations for NGINX Prometheus exporter pod(s) | `{}` | +| `metrics.securityContext.enabled` | Enabled NGINX Exporter containers' Security Context | `false` | +| `metrics.securityContext.runAsUser` | Set NGINX Exporter container's Security Context runAsUser | `1001` | +| `metrics.service.port` | NGINX Prometheus exporter service port | `9113` | +| `metrics.service.annotations` | Annotations for the Prometheus exporter service | `{}` | +| `metrics.resources.limits` | The resources limits for the NGINX Prometheus exporter container | `{}` | +| `metrics.resources.requests` | The requested resources for the NGINX Prometheus exporter container | `{}` | +| `metrics.serviceMonitor.enabled` | Creates a Prometheus Operator ServiceMonitor (also requires `metrics.enabled` to be `true`) | `false` | +| `metrics.serviceMonitor.namespace` | Namespace in which Prometheus is running | `""` | +| `metrics.serviceMonitor.jobLabel` | The name of the label on the target service to use as the job name in prometheus. | `""` | +| `metrics.serviceMonitor.interval` | Interval at which metrics should be scraped. | `""` | +| `metrics.serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended | `""` | +| `metrics.serviceMonitor.selector` | Prometheus instance selector labels | `{}` | +| `metrics.serviceMonitor.labels` | Additional labels that can be used so PodMonitor will be discovered by Prometheus | `{}` | +| `metrics.serviceMonitor.relabelings` | RelabelConfigs to apply to samples before scraping | `[]` | +| `metrics.serviceMonitor.metricRelabelings` | MetricRelabelConfigs to apply to samples before ingestion | `[]` | +| `metrics.serviceMonitor.honorLabels` | honorLabels chooses the metric's labels on collisions with target labels | `false` | +| `metrics.prometheusRule.enabled` | if `true`, creates a Prometheus Operator PrometheusRule (also requires `metrics.enabled` to be `true` and `metrics.prometheusRule.rules`) | `false` | +| `metrics.prometheusRule.namespace` | Namespace for the PrometheusRule Resource (defaults to the Release Namespace) | `""` | +| `metrics.prometheusRule.additionalLabels` | Additional labels that can be used so PrometheusRule will be discovered by Prometheus | `{}` | +| `metrics.prometheusRule.rules` | Prometheus Rule definitions | `[]` | + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +helm install my-release \ + --set imagePullPolicy=Always \ + oci://REGISTRY_NAME/REPOSITORY_NAME/nginx +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The above command sets the `imagePullPolicy` to `Always`. + +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 oci://REGISTRY_NAME/REPOSITORY_NAME/nginx +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> **Tip**: You can use the default [values.yaml](https://github.com/bitnami/charts/tree/main/bitnami/nginx/values.yaml) + +## Configuration and installation details + +### [Rolling VS Immutable tags](https://docs.bitnami.com/tutorials/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. + +### Use a different NGINX version + +To modify the application version used in this chart, specify a different version of the image using the `image.tag` parameter and/or a different repository using the `image.repository` parameter. Refer to the [chart documentation for more information on these parameters and how to use them with images from a private registry](https://docs.bitnami.com/kubernetes/infrastructure/nginx/configuration/change-image-version/). + +### Deploying your custom web application + +The NGINX chart allows you to deploy a custom web application using one of the following methods: + +- Cloning from a git repository: Set `cloneStaticSiteFromGit.enabled` to `true` and set the repository and branch using the `cloneStaticSiteFromGit.repository` and `cloneStaticSiteFromGit.branch` parameters. A sidecar will also pull the latest changes in an interval set by `cloneStaticSitesFromGit.interval`. +- Providing a ConfigMap: Set the `staticSiteConfigmap` value to mount a ConfigMap in the NGINX html folder. +- Using an existing PVC: Set the `staticSitePVC` value to mount an PersistentVolumeClaim with the static site content. + +You can deploy a example web application using git deploying the chart with the following parameters: + +```console +cloneStaticSiteFromGit.enabled=true +cloneStaticSiteFromGit.repository=https://github.com/mdn/beginner-html-site-styled.git +cloneStaticSiteFromGit.branch=master +``` + +### Providing a custom server block + +This helm chart supports using custom custom server block for NGINX to use. + +You can use the `serverBlock` value to provide a custom server block for NGINX to use. To do this, create a values files with your server block and install the chart using it: + +```yaml +serverBlock: |- + server { + listen 0.0.0.0:8080; + location / { + return 200 "hello!"; + } + } +``` + +> Warning: The above example is not compatible with enabling Prometheus metrics since it affects the `/status` endpoint. + +In addition, you can also set an external ConfigMap with the configuration file. This is done by setting the `existingServerBlockConfigmap` parameter. Note that this will override the previous option. + +### Adding extra environment variables + +In case you want to add extra environment variables (useful for advanced operations like custom init scripts), you can use the `extraEnvVars` property. + +```yaml +extraEnvVars: + - name: LOG_LEVEL + value: error +``` + +Alternatively, you can use a ConfigMap or a Secret with the environment variables. To do so, use the `extraEnvVarsCM` or the `extraEnvVarsSecret` values. + +### Setting Pod's affinity + +This chart allows you to set your custom affinity using the `affinity` parameter. Find more information about Pod's affinity in the [kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). + +As an alternative, you can use of the preset configurations for pod affinity, pod anti-affinity, and node affinity available at the [bitnami/common](https://github.com/bitnami/charts/tree/main/bitnami/common#affinity) chart. To do so, set the `podAffinityPreset`, `podAntiAffinityPreset`, or `nodeAffinityPreset` parameters. + +### Deploying extra resources + +There are cases where you may want to deploy extra objects, such a ConfigMap containing your app's configuration or some extra deployment with a micro service used by your app. For covering this case, the chart allows adding the full specification of other objects using the `extraDeploy` parameter. + +### Ingress + +This chart provides support for ingress resources. If you have an ingress controller installed on your cluster, such as [nginx-ingress-controller](https://github.com/bitnami/charts/tree/main/bitnami/nginx-ingress-controller) or [contour](https://github.com/bitnami/charts/tree/main/bitnami/contour) you can utilize the ingress controller to serve your application. + +To enable ingress integration, please set `ingress.enabled` to `true`. + +#### Hosts + +Most likely you will only want to have one hostname that maps to this NGINX installation. If that's your case, the property `ingress.hostname` will set it. However, it is possible to have more than one host. To facilitate this, the `ingress.extraHosts` object can be specified as an array. You can also use `ingress.extraTLS` to add the TLS configuration for extra hosts. + +For each host indicated at `ingress.extraHosts`, please indicate a `name`, `path`, and any `annotations` that you may want the ingress controller to know about. + +For annotations, please see [this document](https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md). Not all annotations are supported by all ingress controllers, but this document does a good job of indicating which annotation is supported by many popular ingress controllers. + +## Troubleshooting + +Find more information about how to deal with common errors related to Bitnami's Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues). + +## Upgrading + +### To 11.0.0 + +This major release renames several values in this chart and adds missing features, in order to be aligned with the rest of the assets in the Bitnami charts repository. + +Affected values: + +- `service.port` was renamed as `service.ports.http`. +- `service.httpsPort` was deprecated. We recommend using `service.ports.https`. +- `serviceAccount.autoMount` was renamed as `serviceAccount.automountServiceAccountToken` +- `metrics.serviceMonitor.additionalLabels` was renamed as `metrics.serviceMonitor.labels` + +### To 10.0.0 + +This major release no longer uses the bitnami/nginx-ldap-auth-daemon container as a dependency since its upstream project is not actively maintained. + +*2022-04-12 edit*: + +[Bitnami's reference implementation](https://www.nginx.com/blog/nginx-plus-authenticate-users/). + +On 9 April 2022, security vulnerabilities in the [NGINX LDAP reference implementation](https://github.com/nginxinc/nginx-ldap-auth) were publicly shared. **Although the deprecation of this container from the Bitnami catalog was not related to this security issue, [here](https://docs.bitnami.com/general/security/) you can find more information from the Bitnami security team.** + +### To 8.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +#### What changes were introduced in this major version? + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- Move dependency information from the *requirements.yaml* to the *Chart.yaml* +- After running `helm dependency update`, a *Chart.lock* file is generated containing the same structure used in the previous *requirements.lock* +- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts + +#### Considerations when upgrading to this version + +- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues +- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore +- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 + +#### Useful links + +- +- +- + +### To 7.0.0 + +- This version also introduces `bitnami/common`, a [library chart](https://helm.sh/docs/topics/library_charts/#helm) as a dependency. More documentation about this new utility could be found [here](https://github.com/bitnami/charts/tree/main/bitnami/common#bitnami-common-library-chart). Please, make sure that you have updated the chart dependencies before executing any upgrade. +- Ingress configuration was also adapted to follow the Helm charts best practices. + +> Note: There is no backwards compatibility due to the above mentioned changes. It's necessary to install a new release of the chart, and migrate your existing application to the new NGINX instances. + +### To 5.6.0 + +Added support for the use of LDAP. + +### To 5.0.0 + +Backwards compatibility is not guaranteed unless you modify the labels used on the chart's deployments. +Use the workaround below to upgrade from versions previous to 5.0.0. The following example assumes that the release name is nginx: + +```console +kubectl delete deployment nginx --cascade=false +helm upgrade nginx oci://REGISTRY_NAME/REPOSITORY_NAME/nginx +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +### To 1.0.0 + +Backwards compatibility is not guaranteed unless you modify the labels used on the chart's deployments. +Use the workaround below to upgrade from versions previous to 1.0.0. The following example assumes that the release name is nginx: + +```console +kubectl patch deployment nginx --type=json -p='[{"op": "remove", "path": "/spec/selector/matchLabels/chart"}]' +``` + +## Bitnami Kubernetes Documentation + +Bitnami Kubernetes documentation is available at [https://docs.bitnami.com/](https://docs.bitnami.com/). You can find there the following resources: + +- [Documentation for NGINX Helm chart](https://docs.bitnami.com/kubernetes/infrastructure/nginx/) +- [Get Started with Kubernetes guides](https://docs.bitnami.com/kubernetes/) +- [Bitnami Helm charts documentation](https://docs.bitnami.com/kubernetes/apps/) +- [Kubernetes FAQs](https://docs.bitnami.com/kubernetes/faq/) +- [Kubernetes Developer guides](https://docs.bitnami.com/tutorials/) + +## License + +Copyright © 2024 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/backing-services/nginx/templates/NOTES.txt b/backing-services/nginx/templates/NOTES.txt new file mode 100644 index 0000000..ba3e6f6 --- /dev/null +++ b/backing-services/nginx/templates/NOTES.txt @@ -0,0 +1,72 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +** Please be patient while the chart is being deployed ** + +{{- if .Values.diagnosticMode.enabled }} +The chart has been deployed in diagnostic mode. All probes have been disabled and the command has been overwritten with: + + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 4 }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 4 }} + +Get the list of pods by executing: + + kubectl get pods --namespace {{ template "common.names.namespace" . }} -l app.kubernetes.io/instance={{ .Release.Name }} + +Access the pod you want to debug by executing + + kubectl exec --namespace {{ template "common.names.namespace" . }} -ti -- bash + +In order to replicate the container startup scripts execute this command: + + /opt/bitnami/scripts/nginx/entrypoint.sh /opt/bitnami/scripts/nginx/run.sh + +{{- else }} +NGINX can be accessed through the following DNS name from within your cluster: + + {{ include "common.names.fullname" . }}.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }} (port {{ .Values.service.ports.http }}) + +To access NGINX from outside the cluster, follow the steps below: + +{{- if .Values.ingress.enabled }} + +1. Get the NGINX URL and associate its hostname to your cluster external IP: + + export CLUSTER_IP=$(minikube ip) # On Minikube. Use: `kubectl cluster-info` on others K8s clusters + echo "NGINX URL: http{{ if .Values.ingress.tls }}s{{ end }}://{{ .Values.ingress.hostname }}" + echo "$CLUSTER_IP {{ .Values.ingress.hostname }}" | sudo tee -a /etc/hosts + +{{- else }} + +1. Get the NGINX URL by running these commands: + +{{- 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 {{ include "common.names.fullname" . }}' + + export SERVICE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].port}" services {{ include "common.names.fullname" . }}) + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "common.names.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo "http://${SERVICE_IP}:${SERVICE_PORT}" + +{{- else if contains "ClusterIP" .Values.service.type }} + + export SERVICE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].port}" services {{ include "common.names.fullname" . }}) + kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ include "common.names.fullname" . }} ${SERVICE_PORT}:${SERVICE_PORT} & + echo "http://127.0.0.1:${SERVICE_PORT}" + +{{- else if contains "NodePort" .Values.service.type }} + + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "common.names.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo "http://${NODE_IP}:${NODE_PORT}" + +{{- end }} +{{- end }} + +{{- include "common.warnings.rollingTag" .Values.image }} +{{- include "common.warnings.rollingTag" .Values.cloneStaticSiteFromGit.image }} +{{- include "common.warnings.rollingTag" .Values.metrics.image }} +{{- include "nginx.validateValues" . }} +{{- end }} diff --git a/backing-services/nginx/templates/_helpers.tpl b/backing-services/nginx/templates/_helpers.tpl new file mode 100644 index 0000000..d614f94 --- /dev/null +++ b/backing-services/nginx/templates/_helpers.tpl @@ -0,0 +1,112 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Return the proper NGINX image name +*/}} +{{- define "nginx.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper GIT image name +*/}} +{{- define "nginx.cloneStaticSiteFromGit.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.cloneStaticSiteFromGit.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper Prometheus metrics image name +*/}} +{{- define "nginx.metrics.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.metrics.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "nginx.imagePullSecrets" -}} +{{ include "common.images.renderPullSecrets" (dict "images" (list .Values.image .Values.cloneStaticSiteFromGit.image .Values.metrics.image) "context" $) }} +{{- end -}} + +{{/* +Return true if a static site should be mounted in the NGINX container +*/}} +{{- define "nginx.useStaticSite" -}} +{{- if or .Values.cloneStaticSiteFromGit.enabled .Values.staticSiteConfigmap .Values.staticSitePVC }} + {- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the volume to use to mount the static site in the NGINX container +*/}} +{{- define "nginx.staticSiteVolume" -}} +{{- if .Values.cloneStaticSiteFromGit.enabled }} +emptyDir: {} +{{- else if .Values.staticSiteConfigmap }} +configMap: + name: {{ printf "%s" (tpl .Values.staticSiteConfigmap $) -}} +{{- else if .Values.staticSitePVC }} +persistentVolumeClaim: + claimName: {{ printf "%s" (tpl .Values.staticSitePVC $) -}} +{{- end }} +{{- end -}} + +{{/* +Return the custom NGINX server block configmap. +*/}} +{{- define "nginx.serverBlockConfigmapName" -}} +{{- if .Values.existingServerBlockConfigmap -}} + {{- printf "%s" (tpl .Values.existingServerBlockConfigmap $) -}} +{{- else -}} + {{- printf "%s-server-block" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Compile all warnings into a single message, and call fail. +*/}} +{{- define "nginx.validateValues" -}} +{{- $messages := list -}} +{{- $messages := append $messages (include "nginx.validateValues.cloneStaticSiteFromGit" .) -}} +{{- $messages := append $messages (include "nginx.validateValues.extraVolumes" .) -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}} +{{- end -}} +{{- end -}} + +{{/* Validate values of NGINX - Clone StaticSite from Git configuration */}} +{{- define "nginx.validateValues.cloneStaticSiteFromGit" -}} +{{- if and .Values.cloneStaticSiteFromGit.enabled (or (not .Values.cloneStaticSiteFromGit.repository) (not .Values.cloneStaticSiteFromGit.branch)) -}} +nginx: cloneStaticSiteFromGit + When enabling cloing a static site from a Git repository, both the Git repository and the Git branch must be provided. + Please provide them by setting the `cloneStaticSiteFromGit.repository` and `cloneStaticSiteFromGit.branch` parameters. +{{- end -}} +{{- end -}} + +{{/* Validate values of NGINX - Incorrect extra volume settings */}} +{{- define "nginx.validateValues.extraVolumes" -}} +{{- if and (.Values.extraVolumes) (not (or .Values.extraVolumeMounts .Values.cloneStaticSiteFromGit.extraVolumeMounts)) -}} +nginx: missing-extra-volume-mounts + You specified extra volumes but not mount points for them. Please set + the extraVolumeMounts value +{{- end -}} +{{- end -}} + +{{/* + Create the name of the service account to use + */}} +{{- define "nginx.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "common.names.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/backing-services/nginx/templates/deployment.yaml b/backing-services/nginx/templates/deployment.yaml new file mode 100644 index 0000000..0720cbb --- /dev/null +++ b/backing-services/nginx/templates/deployment.yaml @@ -0,0 +1,299 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} +kind: Deployment +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + {{- if .Values.updateStrategy }} + strategy: {{- toYaml .Values.updateStrategy | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + annotations: + {{- if .Values.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.podAnnotations "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.podAnnotations "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.serverBlock (not .Values.existingServerBlockConfigmap) }} + checksum/server-block-configuration: {{ include (print $.Template.BasePath "/server-block-configmap.yaml") . | sha256sum }} + {{- end }} + spec: + {{- include "nginx.imagePullSecrets" . | nindent 6 }} + automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} + shareProcessNamespace: {{ .Values.sidecarSingleProcessNamespace }} + serviceAccountName: {{ template "nginx.serviceAccountName" . }} + {{- if .Values.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAffinityPreset "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAntiAffinityPreset "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.nodeAffinityPreset.type "key" .Values.nodeAffinityPreset.key "values" .Values.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + hostNetwork: {{ .Values.hostNetwork }} + hostIPC: {{ .Values.hostIPC }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName | quote }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.schedulerName }} + schedulerName: {{ .Values.schedulerName | quote }} + {{- end }} + {{- if .Values.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- omit .Values.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} + {{- end }} + initContainers: + {{- if .Values.cloneStaticSiteFromGit.enabled }} + - name: git-clone-repository + image: {{ include "nginx.cloneStaticSiteFromGit.image" . }} + imagePullPolicy: {{ .Values.cloneStaticSiteFromGit.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.cloneStaticSiteFromGit.gitClone.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.cloneStaticSiteFromGit.gitClone.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -ec + - | + [[ -f "/opt/bitnami/scripts/git/entrypoint.sh" ]] && source "/opt/bitnami/scripts/git/entrypoint.sh" + git clone {{ .Values.cloneStaticSiteFromGit.repository }} --branch {{ .Values.cloneStaticSiteFromGit.branch }} /tmp/app + [[ "$?" -eq 0 ]] && shopt -s dotglob && rm -rf /app/* && mv /tmp/app/* /app/ + {{- end }} + {{- if .Values.cloneStaticSiteFromGit.gitClone.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.cloneStaticSiteFromGit.gitClone.args "context" $) | nindent 12 }} + {{- end }} + volumeMounts: + - name: staticsite + mountPath: /app + {{- if .Values.cloneStaticSiteFromGit.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.cloneStaticSiteFromGit.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.cloneStaticSiteFromGit.extraEnvVars }} + env: {{- include "common.tplvalues.render" (dict "value" .Values.cloneStaticSiteFromGit.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.cloneStaticSiteFromGit.extraEnvVarsSecret }} + envFrom: + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.cloneStaticSiteFromGit.extraEnvVarsSecret "context" $) }} + {{- end }} + {{- end }} + {{- if .Values.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.initContainers "context" $) | nindent 8 }} + {{- end }} + containers: + {{- if .Values.cloneStaticSiteFromGit.enabled }} + - name: git-repo-syncer + image: {{ include "nginx.cloneStaticSiteFromGit.image" . }} + imagePullPolicy: {{ .Values.cloneStaticSiteFromGit.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.cloneStaticSiteFromGit.gitSync.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.cloneStaticSiteFromGit.gitSync.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -ec + - | + [[ -f "/opt/bitnami/scripts/git/entrypoint.sh" ]] && source "/opt/bitnami/scripts/git/entrypoint.sh" + while true; do + cd /app && git -c safe.directory=/app pull origin {{ .Values.cloneStaticSiteFromGit.branch }} + sleep {{ .Values.cloneStaticSiteFromGit.interval }} + done + {{- end }} + {{- if .Values.cloneStaticSiteFromGit.gitSync.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.cloneStaticSiteFromGit.gitSync.args "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.cloneStaticSiteFromGit.gitSync.resources }} + resources: {{- toYaml .Values.cloneStaticSiteFromGit.gitSync.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: staticsite + mountPath: /app + {{- if .Values.cloneStaticSiteFromGit.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.cloneStaticSiteFromGit.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.cloneStaticSiteFromGit.extraEnvVars }} + env: {{- include "common.tplvalues.render" (dict "value" .Values.cloneStaticSiteFromGit.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.cloneStaticSiteFromGit.extraEnvVarsSecret }} + envFrom: + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.cloneStaticSiteFromGit.extraEnvVarsSecret "context" $) }} + {{- end }} + {{- end }} + - name: nginx + image: {{ include "nginx.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.args "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" .Values.image.debug | quote }} + - name: NGINX_HTTP_PORT_NUMBER + value: {{ .Values.containerPorts.http | quote }} + {{- if .Values.containerPorts.https }} + - name: NGINX_HTTPS_PORT_NUMBER + value: {{ .Values.containerPorts.https | quote }} + {{- end }} + {{- if .Values.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.extraEnvVarsSecret "context" $) }} + {{- end }} + ports: + - name: http + containerPort: {{ .Values.containerPorts.http }} + {{- if .Values.containerPorts.https }} + - name: https + containerPort: {{ .Values.containerPorts.https }} + {{- end }} + {{- if .Values.extraContainerPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraContainerPorts "context" $) | nindent 12 }} + {{- end }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.livenessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: http + {{- end }} + {{- if .Values.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.readinessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: http + {{- end }} + {{- if .Values.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: http + {{- end }} + {{- end }} + {{- if .Values.resources }} + resources: {{- toYaml .Values.resources | nindent 12 }} + {{- end }} + volumeMounts: + {{- if or .Values.serverBlock .Values.existingServerBlockConfigmap }} + - name: nginx-server-block + mountPath: /opt/bitnami/nginx/conf/server_blocks + {{- end }} + {{- if (include "nginx.useStaticSite" .) }} + - name: staticsite + mountPath: /app + {{- end }} + {{- if .Values.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ include "nginx.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.metrics.securityContext.enabled }} + securityContext: {{- omit .Values.metrics.securityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + command: + - exporter + args: + - --nginx.scrape-uri + - {{ printf "http://127.0.0.1:%d/status" (int (default .Values.containerPorts.http .Values.metrics.port)) | quote }} + - --web.listen-address + - {{ printf ":%d" (int .Values.metrics.containerPorts.metrics) | quote }} + {{- if .Values.metrics.extraArgs }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.extraArgs "context" $ ) | nindent 12 }} + {{- end }} + ports: + - name: metrics + containerPort: {{ .Values.metrics.containerPorts.metrics }} + livenessProbe: + httpGet: + path: /metrics + port: metrics + initialDelaySeconds: 15 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: /metrics + port: metrics + initialDelaySeconds: 5 + timeoutSeconds: 1 + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.sidecars }} + {{- include "common.tplvalues.render" ( dict "value" .Values.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + {{- if or .Values.serverBlock .Values.existingServerBlockConfigmap }} + - name: nginx-server-block + configMap: + name: {{ include "nginx.serverBlockConfigmapName" . }} + {{- end }} + {{- if (include "nginx.useStaticSite" .) }} + - name: staticsite + {{- include "nginx.staticSiteVolume" . | nindent 10 }} + {{- end }} + {{- if .Values.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.extraVolumes "context" $) | nindent 8 }} + {{- end }} diff --git a/backing-services/nginx/templates/extra-list.yaml b/backing-services/nginx/templates/extra-list.yaml new file mode 100644 index 0000000..2d35a58 --- /dev/null +++ b/backing-services/nginx/templates/extra-list.yaml @@ -0,0 +1,9 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/backing-services/nginx/templates/health-ingress.yaml b/backing-services/nginx/templates/health-ingress.yaml new file mode 100644 index 0000000..8aa7d2f --- /dev/null +++ b/backing-services/nginx/templates/health-ingress.yaml @@ -0,0 +1,59 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.healthIngress.enabled }} +apiVersion: {{ include "common.capabilities.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ include "common.names.fullname" . }}-health + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.healthIngress.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.healthIngress.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.healthIngress.ingressClassName (eq "true" (include "common.ingress.supportsIngressClassname" .)) }} + ingressClassName: {{ .Values.healthIngress.ingressClassName | quote }} + {{- end }} + rules: + {{- if .Values.healthIngress.hostname }} + - host: {{ .Values.healthIngress.hostname }} + http: + paths: + {{- if .Values.healthIngress.extraPaths }} + {{- toYaml .Values.healthIngress.extraPaths | nindent 10 }} + {{- end }} + - path: {{ .Values.healthIngress.path }} + {{- if eq "true" (include "common.ingress.supportsPathType" .) }} + pathType: {{ .Values.healthIngress.pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" .) "servicePort" "http" "context" $) | nindent 14 }} + {{- end }} + {{- range .Values.healthIngress.extraHosts }} + - host: {{ .name | quote }} + http: + paths: + - path: {{ default "/" .path }} + {{- if eq "true" (include "common.ingress.supportsPathType" $) }} + pathType: {{ default "ImplementationSpecific" .pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" $) "servicePort" "http" "context" $) | nindent 14 }} + {{- end }} + {{- if .Values.healthIngress.extraRules }} + {{- include "common.tplvalues.render" (dict "value" .Values.healthIngress.extraRules "context" $) | nindent 4 }} + {{- end }} + {{- if or (and .Values.healthIngress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.healthIngress.annotations )) .Values.healthIngress.selfSigned (not (empty .Values.healthIngress.secrets)))) .Values.healthIngress.extraTls }} + tls: + {{- if and .Values.healthIngress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.healthIngress.annotations )) .Values.healthIngress.selfSigned (not (empty .Values.healthIngress.secrets))) }} + - hosts: + - {{ .Values.healthIngress.hostname | quote }} + secretName: {{ printf "%s-health-tls" .Values.healthIngress.hostname }} + {{- end }} + {{- if .Values.healthIngress.extraTls }} + {{- include "common.tplvalues.render" (dict "value" .Values.healthIngress.extraTls "context" $) | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/nginx/templates/hpa.yaml b/backing-services/nginx/templates/hpa.yaml new file mode 100644 index 0000000..decf311 --- /dev/null +++ b/backing-services/nginx/templates/hpa.yaml @@ -0,0 +1,48 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.autoscaling.enabled }} +apiVersion: {{ include "common.capabilities.hpa.apiVersion" ( dict "context" $ ) }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + scaleTargetRef: + apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} + kind: Deployment + name: {{ template "common.names.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetMemory }} + - type: Resource + resource: + name: memory + {{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .) }} + targetAverageUtilization: {{ .Values.autoscaling.targetMemory }} + {{- else }} + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemory }} + {{- end }} + {{- end }} + {{- if .Values.autoscaling.targetCPU }} + - type: Resource + resource: + name: cpu + {{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .) }} + targetAverageUtilization: {{ .Values.autoscaling.targetCPU }} + {{- else }} + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPU }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/nginx/templates/ingress.yaml b/backing-services/nginx/templates/ingress.yaml new file mode 100644 index 0000000..4382f0a --- /dev/null +++ b/backing-services/nginx/templates/ingress.yaml @@ -0,0 +1,70 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.ingress.enabled }} +apiVersion: {{ include "common.capabilities.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.ingress.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.ingress.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.ingressClassName (eq "true" (include "common.ingress.supportsIngressClassname" .)) }} + ingressClassName: {{ .Values.ingress.ingressClassName | quote }} + {{- end }} + rules: + {{- if .Values.ingress.hostname }} + - host: {{ .Values.ingress.hostname | quote }} + http: + paths: + {{- if .Values.ingress.extraPaths }} + {{- toYaml .Values.ingress.extraPaths | nindent 10 }} + {{- end }} + - path: {{ .Values.ingress.path }} + {{- if eq "true" (include "common.ingress.supportsPathType" .) }} + pathType: {{ .Values.ingress.pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" .) "servicePort" "http" "context" $) | nindent 14 }} + {{- else if .Values.ingress.path }} + - http: + paths: + {{- if .Values.ingress.extraPaths }} + {{- toYaml .Values.ingress.extraPaths | nindent 10 }} + {{- end }} + - path: {{ .Values.ingress.path }} + {{- if eq "true" (include "common.ingress.supportsPathType" .) }} + pathType: {{ .Values.ingress.pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" .) "servicePort" "http" "context" $) | nindent 14 }} + {{- end }} + {{- range .Values.ingress.extraHosts }} + - host: {{ .name | quote }} + http: + paths: + - path: {{ default "/" .path }} + {{- if eq "true" (include "common.ingress.supportsPathType" $) }} + pathType: {{ default "ImplementationSpecific" .pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" $) "servicePort" "http" "context" $) | nindent 14 }} + {{- end }} + {{- if .Values.ingress.extraRules }} + {{- include "common.tplvalues.render" (dict "value" .Values.ingress.extraRules "context" $) | nindent 4 }} + {{- end }} + {{- if or (and .Values.ingress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.ingress.annotations )) .Values.ingress.selfSigned (not (empty .Values.ingress.secrets)))) .Values.ingress.extraTls }} + tls: + {{- if and .Values.ingress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.ingress.annotations )) .Values.ingress.selfSigned (not (empty .Values.ingress.secrets))) }} + - hosts: + - {{ .Values.ingress.hostname | quote }} + secretName: {{ printf "%s-tls" .Values.ingress.hostname }} + {{- end }} + {{- if .Values.ingress.extraTls }} + {{- include "common.tplvalues.render" (dict "value" .Values.ingress.extraTls "context" $) | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/nginx/templates/pdb.yaml b/backing-services/nginx/templates/pdb.yaml new file mode 100644 index 0000000..a02d402 --- /dev/null +++ b/backing-services/nginx/templates/pdb.yaml @@ -0,0 +1,26 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.pdb.minAvailable }} + minAvailable: {{ .Values.pdb.minAvailable }} + {{- end }} + {{- if .Values.pdb.maxUnavailable }} + maxUnavailable: {{ .Values.pdb.maxUnavailable }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} +{{- end }} diff --git a/backing-services/nginx/templates/prometheusrules.yaml b/backing-services/nginx/templates/prometheusrules.yaml new file mode 100644 index 0000000..fef0d8a --- /dev/null +++ b/backing-services/nginx/templates/prometheusrules.yaml @@ -0,0 +1,25 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ default (include "common.names.namespace" .) .Values.metrics.prometheusRule.namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: nginx + app.kubernetes.io/component: metrics + {{- if .Values.metrics.prometheusRule.additionalLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.prometheusRule.additionalLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + groups: + - name: {{ include "common.names.fullname" . }} + rules: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.prometheusRule.rules "context" $ ) | nindent 6 }} +{{- end }} diff --git a/backing-services/nginx/templates/server-block-configmap.yaml b/backing-services/nginx/templates/server-block-configmap.yaml new file mode 100644 index 0000000..03f385c --- /dev/null +++ b/backing-services/nginx/templates/server-block-configmap.yaml @@ -0,0 +1,19 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.serverBlock (not .Values.existingServerBlockConfigmap) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "common.names.fullname" . }}-server-block + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + server-block.conf: |- + {{- include "common.tplvalues.render" ( dict "value" .Values.serverBlock "context" $ ) | nindent 4 }} +{{- end }} diff --git a/backing-services/nginx/templates/serviceaccount.yaml b/backing-services/nginx/templates/serviceaccount.yaml new file mode 100644 index 0000000..a6c3003 --- /dev/null +++ b/backing-services/nginx/templates/serviceaccount.yaml @@ -0,0 +1,18 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "nginx.serviceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +{{- end -}} diff --git a/backing-services/nginx/templates/servicemonitor.yaml b/backing-services/nginx/templates/servicemonitor.yaml new file mode 100644 index 0000000..7106c8f --- /dev/null +++ b/backing-services/nginx/templates/servicemonitor.yaml @@ -0,0 +1,45 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ default (include "common.names.namespace" .) .Values.metrics.serviceMonitor.namespace | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.serviceMonitor.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + jobLabel: {{ .Values.metrics.serviceMonitor.jobLabel | quote }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + {{- if .Values.metrics.serviceMonitor.selector }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.serviceMonitor.selector "context" $) | nindent 6 }} + {{- end }} + endpoints: + - port: metrics + path: /metrics + {{- if .Values.metrics.serviceMonitor.interval }} + interval: {{ .Values.metrics.serviceMonitor.interval }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.honorLabels }} + honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.relabelings }} + relabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.relabelings "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.metricRelabelings "context" $) | nindent 8 }} + {{- end }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} +{{- end }} diff --git a/backing-services/nginx/templates/svc.yaml b/backing-services/nginx/templates/svc.yaml new file mode 100644 index 0000000..bd20b52 --- /dev/null +++ b/backing-services/nginx/templates/svc.yaml @@ -0,0 +1,67 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + annotations: + {{- if or .Values.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.service.annotations .Values.commonAnnotations ) "context" . ) }} + {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.service.annotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.service.annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + {{- if and .Values.service.clusterIP (eq .Values.service.type "ClusterIP") }} + clusterIP: {{ .Values.service.clusterIP }} + {{- end }} + {{- if .Values.service.sessionAffinity }} + sessionAffinity: {{ .Values.service.sessionAffinity }} + {{- end }} + {{- if .Values.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + {{- if or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{- toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerClass }} + loadBalancerClass: {{ .Values.service.loadBalancerClass }} + {{- end }} + ports: + - name: http + port: {{ .Values.service.ports.http }} + targetPort: {{ .Values.service.targetPort.http }} + {{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.http)) }} + nodePort: {{ .Values.service.nodePorts.http }} + {{- end }} + {{- if .Values.containerPorts.https }} + - name: https + port: {{ .Values.service.ports.https }} + targetPort: {{ .Values.service.targetPort.https }} + {{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.https)) }} + nodePort: {{ .Values.service.nodePorts.https }} + {{- end }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + port: {{ .Values.metrics.service.port }} + targetPort: metrics + {{- end }} + {{- if .Values.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} diff --git a/backing-services/nginx/templates/tls-secrets.yaml b/backing-services/nginx/templates/tls-secrets.yaml new file mode 100644 index 0000000..5160bfe --- /dev/null +++ b/backing-services/nginx/templates/tls-secrets.yaml @@ -0,0 +1,83 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.ingress.enabled }} +{{- if .Values.ingress.secrets }} +{{- range .Values.ingress.secrets }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .name }} + namespace: {{ include "common.names.namespace" $ | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $.Values.commonLabels "context" $ ) | nindent 4 }} + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ .certificate | b64enc }} + tls.key: {{ .key | b64enc }} +--- +{{- end }} +{{- else if and .Values.ingress.tls .Values.ingress.selfSigned }} +{{- $secretName := printf "%s-tls" .Values.ingress.hostname }} +{{- $ca := genCA "nginx-ca" 365 }} +{{- $cert := genSignedCert .Values.ingress.hostname nil (list .Values.ingress.hostname) 365 $ca }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.crt" "defaultValue" $cert.Cert "context" $) }} + tls.key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.key" "defaultValue" $cert.Key "context" $) }} + ca.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }} +--- +{{- end }} +{{- end }} +{{- if .Values.healthIngress.enabled }} +{{- if .Values.healthIngress.secrets }} +{{- range .Values.healthIngress.secrets }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .name }} + namespace: {{ include "common.names.namespace" $ | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $.Values.commonLabels "context" $ ) | nindent 4 }} + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ .certificate | b64enc }} + tls.key: {{ .key | b64enc }} +--- +{{- end }} +{{- else if and .Values.healthIngress.tls .Values.healthIngress.selfSigned }} +{{- $secretName := printf "%s-tls" .Values.healthIngress.hostname }} +{{- $ca := genCA "nginx-health-ca" 365 }} +{{- $cert := genSignedCert .Values.healthIngress.hostname nil (list .Values.healthIngress.hostname) 365 $ca }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.crt" "defaultValue" $cert.Cert "context" $) }} + tls.key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.key" "defaultValue" $cert.Key "context" $) }} + ca.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }} +--- +{{- end }} +{{- end }} diff --git a/backing-services/nginx/values.schema.json b/backing-services/nginx/values.schema.json new file mode 100644 index 0000000..4b04738 --- /dev/null +++ b/backing-services/nginx/values.schema.json @@ -0,0 +1,119 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "ingress": { + "type": "object", + "form": true, + "title": "Ingress details", + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Use a custom hostname", + "description": "Enable the ingress resource that allows you to access the NGINX installation." + }, + "hostname": { + "type": "string", + "form": true, + "title": "Hostname", + "hidden": { + "value": false, + "path": "ingress/enabled" + } + } + } + }, + "service": { + "type": "object", + "form": true, + "title": "Service Configuration", + "properties": { + "type": { + "type": "string", + "form": true, + "title": "Service Type", + "description": "Allowed values: \"ClusterIP\", \"NodePort\" and \"LoadBalancer\"" + } + } + }, + "replicaCount": { + "type": "integer", + "form": true, + "title": "Number of replicas", + "description": "Number of replicas to deploy" + }, + "serverBlock": { + "type": "string", + "form": true, + "title": "Custom server block", + "description": "Custom server block to be added to NGINX configuration" + }, + "containerSecurityContext": { + "type": "object", + "form": true, + "title": "NGINX containers' Security Context", + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable Security Context", + "description": "Whether to enable NGINX containers' Security Context" + }, + "runAsUser": { + "type": "integer", + "form": true, + "title": "ID of the user", + "description": "The UID of the user NGINX containers will run as" + } + } + }, + "podSecurityContext": { + "type": "object", + "form": true, + "title": "NGINX pods' Security Context", + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable Security Context", + "description": "Whether to enable NGINX pods' Security Context" + }, + "fsGroup": { + "type": "integer", + "form": true, + "title": "ID of the group", + "description": "The GID of the group NGINX pods will run as" + } + } + }, + "metrics": { + "type": "object", + "form": true, + "title": "Prometheus metrics details", + "properties": { + "enabled": { + "type": "boolean", + "title": "Create Prometheus metrics exporter", + "description": "Create a side-car container to expose Prometheus metrics", + "form": true + }, + "serviceMonitor": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Create Prometheus Operator ServiceMonitor", + "description": "Create a ServiceMonitor to track metrics using Prometheus Operator", + "form": true, + "hidden": { + "value": false, + "path": "metrics/enabled" + } + } + } + } + } + } + } +} diff --git a/backing-services/nginx/values.yaml b/backing-services/nginx/values.yaml new file mode 100644 index 0000000..dbed670 --- /dev/null +++ b/backing-services/nginx/values.yaml @@ -0,0 +1,941 @@ +# Copyright VMware, Inc. +# SPDX-License-Identifier: APACHE-2.0 + +## @section Global parameters +## 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, imagePullSecrets and storageClass + +## @param global.imageRegistry Global Docker image registry +## @param global.imagePullSecrets Global Docker registry secret names as an array +## +global: + imageRegistry: "" + ## E.g. + ## imagePullSecrets: + ## - myRegistryKeySecretName + ## + imagePullSecrets: [] + +## @section Common parameters + +## @param nameOverride String to partially override nginx.fullname template (will maintain the release name) +## +nameOverride: "" +## @param fullnameOverride String to fully override nginx.fullname template +## +fullnameOverride: "" +## @param namespaceOverride String to fully override common.names.namespace +## +namespaceOverride: "" +## @param kubeVersion Force target Kubernetes version (using Helm capabilities if not set) +## +kubeVersion: "" +## @param clusterDomain Kubernetes Cluster Domain +## +clusterDomain: cluster.local +## @param extraDeploy Extra objects to deploy (value evaluated as a template) +## +extraDeploy: [] +## @param commonLabels Add labels to all the deployed resources +## +commonLabels: {} +## @param commonAnnotations Add annotations to all the deployed resources +## +commonAnnotations: {} + +## Enable diagnostic mode in the deployment(s)/statefulset(s) +## +diagnosticMode: + ## @param diagnosticMode.enabled Enable diagnostic mode (all probes will be disabled and the command will be overridden) + ## + enabled: false + ## @param diagnosticMode.command Command to override all containers in the the deployment(s)/statefulset(s) + ## + command: + - sleep + ## @param diagnosticMode.args Args to override all containers in the the deployment(s)/statefulset(s) + ## + args: + - infinity + +## @section NGINX parameters + +## Bitnami NGINX image version +## ref: https://hub.docker.com/r/bitnami/nginx/tags/ +## @param image.registry [default: REGISTRY_NAME] NGINX image registry +## @param image.repository [default: REPOSITORY_NAME/nginx] NGINX image repository +## @skip image.tag NGINX image tag (immutable tags are recommended) +## @param image.digest NGINX image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag +## @param image.pullPolicy NGINX image pull policy +## @param image.pullSecrets Specify docker-registry secret names as an array +## @param image.debug Set to true if you would like to see extra information on logs +## +image: + registry: docker.io + repository: bitnami/nginx + tag: 1.25.3-debian-11-r3 + digest: "" + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://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/ + ## E.g.: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Set to true if you would like to see extra information on logs + ## + debug: false +## @param hostAliases Deployment pod host aliases +## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ +## +hostAliases: [] +## Command and args for running the container (set to default if not set). Use array form +## @param command Override default container command (useful when using custom images) +## @param args Override default container args (useful when using custom images) +## +command: [] +args: [] +## @param extraEnvVars Extra environment variables to be set on NGINX containers +## E.g: +## extraEnvVars: +## - name: FOO +## value: BAR +## +extraEnvVars: [] +## @param extraEnvVarsCM ConfigMap with extra environment variables +## +extraEnvVarsCM: "" +## @param extraEnvVarsSecret Secret with extra environment variables +## +extraEnvVarsSecret: "" + +## @section NGINX deployment parameters + +## @param replicaCount Number of NGINX replicas to deploy +## +replicaCount: 1 +## @param revisionHistoryLimit The number of old history to retain to allow rollback +## +revisionHistoryLimit: 10 +## @param updateStrategy.type NGINX deployment strategy type +## @param updateStrategy.rollingUpdate NGINX deployment rolling update configuration parameters +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy +## +updateStrategy: + type: RollingUpdate + rollingUpdate: {} +## @param podLabels Additional labels for NGINX pods +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +## +podLabels: {} +## @param podAnnotations Annotations for NGINX pods +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +## +podAnnotations: {} +## @param podAffinityPreset Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## +podAffinityPreset: "" +## @param podAntiAffinityPreset Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` +## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## +podAntiAffinityPreset: soft +## Node affinity preset +## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity +## +nodeAffinityPreset: + ## @param nodeAffinityPreset.type Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param nodeAffinityPreset.key Node label key to match Ignored if `affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param nodeAffinityPreset.values Node label values to match. Ignored if `affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] +## @param affinity Affinity for pod assignment +## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +## Note: podAffinityPreset, podAntiAffinityPreset, and nodeAffinityPreset will be ignored when it's set +## +affinity: {} +## @param hostNetwork Specify if host network should be enabled for NGINX pod +## +hostNetwork: false +## @param hostIPC Specify if host IPC should be enabled for NGINX pod +## +hostIPC: false +## @param nodeSelector Node labels for pod assignment. Evaluated as a template. +## Ref: https://kubernetes.io/docs/user-guide/node-selection/ +## +nodeSelector: {} +## @param tolerations Tolerations for pod assignment. Evaluated as a template. +## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +## +tolerations: [] +## @param priorityClassName NGINX pods' priorityClassName +## +priorityClassName: "" +## @param schedulerName Name of the k8s scheduler (other than default) +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +schedulerName: "" +## @param terminationGracePeriodSeconds In seconds, time the given to the NGINX pod needs to terminate gracefully +## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods +## +terminationGracePeriodSeconds: "" +## @param topologySpreadConstraints Topology Spread Constraints for pod assignment +## https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ +## The value is evaluated as a template +## +topologySpreadConstraints: [] +## NGINX pods' Security Context. +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod +## @param podSecurityContext.enabled Enabled NGINX pods' Security Context +## @param podSecurityContext.fsGroup Set NGINX pod's Security Context fsGroup +## @param podSecurityContext.sysctls sysctl settings of the NGINX pods +## +podSecurityContext: + enabled: true + fsGroup: 1001 + ## sysctl settings + ## Example: + ## sysctls: + ## - name: net.core.somaxconn + ## value: "10000" + ## + sysctls: [] +## NGINX containers' Security Context. +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container +## @param containerSecurityContext.enabled Enabled containers' Security Context +## @param containerSecurityContext.runAsUser Set containers' Security Context runAsUser +## @param containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot +## @param containerSecurityContext.privileged Set container's Security Context privileged +## @param containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem +## @param containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation +## @param containerSecurityContext.capabilities.drop List of capabilities to be dropped +## @param containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile +## +containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: false + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" +## Configures the ports NGINX listens on +## @param containerPorts.http Sets http port inside NGINX container +## @param containerPorts.https Sets https port inside NGINX container +## +containerPorts: + http: 8080 + https: "" +## @param extraContainerPorts Array of additional container ports for the Nginx container +## e.g: +## extraContainerPorts: +## - name: grpc +## containerPort: 4317 +## +extraContainerPorts: [] +## NGINX containers' resource requests and limits +## ref: https://kubernetes.io/docs/user-guide/compute-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:'. +## @param resources.limits The resources limits for the NGINX container +## @param resources.requests The requested resources for the NGINX container +## +resources: + ## Example: + ## limits: + ## cpu: 100m + ## memory: 128Mi + limits: {} + ## Examples: + ## requests: + ## cpu: 100m + ## memory: 128Mi + requests: {} +## NGINX containers' lifecycleHooks +## ref: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/ +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/attach-handler-lifecycle-event/ +## If you do want to specify lifecycleHooks, uncomment the following +## lines, adjust them as necessary, and remove the curly braces on 'lifecycle:{}'. +## @param lifecycleHooks Optional lifecycleHooks for the NGINX container +lifecycleHooks: {} + ## Example: + ## postStart: + ## exec: + ## command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"] + ## Example: + ## preStop: + ## exec: + ## command: ["/bin/sleep", "20"] + ## command: ["/bin/sh","-c","nginx -s quit; while killall -0 nginx; do sleep 1; done"] + +## NGINX containers' startup probe. +## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes +## @param startupProbe.enabled Enable startupProbe +## @param startupProbe.initialDelaySeconds Initial delay seconds for startupProbe +## @param startupProbe.periodSeconds Period seconds for startupProbe +## @param startupProbe.timeoutSeconds Timeout seconds for startupProbe +## @param startupProbe.failureThreshold Failure threshold for startupProbe +## @param startupProbe.successThreshold Success threshold for startupProbe +## +startupProbe: + enabled: false + initialDelaySeconds: 30 + timeoutSeconds: 5 + periodSeconds: 10 + failureThreshold: 6 + successThreshold: 1 +## NGINX containers' liveness probe. +## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes +## @param livenessProbe.enabled Enable livenessProbe +## @param livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe +## @param livenessProbe.periodSeconds Period seconds for livenessProbe +## @param livenessProbe.timeoutSeconds Timeout seconds for livenessProbe +## @param livenessProbe.failureThreshold Failure threshold for livenessProbe +## @param livenessProbe.successThreshold Success threshold for livenessProbe +## +livenessProbe: + enabled: true + initialDelaySeconds: 30 + timeoutSeconds: 5 + periodSeconds: 10 + failureThreshold: 6 + successThreshold: 1 +## NGINX containers' readiness probe. +## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes +## @param readinessProbe.enabled Enable readinessProbe +## @param readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe +## @param readinessProbe.periodSeconds Period seconds for readinessProbe +## @param readinessProbe.timeoutSeconds Timeout seconds for readinessProbe +## @param readinessProbe.failureThreshold Failure threshold for readinessProbe +## @param readinessProbe.successThreshold Success threshold for readinessProbe +## +readinessProbe: + enabled: true + initialDelaySeconds: 5 + timeoutSeconds: 3 + periodSeconds: 5 + failureThreshold: 3 + successThreshold: 1 +## @param customStartupProbe Custom liveness probe for the Web component +## +customStartupProbe: {} +## @param customLivenessProbe Override default liveness probe +## +customLivenessProbe: {} +## @param customReadinessProbe Override default readiness probe +## +customReadinessProbe: {} +## Autoscaling parameters +## @param autoscaling.enabled Enable autoscaling for NGINX deployment +## @param autoscaling.minReplicas Minimum number of replicas to scale back +## @param autoscaling.maxReplicas Maximum number of replicas to scale out +## @param autoscaling.targetCPU Target CPU utilization percentage +## @param autoscaling.targetMemory Target Memory utilization percentage +## +autoscaling: + enabled: false + minReplicas: "" + maxReplicas: "" + targetCPU: "" + targetMemory: "" +## @param extraVolumes Array to add extra volumes +## +extraVolumes: [] +## @param extraVolumeMounts Array to add extra mount +## +extraVolumeMounts: [] +## Pods Service Account +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ +## +serviceAccount: + ## @param serviceAccount.create Enable creation of ServiceAccount for nginx pod + ## + create: false + ## @param serviceAccount.name The name of the ServiceAccount to use. + ## If not set and create is true, a name is generated using the `common.names.fullname` template + name: "" + ## @param serviceAccount.annotations Annotations for service account. Evaluated as a template. + ## Only used if `create` is `true`. + ## + annotations: {} + ## @param serviceAccount.automountServiceAccountToken Auto-mount the service account token in the pod + ## + automountServiceAccountToken: false +## @param sidecars Sidecar parameters +## e.g: +## sidecars: +## - name: your-image-name +## image: your-image +## imagePullPolicy: Always +## ports: +## - name: portname +## containerPort: 1234 +## +sidecars: [] + +## @param sidecarSingleProcessNamespace Enable sharing the process namespace with sidecars +## This will switch pod.spec.shareProcessNamespace parameter +## +sidecarSingleProcessNamespace: false + +## @param initContainers Extra init containers +## +initContainers: [] +## Pod Disruption Budget configuration +## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ +## +pdb: + ## @param pdb.create Created a PodDisruptionBudget + ## + create: false + ## @param pdb.minAvailable Min number of pods that must still be available after the eviction. + ## You can specify an integer or a percentage by setting the value to a string representation of a percentage (eg. "50%"). It will be disabled if set to 0 + ## + minAvailable: 1 + ## @param pdb.maxUnavailable Max number of pods that can be unavailable after the eviction. + ## You can specify an integer or a percentage by setting the value to a string representation of a percentage (eg. "50%"). It will be disabled if set to 0 + ## + maxUnavailable: 0 + +## @section Custom NGINX application parameters + +## Get the server static content from a git repository +## NOTE: This will override staticSiteConfigmap and staticSitePVC +## +cloneStaticSiteFromGit: + ## @param cloneStaticSiteFromGit.enabled Get the server static content from a Git repository + ## + enabled: false + ## Bitnami Git image version + ## ref: https://hub.docker.com/r/bitnami/git/tags/ + ## @param cloneStaticSiteFromGit.image.registry [default: REGISTRY_NAME] Git image registry + ## @param cloneStaticSiteFromGit.image.repository [default: REPOSITORY_NAME/git] Git image repository + ## @skip cloneStaticSiteFromGit.image.tag Git image tag (immutable tags are recommended) + ## @param cloneStaticSiteFromGit.image.digest Git image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param cloneStaticSiteFromGit.image.pullPolicy Git image pull policy + ## @param cloneStaticSiteFromGit.image.pullSecrets Specify docker-registry secret names as an array + ## + image: + registry: docker.io + repository: bitnami/git + tag: 2.43.0-debian-11-r5 + digest: "" + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## @param cloneStaticSiteFromGit.repository Git Repository to clone static content from + ## + repository: "" + ## @param cloneStaticSiteFromGit.branch Git branch to checkout + ## + branch: "" + ## @param cloneStaticSiteFromGit.interval Interval for sidecar container pull from the Git repository + ## + interval: 60 + ## Additional configuration for git-clone-repository initContainer + ## + gitClone: + ## @param cloneStaticSiteFromGit.gitClone.command Override default container command for git-clone-repository + ## + command: [] + ## @param cloneStaticSiteFromGit.gitClone.args Override default container args for git-clone-repository + ## + args: [] + ## Additional configuration for the git-repo-syncer container + ## + gitSync: + ## @param cloneStaticSiteFromGit.gitSync.command Override default container command for git-repo-syncer + ## + command: [] + ## @param cloneStaticSiteFromGit.gitSync.args Override default container args for git-repo-syncer + ## + args: [] + ## git-repo-syncer resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param cloneStaticSiteFromGit.gitSync.resources.limits The resources limits for the git-repo-syncer container + ## @param cloneStaticSiteFromGit.gitSync.resources.requests The requested resources for the git-repo-syncer container + ## + resources: + limits: {} + requests: {} + ## @param cloneStaticSiteFromGit.extraEnvVars Additional environment variables to set for the in the containers that clone static site from git + ## E.g: + ## extraEnvVars: + ## - name: FOO + ## value: BAR + ## + extraEnvVars: [] + ## @param cloneStaticSiteFromGit.extraEnvVarsSecret Secret with extra environment variables + ## + extraEnvVarsSecret: "" + ## @param cloneStaticSiteFromGit.extraVolumeMounts Add extra volume mounts for the Git containers + ## Useful to mount keys to connect through ssh. (normally used with extraVolumes) + ## E.g: + ## extraVolumeMounts: + ## - name: ssh-dir + ## mountPath: /root/.ssh/ + ## + extraVolumeMounts: [] +## @param serverBlock Custom server block to be added to NGINX configuration +## PHP-FPM example server block: +## serverBlock: |- +## server { +## listen 0.0.0.0:8080; +## root /app; +## location / { +## index index.html index.php; +## } +## location ~ \.php$ { +## fastcgi_pass phpfpm-server:9000; +## fastcgi_index index.php; +## include fastcgi.conf; +## } +## } +## +serverBlock: "" +## @param existingServerBlockConfigmap ConfigMap with custom server block to be added to NGINX configuration +## NOTE: This will override serverBlock +## +existingServerBlockConfigmap: "" +## @param staticSiteConfigmap Name of existing ConfigMap with the server static site content +## +staticSiteConfigmap: "" +## @param staticSitePVC Name of existing PVC with the server static site content +## NOTE: This will override staticSiteConfigmap +## +staticSitePVC: "" + +## @section Traffic Exposure parameters + +## NGINX Service properties +## +service: + ## @param service.type Service type + ## + type: LoadBalancer + ## @param service.ports.http Service HTTP port + ## @param service.ports.https Service HTTPS port + ## + ports: + http: 80 + https: 443 + ## + ## @param service.nodePorts [object] Specify the nodePort(s) value(s) for the LoadBalancer and NodePort service types. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + nodePorts: + http: "" + https: "" + ## @param service.targetPort [object] Target port reference value for the Loadbalancer service types can be specified explicitly. + ## Listeners for the Loadbalancer can be custom mapped to the http or https service. + ## Example: Mapping the https listener to targetPort http [http: https] + ## + targetPort: + http: http + https: https + ## @param service.clusterIP NGINX service Cluster IP + ## e.g.: + ## clusterIP: None + ## + clusterIP: "" + ## @param service.loadBalancerIP LoadBalancer service IP address + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param service.loadBalancerSourceRanges NGINX service Load Balancer sources + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param service.loadBalancerClass service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerClass: "" + ## @param service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## @param service.annotations Service annotations + ## This can be used to set the LoadBalancer service type to internal only. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + annotations: {} + ## @param service.externalTrafficPolicy Enable client source IP preservation + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster +## Configure the ingress resource that allows you to access the +## Nginx installation. Set up the URL +## ref: https://kubernetes.io/docs/user-guide/ingress/ +## +ingress: + ## @param ingress.enabled Set to true to enable ingress record generation + ## + enabled: false + ## @param ingress.selfSigned Create a TLS secret for this ingress record using self-signed certificates generated by Helm + ## + selfSigned: false + ## @param ingress.pathType Ingress path type + ## + pathType: ImplementationSpecific + ## @param ingress.apiVersion Force Ingress API version (automatically detected if not set) + ## + apiVersion: "" + ## @param ingress.hostname Default host for the ingress resource + ## + hostname: nginx.local + ## @param ingress.path The Path to Nginx. You may need to set this to '/*' in order to use this with ALB ingress controllers. + ## + path: / + ## @param ingress.annotations Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. + ## For a full list of possible ingress annotations, please see + ## ref: https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md + ## Use this parameter to set the required annotations for cert-manager, see + ## ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations + ## + ## e.g: + ## annotations: + ## kubernetes.io/ingress.class: nginx + ## cert-manager.io/cluster-issuer: cluster-issuer-name + ## + annotations: {} + ## @param ingress.ingressClassName Set the ingerssClassName on the ingress record for k8s 1.18+ + ## This is supported in Kubernetes 1.18+ and required if you have more than one IngressClass marked as the default for your cluster . + ## ref: https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/ + ## + ingressClassName: "" + ## @param ingress.tls Create TLS Secret + ## TLS certificates will be retrieved from a TLS secret with name: {{- printf "%s-tls" .Values.ingress.hostname }} + ## You can use the ingress.secrets parameter to create this TLS secret or relay on cert-manager to create it + ## + tls: false + ## @param ingress.extraHosts The list of additional hostnames to be covered with this ingress record. + ## Most likely the hostname above will be enough, but in the event more hosts are needed, this is an array + ## extraHosts: + ## - name: nginx.local + ## path: / + ## + extraHosts: [] + ## @param ingress.extraPaths Any additional arbitrary paths that may need to be added to the ingress under the main host. + ## For example: The ALB ingress controller requires a special rule for handling SSL redirection. + ## extraPaths: + ## - path: /* + ## backend: + ## serviceName: ssl-redirect + ## servicePort: use-annotation + ## + extraPaths: [] + ## @param ingress.extraTls The tls configuration for additional hostnames to be covered with this ingress record. + ## see: https://kubernetes.io/docs/concepts/services-networking/ingress/#tls + ## extraTls: + ## - hosts: + ## - nginx.local + ## secretName: nginx.local-tls + ## + extraTls: [] + ## @param ingress.secrets If you're providing your own certificates, please use this to add the certificates as secrets + ## key and certificate should start with -----BEGIN CERTIFICATE----- or + ## -----BEGIN RSA PRIVATE KEY----- + ## + ## name should line up with a tlsSecret set further up + ## If you're using cert-manager, this is unneeded, as it will create the secret for you if it is not set + ## + ## It is also possible to create and manage the certificates outside of this helm chart + ## Please see README.md for more information + ## e.g: + ## - name: nginx.local-tls + ## key: + ## certificate: + ## + secrets: [] + ## @param ingress.extraRules The list of additional rules to be added to this ingress record. Evaluated as a template + ## Useful when looking for additional customization, such as using different backend + ## + extraRules: [] +## Health Ingress parameters +## +healthIngress: + ## @param healthIngress.enabled Set to true to enable health ingress record generation + ## + enabled: false + ## @param healthIngress.selfSigned Create a TLS secret for this ingress record using self-signed certificates generated by Helm + ## + selfSigned: false + ## @param healthIngress.pathType Ingress path type + ## + pathType: ImplementationSpecific + ## @param healthIngress.hostname When the health ingress is enabled, a host pointing to this will be created + ## + hostname: example.local + ## @param healthIngress.path Default path for the ingress record + ## NOTE: You may need to set this to '/*' in order to use this with ALB ingress controllers + ## + path: / + ## @param healthIngress.annotations Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. + ## For a full list of possible ingress annotations, please see + ## ref: https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md + ## Use this parameter to set the required annotations for cert-manager, see + ## ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations + ## + ## e.g: + ## annotations: + ## kubernetes.io/ingress.class: nginx + ## cert-manager.io/cluster-issuer: cluster-issuer-name + ## + annotations: {} + ## @param healthIngress.tls Enable TLS configuration for the hostname defined at `healthIngress.hostname` parameter + ## TLS certificates will be retrieved from a TLS secret with name: {{- printf "%s-tls" .Values.healthIngress.hostname }} + ## You can use the healthIngress.secrets parameter to create this TLS secret, relay on cert-manager to create it, or + ## let the chart create self-signed certificates for you + ## + tls: false + ## @param healthIngress.extraHosts An array with additional hostname(s) to be covered with the ingress record + ## e.g: + ## extraHosts: + ## - name: example.local + ## path: / + ## + extraHosts: [] + ## @param healthIngress.extraPaths An array with additional arbitrary paths that may need to be added to the ingress under the main host + ## e.g: + ## extraPaths: + ## - path: /* + ## backend: + ## serviceName: ssl-redirect + ## servicePort: use-annotation + ## + extraPaths: [] + ## @param healthIngress.extraTls TLS configuration for additional hostnames to be covered + ## see: https://kubernetes.io/docs/concepts/services-networking/ingress/#tls + ## E.g. + ## extraTls: + ## - hosts: + ## - example.local + ## secretName: example.local-tls + ## + extraTls: [] + ## @param healthIngress.secrets TLS Secret configuration + ## If you're providing your own certificates, please use this to add the certificates as secrets + ## key and certificate should start with -----BEGIN CERTIFICATE----- or -----BEGIN RSA PRIVATE KEY----- + ## name should line up with a secretName set further up + ## If it is not set and you're using cert-manager, this is unneeded, as it will create the secret for you + ## If it is not set and you're NOT using cert-manager either, self-signed certificates will be created + ## It is also possible to create and manage the certificates outside of this helm chart + ## Please see README.md for more information + ## + ## E.g. + ## secrets: + ## - name: example.local-tls + ## key: + ## certificate: + ## + secrets: [] + ## @param healthIngress.ingressClassName IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+) + ## This is supported in Kubernetes 1.18+ and required if you have more than one IngressClass marked as the default for your cluster . + ## ref: https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/ + ## + ingressClassName: "" + ## @param healthIngress.extraRules The list of additional rules to be added to this ingress record. Evaluated as a template + ## Useful when looking for additional customization, such as using different backend + ## + extraRules: [] + +## @section Metrics parameters + +## Prometheus Exporter / Metrics +## +metrics: + ## @param metrics.enabled Start a Prometheus exporter sidecar container + ## + enabled: false + ## Bitnami NGINX Prometheus Exporter image + ## ref: https://hub.docker.com/r/bitnami/nginx-exporter/tags/ + ## @param metrics.image.registry [default: REGISTRY_NAME] NGINX Prometheus exporter image registry + ## @param metrics.image.repository [default: REPOSITORY_NAME/nginx-exporter] NGINX Prometheus exporter image repository + ## @skip metrics.image.tag NGINX Prometheus exporter image tag (immutable tags are recommended) + ## @param metrics.image.digest NGINX Prometheus exporter image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param metrics.image.pullPolicy NGINX Prometheus exporter image pull policy + ## @param metrics.image.pullSecrets Specify docker-registry secret names as an array + ## + image: + registry: docker.io + repository: bitnami/nginx-exporter + tag: 1.0.0-debian-11-r0 + digest: "" + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## @param metrics.port NGINX Container Status Port scraped by Prometheus Exporter + ## Defaults to specified http port + ## + port: "" + ## @param metrics.extraArgs Extra arguments for Prometheus exporter + ## e.g: + ## extraArgs: + ## - --nginx.timeout + ## - 5s + ## + extraArgs: [] + ## @param metrics.containerPorts.metrics Prometheus exporter container port + ## + containerPorts: + metrics: 9113 + ## @param metrics.podAnnotations Additional annotations for NGINX Prometheus exporter pod(s) + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + ## @param metrics.securityContext.enabled Enabled NGINX Exporter containers' Security Context + ## @param metrics.securityContext.runAsUser Set NGINX Exporter container's Security Context runAsUser + ## + securityContext: + enabled: false + runAsUser: 1001 + ## Prometheus exporter service parameters + ## + service: + ## @param metrics.service.port NGINX Prometheus exporter service port + ## + port: 9113 + ## @param metrics.service.annotations [object] Annotations for the Prometheus exporter service + ## + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "{{ .Values.metrics.service.port }}" + ## NGINX Prometheus exporter resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-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:'. + ## @param metrics.resources.limits The resources limits for the NGINX Prometheus exporter container + ## @param metrics.resources.requests The requested resources for the NGINX Prometheus exporter container + ## + resources: + ## Example: + ## limits: + ## cpu: 100m + ## memory: 128Mi + limits: {} + ## Examples: + ## requests: + ## cpu: 100m + ## memory: 128Mi + requests: {} + ## Prometheus Operator ServiceMonitor configuration + ## + serviceMonitor: + ## @param metrics.serviceMonitor.enabled Creates a Prometheus Operator ServiceMonitor (also requires `metrics.enabled` to be `true`) + ## + enabled: false + ## @param metrics.serviceMonitor.namespace Namespace in which Prometheus is running + ## + namespace: "" + ## @param metrics.serviceMonitor.jobLabel The name of the label on the target service to use as the job name in prometheus. + ## + jobLabel: "" + ## @param metrics.serviceMonitor.interval Interval at which metrics should be scraped. + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint + ## e.g: + ## interval: 10s + ## + interval: "" + ## @param metrics.serviceMonitor.scrapeTimeout Timeout after which the scrape is ended + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint + ## e.g: + ## scrapeTimeout: 10s + ## + scrapeTimeout: "" + ## @param metrics.serviceMonitor.selector Prometheus instance selector labels + ## ref: https://github.com/bitnami/charts/tree/main/bitnami/prometheus-operator#prometheus-configuration + ## + ## selector: + ## prometheus: my-prometheus + ## + selector: {} + ## @param metrics.serviceMonitor.labels Additional labels that can be used so PodMonitor will be discovered by Prometheus + ## + labels: {} + ## @param metrics.serviceMonitor.relabelings RelabelConfigs to apply to samples before scraping + ## + relabelings: [] + ## @param metrics.serviceMonitor.metricRelabelings MetricRelabelConfigs to apply to samples before ingestion + ## + metricRelabelings: [] + ## @param metrics.serviceMonitor.honorLabels honorLabels chooses the metric's labels on collisions with target labels + ## + honorLabels: false + ## Prometheus Operator PrometheusRule configuration + ## + prometheusRule: + ## @param metrics.prometheusRule.enabled if `true`, creates a Prometheus Operator PrometheusRule (also requires `metrics.enabled` to be `true` and `metrics.prometheusRule.rules`) + ## + enabled: false + ## @param metrics.prometheusRule.namespace Namespace for the PrometheusRule Resource (defaults to the Release Namespace) + ## + namespace: "" + ## @param metrics.prometheusRule.additionalLabels Additional labels that can be used so PrometheusRule will be discovered by Prometheus + ## + additionalLabels: {} + ## @param metrics.prometheusRule.rules Prometheus Rule definitions + ## - alert: LowInstance + ## expr: up{service="{{ template "common.names.fullname" . }}"} < 1 + ## for: 1m + ## labels: + ## severity: critical + ## annotations: + ## description: Service {{ template "common.names.fullname" . }} Tomcat is down since 1m. + ## summary: Tomcat instance is down. + ## + rules: [] diff --git a/backing-services/osrm/.helmignore b/backing-services/osrm/.helmignore new file mode 100644 index 0000000..50af031 --- /dev/null +++ b/backing-services/osrm/.helmignore @@ -0,0 +1,22 @@ +# 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 +.vscode/ diff --git a/backing-services/osrm/Chart.yaml b/backing-services/osrm/Chart.yaml new file mode 100644 index 0000000..afbec9f --- /dev/null +++ b/backing-services/osrm/Chart.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +appVersion: 5.22.0 +description: OSRM - Open Source Routing Machine +keywords: +- osrm +kubeVersion: '>= 1.19.0-0' +name: osrm +sources: +- https://github.com/Project-OSRM/osrm-backend +version: 0.6.0 diff --git a/backing-services/osrm/files/gcs-download-prepared.sh.tpl b/backing-services/osrm/files/gcs-download-prepared.sh.tpl new file mode 100644 index 0000000..2ae4e63 --- /dev/null +++ b/backing-services/osrm/files/gcs-download-prepared.sh.tpl @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +set -euo pipefail + +ensure_dependency() { + if ! which "$1" &>/dev/null ; then + echo "$1 not found" + exit 1 + fi +} + +ensure_dependency gsutil +ensure_dependency tar + +version="{{ .Values.map.gcs.version | default "unversioned" }}" +uri="{{ .Values.map.gcs.uri }}" +file="{{ base .Values.map.gcs.uri }}" + +mkdir -p "/data/maps/${version}" +cd "/data/maps/${version}" + +if [ ! -r downloaded.lock ]; then + gcloud auth activate-service-account --key-file="$GOOGLE_APPLICATION_CREDENTIALS" + gsutil -m cp "${uri}" . + tar xzvf "${file}" + rm "${file}" + + # Rename all files so we have predictable argument name in statefulset. + shopt -s nullglob + for f in *.osrm* + do + echo "Rename $f -> map.osrm${f#*.osrm*}" + mv "$f" "map.osrm${f#*.osrm*}" + done + + touch downloaded.lock +fi + +echo "Done!" +exit 0 diff --git a/backing-services/osrm/files/http-download.sh.tpl b/backing-services/osrm/files/http-download.sh.tpl new file mode 100644 index 0000000..aa17f87 --- /dev/null +++ b/backing-services/osrm/files/http-download.sh.tpl @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +set -euo pipefail + +ensure_dependency() { + if ! which "$1" &>/dev/null ; then + echo "$1 not found" + exit 1 + fi +} + +ensure_dependency wget +ensure_dependency md5sum + +version="{{ .Values.map.http.version | default "unversioned" }}" +uri="{{ .Values.map.http.uri }}" +file="{{ base .Values.map.http.uri }}" +checkMD5="{{ if .Values.map.http.checkMD5 }}1{{ end }}" + +mkdir -p "/data/maps/${version}" +cd "/data/maps/${version}" + +if [ ! -r downloaded.lock ]; then + wget "${uri}" + + if [ -n "${checkMD5}" ]; then + wget "${uri}.md5" + md5sum -c "${file}.md5" + rm "${file}.md5" + fi + + # Rename the file so we have predictable argument name in statefulset. + echo "Rename ${file} -> map.osm.pbf" + mv "${file}" "map.osm.pbf" + + touch downloaded.lock +fi + +echo "Done!" +exit 0 diff --git a/backing-services/osrm/files/http-extract.sh.tpl b/backing-services/osrm/files/http-extract.sh.tpl new file mode 100644 index 0000000..de00bb9 --- /dev/null +++ b/backing-services/osrm/files/http-extract.sh.tpl @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +set -euo pipefail + +ensure_dependency() { + if ! which "$1" &>/dev/null ; then + echo "$1 not found" + exit 1 + fi +} + +ensure_dependency osrm-extract +ensure_dependency osrm-partition +ensure_dependency osrm-customize + +version="{{ .Values.map.http.version | default "unversioned" }}" +file_pbf="map.osm.pbf" +file_osrm="map.osrm" +profile="{{ .Values.map.profile | default "car" }}" + +cd "/data/maps/${version}" + +if [ ! -r extracted.lock ]; then + osrm-extract -p /opt/${profile}.lua "${file_pbf}" + osrm-partition "${file_osrm}" + osrm-customize "${file_osrm}" + + touch extracted.lock +fi + +echo "Done!" +exit 0 diff --git a/backing-services/osrm/schoolbus-demo.values.yaml b/backing-services/osrm/schoolbus-demo.values.yaml new file mode 100644 index 0000000..4470ca5 --- /dev/null +++ b/backing-services/osrm/schoolbus-demo.values.yaml @@ -0,0 +1,32 @@ +image: + repository: 172.16.16.2:30516/osrm/osrm-backend + tag: v5.22.0 + pullPolicy: IfNotPresent + +map: + enabled: true + + # Profile to be used for routing (one of "car", "bicycle", "foot") + profile: car + source: http + http: + version: "" + uri: https://blog.tavanasys.app/iran-latest.osm.pbf + +resources: + requests: + cpu: 1000m + memory: 1200Mi + limits: + cpu: 1000m + memory: 1200Mi + +ingress: + enabled: false + annotations: + kubernetes.io/ingress.class: traefik + hosts: + - host: osm.tavanasys.app + +nodeSelector: + node.name: worker-1 diff --git a/backing-services/osrm/templates/NOTES.txt b/backing-services/osrm/templates/NOTES.txt new file mode 100644 index 0000000..9815760 --- /dev/null +++ b/backing-services/osrm/templates/NOTES.txt @@ -0,0 +1,21 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ . }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "osrm.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "osrm.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "osrm.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "osrm.name" . }},app.kubernetes.io/instance={{ .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:80 +{{- end }} diff --git a/backing-services/osrm/templates/_helpers.tpl b/backing-services/osrm/templates/_helpers.tpl new file mode 100644 index 0000000..53ec246 --- /dev/null +++ b/backing-services/osrm/templates/_helpers.tpl @@ -0,0 +1,45 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "osrm.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "osrm.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "osrm.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "osrm.labels" -}} +app.kubernetes.io/name: {{ include "osrm.name" . }} +helm.sh/chart: {{ include "osrm.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} diff --git a/backing-services/osrm/templates/configmap-files.yaml b/backing-services/osrm/templates/configmap-files.yaml new file mode 100644 index 0000000..c358b1d --- /dev/null +++ b/backing-services/osrm/templates/configmap-files.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "osrm.fullname" . }}-files + labels: {{ include "osrm.labels" . | nindent 4 }} +data: + {{- range $key, $filepath := .Values.configTemplatedFiles }} + {{ $key }}: |- {{ ( tpl ($.Files.Get $filepath) $ ) | nindent 4 }} + {{- end }} + + {{- if and .Values.map.enabled ( eq "http" .Values.map.source ) }} + {{- range $key, $filepath := .Values.map.http.configTemplatedFiles }} + {{ $key }}: |- {{ ( tpl ($.Files.Get $filepath) $ ) | nindent 4 }} + {{- end }} + {{- end }} + + {{- if and .Values.map.enabled ( eq "gcs" .Values.map.source ) }} + {{- range $key, $filepath := .Values.map.gcs.configTemplatedFiles }} + {{ $key }}: |- {{ ( tpl ($.Files.Get $filepath) $ ) | nindent 4 }} + {{- end }} + {{- end }} diff --git a/backing-services/osrm/templates/ingress.yaml b/backing-services/osrm/templates/ingress.yaml new file mode 100644 index 0000000..16a2336 --- /dev/null +++ b/backing-services/osrm/templates/ingress.yaml @@ -0,0 +1,43 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "osrm.fullname" . -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "osrm.labels" . | nindent 4 }} + {{- with .Values.ingress.extraLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + ingressClassName: {{ .Values.ingress.className }} +{{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} +{{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ . }} + pathType: ImplementationSpecific + backend: + service: + name: {{ $fullName }} + port: + name: http + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/osrm/templates/service-headless.yaml b/backing-services/osrm/templates/service-headless.yaml new file mode 100644 index 0000000..d712301 --- /dev/null +++ b/backing-services/osrm/templates/service-headless.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "osrm.fullname" . }}-headless + labels: +{{ include "osrm.labels" . | indent 4 }} +spec: + type: {{ .Values.service.type }} + clusterIP: None + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + app.kubernetes.io/name: {{ include "osrm.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} diff --git a/backing-services/osrm/templates/service.yaml b/backing-services/osrm/templates/service.yaml new file mode 100644 index 0000000..19e88c5 --- /dev/null +++ b/backing-services/osrm/templates/service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "osrm.fullname" . }} + labels: +{{ include "osrm.labels" . | indent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + app.kubernetes.io/name: {{ include "osrm.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} diff --git a/backing-services/osrm/templates/statefulset.yaml b/backing-services/osrm/templates/statefulset.yaml new file mode 100644 index 0000000..5025ebe --- /dev/null +++ b/backing-services/osrm/templates/statefulset.yaml @@ -0,0 +1,115 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "osrm.fullname" . }} + labels: +{{ include "osrm.labels" . | indent 4 }} +spec: + serviceName: {{ include "osrm.fullname" . }}-headless + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "osrm.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "osrm.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + initContainers: + {{- with .Values.initContainersTpl }} + {{- ( tpl . $ ) | nindent 8 }} + {{- end }} + {{- with .Values.initContainers }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if and .Values.map.enabled ( eq "http" .Values.map.source ) }} + {{- ( tpl .Values.map.http.initContainersTpl $ ) | nindent 8 }} + {{- end }} + {{- if and .Values.map.enabled ( eq "gcs" .Values.map.source ) }} + {{- ( tpl .Values.map.gcs.initContainersTpl $ ) | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - osrm-routed + - --algorithm + - mld + {{- if and .Values.map.enabled ( eq "http" .Values.map.source ) }} + - /data/maps/{{ .Values.map.http.version | default "unversioned" }}/map.osrm + {{- end }} + {{- if and .Values.map.enabled ( eq "gcs" .Values.map.source ) }} + - /data/maps/{{ .Values.map.gcs.version | default "unversioned" }}/map.osrm + {{- end }} + {{- if .Values.extraArgs }} + {{- toYaml .Values.extraArgs | nindent 12 }} + {{- end }} + ports: + - name: http + containerPort: 5000 + protocol: TCP + {{- with .Values.livenessProbe }} + livenessProbe: {{ toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.readinessProbe }} + readinessProbe: {{ toYaml . | nindent 12 }} + {{- end }} + resources: {{ toYaml .Values.resources | nindent 12 }} + volumeMounts: + - name: maps + mountPath: /data/maps + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: config-files + configMap: + name: {{ include "osrm.fullname" . }}-files + defaultMode: 0755 + {{- if not .Values.persistence.enabled }} + - name: maps + emptyDir: {} + {{- end }} + {{- with .Values.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.extraVolumesTpl }} + {{- ( tpl . $ ) | nindent 8 }} + {{- end }} + {{- if and .Values.map.enabled ( eq "gcs" .Values.map.source ) }} + {{- ( tpl .Values.map.gcs.extraVolumesTpl $ ) | nindent 8 }} + {{- end }} + {{- if .Values.persistence.enabled }} + volumeClaimTemplates: + - metadata: + name: maps + spec: + accessModes: + {{- toYaml .Values.persistence.accessModes | nindent 10 }} + {{- if .Values.persistence.storageClassName }} + {{- if (eq "-" .Values.persistence.storageClassName) }} + storageClassName: "" + {{- else }} + storageClassName: {{ .Values.persistence.storageClassName }} + {{- end }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- end }} diff --git a/backing-services/osrm/templates/tests/test-connection.yaml b/backing-services/osrm/templates/tests/test-connection.yaml new file mode 100644 index 0000000..0e036d7 --- /dev/null +++ b/backing-services/osrm/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "osrm.fullname" . }}-test-connection" + labels: +{{ include "osrm.labels" . | indent 4 }} + annotations: + "helm.sh/hook": test-success +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ include "osrm.fullname" . }}:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/backing-services/osrm/values.yaml b/backing-services/osrm/values.yaml new file mode 100644 index 0000000..1165d02 --- /dev/null +++ b/backing-services/osrm/values.yaml @@ -0,0 +1,254 @@ +# Default values for osrm. + +# Chart name override. Defaults to chart name, i.e. "osrm". +nameOverride: "" +# App name override. Defaults to name built upon release name and chart name. +fullnameOverride: "" + +# How many replicas of the statefulset to deploy. +replicaCount: 1 + +image: + repository: osrm/osrm-backend + tag: v5.22.0 + pullPolicy: IfNotPresent + +imagePullSecrets: [] + +# Init containers to add to the pod in statefulset. +# This field is plain yaml that is inserted as-is. +initContainers: [] + +# Init containers to add to the pod in statefulset. +# This field is a template string that is passed to tpl func before insertion. +initContainersTpl: "" + +# Extra arguments to pass to the osrm binary. +extraArgs: [] + +# Extra volumes to add to the pod. +# This field is plain yaml that is inserted as-is. +extraVolumes: [] +# # Example: +# - name: something +# configMap: +# name: some-volume + +# Extra volumes to add to the pod. +# This field is a template string that is passed to tpl func before insertion. +extraVolumesTpl: "" +# # Example: +# - name: scripts +# configMap: +# name: {{ include "osrm.fullname" . }}-scripts + +# Files that are stored in configmap and can be accessed from containers/initContainers. +# This field is a map, where keys are configmap key names and values are file paths relative to chart root. +# File contents is passed to tpl func before insertion. +configTemplatedFiles: {} +# # Example: +# download.sh: "files/download.sh.tpl" +# extract.sh: "files/extract.sh.tpl" + +# Kubernetes Service object configuration. +service: + type: ClusterIP + port: 80 + +# Kubernetes Ingress object configuration. +ingress: + enabled: false + extraLabels: {} + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + className: "" + hosts: + - host: chart-example.local + paths: [] + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # requests: + # cpu: 200m + # memory: 256Mi + # limits: + # cpu: 1000m + # memory: 512Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +livenessProbe: null +# httpGet: +# path: /route/v1/driving/13.388860,52.517037;13.385983,52.496891 +# port: http + +readinessProbe: null +# httpGet: +# path: /route/v1/driving/13.388860,52.517037;13.385983,52.496891 +# port: http + +# Persistence allows you to store downloaded maps in the persistent store. +# Enable & configure this if you don't want to download the same maps each +# time you deploy. +persistence: + enabled: false + + # If defined, storageClassName: . + # If set to "-", storageClassName: "", which disables dynamic provisioning. + # If set to null (the default), no storageClassName spec is set, choosing + # 'standard' storage class available with the default provisioner + # (gcd-pd on GKE, hostpath on minikube, etc). + # More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#class-1 + storageClassName: null + + accessModes: + - ReadWriteOnce + size: 1Gi + +# map configuration enables out-of-the-box map downloading from various sources and required preparations +# (extraction, etc.). +# +# If you do not want to use default downloading mechanics of this chart, you can disable this. +map: + # Whether the map downloading feature is enabled. + # If you want to manage maps yourself (e.g. mount pre-existing PV with maps to the pod), + # set this to false. + enabled: true + + # Profile to be used for routing (one of "car", "bicycle", "foot") + profile: car + + # Configures what source provider to use to download map. + # Supported providers: + # - http + # - gcs + source: http + + # http section is used when chart is configured to download maps from an HTTP endpoint. + # + # HTTP mode is designed to download .pbf file from the source, extract it and run other preparation commands. + # Each replica in the stateful set executes these actions on its own volume and map. + # + # HTTP mode supports versioning. It downloads/extracts the map once for each version and creates corresponding + # lock-files "downloaded.lock", "extracted.lock". You can remove file to re-do an action, e.g. remove + # "downloaded.txt" to re-download the map. + # There is no logic to distinguish versions, so no version can be considered "old". If you want to remove old + # versions from the volume, you have to do it manually. + http: + # An arbitrary version for the map at the uri. Any versioning scheme can be used. This field is used only to create + # corresponding directory within the volume and to decide whether to download a new version of the map. + # + # Example: "20200226-1" + version: "" + + # HTTP(S) uri to download map. + # + # Some sources/mirrors you may use: + # - http://download.geofabrik.de + # - https://download.openstreetmap.fr/extracts/ + uri: https://download.openstreetmap.fr/extracts/europe/monaco.osm.pbf + + # Set to "true" when the .md5 file is available for checksum. + checkMD5: false + + # http mode files for config map. + # See top-level 'configTemplatedFiles' for documentation. + configTemplatedFiles: + download.sh: "files/http-download.sh.tpl" + extract.sh: "files/http-extract.sh.tpl" + + # http mode init containers. + # See tol-level 'initContainersTpl' for documentation. + initContainersTpl: |- + - name: map-downloader + image: 172.16.16.2:30516/bash:5 + imagePullPolicy: IfNotPresent + command: + - /scripts/download.sh + volumeMounts: + - name: config-files + mountPath: /scripts + - name: maps + mountPath: /data/maps + - name: map-extractor + image: {{ .Values.image.repository }}:{{ .Values.image.tag }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - /scripts/extract.sh + volumeMounts: + - name: config-files + mountPath: /scripts + - name: maps + mountPath: /data/maps + + # gcs section is used when chart is configured to download maps from Google Cloud Storage bucket. + # + # gcs mode is designed to do download already prepared map files in the form of tgz archive. + # Each replica in the stateful set downloads its own copy of map. + # + # gcs mode supports versioning. It downloads the map once for each version, and creates "ready.lock" file. + # If you want to re-download the map of already downloaded version on the next pod start, remove this file. + # There is no logic to distinguish versions, so no version can be considered "old". If you want to remove old + # versions from the volume, you have to do it manually. + gcs: + # An arbitrary version for the map at the uri. Any versioning scheme can be used. This field is used only to create + # corresponding directory within the volume and to decide whether to download a new version of the map. + # + # Example: "20200226-1" + version: "" + + # Google Cloud Storage URI to download map archive from. + # + # Example: "gs://example-osrm-maps/20200226-1/map.tar.gz" + uri: "" + + # To download from private gcs bucket you need google application credentials. + # This section allows configuring it via an externally created secret. + googleApplicationCredentials: + enabled: true + secretName: osrm-google-application-credentials + secretKey: credentials.json + + # gcs mode files for config map. + # See top-level 'configTemplatedFiles' for documentation. + configTemplatedFiles: + download.sh: "files/gcs-download-prepared.sh.tpl" + + # gcs mode init containers. + # See tol-level 'initContainersTpl' for documentation. + initContainersTpl: |- + - name: map-downloader + image: gcr.io/google.com/cloudsdktool/cloud-sdk:282.0.0-alpine + imagePullPolicy: IfNotPresent + command: + - /scripts/download.sh + {{- if .Values.map.gcs.googleApplicationCredentials.enabled }} + env: + - name: GOOGLE_APPLICATION_CREDENTIALS + value: /var/run/secrets/osrm/google-application-credentials/{{ .Values.map.gcs.googleApplicationCredentials.secretKey }} + {{- end }} + volumeMounts: + - name: config-files + mountPath: /scripts + - name: maps + mountPath: /data/maps + {{- if .Values.map.gcs.googleApplicationCredentials.enabled }} + - name: google-application-credentials + mountPath: /var/run/secrets/osrm/google-application-credentials + readOnly: true + {{- end }} + + # gcs mode extra volumes. + # See tol-level 'extraVolumesTpl' for documentation. + extraVolumesTpl: |- + - name: google-application-credentials + secret: + secretName: {{ .Values.map.gcs.googleApplicationCredentials.secretName }} diff --git a/backing-services/prometheus/Chart.lock b/backing-services/prometheus/Chart.lock new file mode 100644 index 0000000..7b01d03 --- /dev/null +++ b/backing-services/prometheus/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + version: 2.13.3 +digest: sha256:9a971689db0c66ea95ac2e911c05014c2b96c6077c991131ff84f2982f88fb83 +generated: "2023-11-08T15:29:25.848183439Z" diff --git a/backing-services/prometheus/Chart.yaml b/backing-services/prometheus/Chart.yaml new file mode 100644 index 0000000..b316216 --- /dev/null +++ b/backing-services/prometheus/Chart.yaml @@ -0,0 +1,38 @@ +# Copyright VMware, Inc. +# SPDX-License-Identifier: APACHE-2.0 + +annotations: + category: Analytics + licenses: Apache-2.0 + images: | + - name: alertmanager + image: docker.io/bitnami/alertmanager:0.26.0-debian-11-r45 + - name: os-shell + image: docker.io/bitnami/os-shell:11-debian-11-r92 + - name: prometheus + image: docker.io/bitnami/prometheus:2.48.1-debian-11-r0 + - name: thanos + image: docker.io/bitnami/thanos:0.32.5-debian-11-r2 +apiVersion: v2 +appVersion: 2.48.1 +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + tags: + - bitnami-common + version: 2.x.x +description: Prometheus is an open source monitoring and alerting system. It enables sysadmins to monitor their infrastructures by collecting metrics from configured targets at given intervals. +home: https://github.com/prometheus/prometheus +icon: https://bitnami.com/assets/stacks/prometheus/img/prometheus-stack-220x234.png +keywords: +- prometheus +- monitoring +maintainers: +- name: Bitnami + url: https://github.com/bitnami/charts +name: prometheus +sources: +- https://github.com/bitnami/containers/tree/main/bitnami/prometheus +- https://github.com/prometheus/prometheus +- https://github.com/prometheus-community/helm-charts +version: 0.5.1 diff --git a/backing-services/prometheus/README.md b/backing-services/prometheus/README.md new file mode 100644 index 0000000..45452f5 --- /dev/null +++ b/backing-services/prometheus/README.md @@ -0,0 +1,700 @@ + + +# Bitnami package for Prometheus + +Prometheus is an open source monitoring and alerting system. It enables sysadmins to monitor their infrastructures by collecting metrics from configured targets at given intervals. + +[Overview of Prometheus](https://prometheus.io/) + +Trademarks: This software listing is packaged by Bitnami. The respective trademarks mentioned in the offering are owned by the respective companies, and use of them does not imply any affiliation or endorsement. + +## TL;DR + +```console +helm install my-release oci://registry-1.docker.io/bitnamicharts/prometheus +``` + +Looking to use Prometheus in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the enterprise edition of Bitnami Application Catalog. + +## Introduction + +Bitnami charts for Helm are carefully engineered, actively maintained and are the quickest and easiest way to deploy containers on a Kubernetes cluster that are ready to handle production workloads. + +This chart bootstraps a [Prometheus](https://prometheus.io) Deployment in a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters. + +[Learn more about the default configuration of the chart](https://docs.bitnami.com/kubernetes/infrastructure/prometheus/get-started/). + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ +- PV provisioner support in the underlying infrastructure +- ReadWriteMany volumes for deployment scaling + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```console +helm install my-release oci://REGISTRY_NAME/REPOSITORY_NAME/prometheus +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The command deploys Prometheus 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 + +### Global parameters + +| Name | Description | Value | +| ------------------------- | ----------------------------------------------- | ----- | +| `global.imageRegistry` | Global Docker image registry | `""` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | +| `global.storageClass` | Global StorageClass for Persistent Volume(s) | `""` | + +### Common parameters + +| Name | Description | Value | +| ------------------------ | --------------------------------------------------------------------------------------- | --------------- | +| `kubeVersion` | Override Kubernetes version | `""` | +| `nameOverride` | String to partially override common.names.name | `""` | +| `fullnameOverride` | String to fully override common.names.fullname | `""` | +| `namespaceOverride` | String to fully override common.names.namespace | `""` | +| `commonLabels` | Labels to add to all deployed objects | `{}` | +| `commonAnnotations` | Annotations to add to all deployed objects | `{}` | +| `clusterDomain` | Kubernetes cluster domain name | `cluster.local` | +| `extraDeploy` | Array of extra objects to deploy with the release | `[]` | +| `diagnosticMode.enabled` | Enable diagnostic mode (all probes will be disabled and the command will be overridden) | `false` | +| `diagnosticMode.command` | Command to override all containers in the deployment | `["sleep"]` | +| `diagnosticMode.args` | Args to override all containers in the deployment | `["infinity"]` | +| `ingress.apiVersion` | Force Ingress API version (automatically detected if not set) | `""` | + +### Alertmanager Parameters + +| Name | Description | Value | +| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | +| `alertmanager.enabled` | Alertmanager enabled | `true` | +| `alertmanager.image.registry` | Alertmanager image registry | `REGISTRY_NAME` | +| `alertmanager.image.repository` | Alertmanager image repository | `REPOSITORY_NAME/alertmanager` | +| `alertmanager.image.digest` | Alertmanager image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag image tag (immutable tags are recommended) | `""` | +| `alertmanager.image.pullPolicy` | Alertmanager image pull policy | `IfNotPresent` | +| `alertmanager.image.pullSecrets` | Alertmanager image pull secrets | `[]` | +| `alertmanager.configuration` | Alertmanager configuration. This content will be stored in the the alertmanager.yaml file and the content can be a template. | `""` | +| `alertmanager.replicaCount` | Number of Alertmanager replicas to deploy | `1` | +| `alertmanager.containerPorts.http` | Alertmanager HTTP container port | `9093` | +| `alertmanager.containerPorts.cluster` | Alertmanager Cluster HA port | `9094` | +| `alertmanager.livenessProbe.enabled` | Enable livenessProbe on Alertmanager containers | `true` | +| `alertmanager.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `5` | +| `alertmanager.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `20` | +| `alertmanager.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `3` | +| `alertmanager.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `3` | +| `alertmanager.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `alertmanager.readinessProbe.enabled` | Enable readinessProbe on Alertmanager containers | `true` | +| `alertmanager.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `alertmanager.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `alertmanager.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `2` | +| `alertmanager.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `5` | +| `alertmanager.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `alertmanager.startupProbe.enabled` | Enable startupProbe on Alertmanager containers | `false` | +| `alertmanager.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `2` | +| `alertmanager.startupProbe.periodSeconds` | Period seconds for startupProbe | `5` | +| `alertmanager.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `2` | +| `alertmanager.startupProbe.failureThreshold` | Failure threshold for startupProbe | `10` | +| `alertmanager.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `alertmanager.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `alertmanager.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `alertmanager.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `alertmanager.resources.limits` | The resources limits for the Alertmanager containers | `{}` | +| `alertmanager.resources.requests` | The requested resources for the Alertmanager containers | `{}` | +| `alertmanager.podSecurityContext.enabled` | Enabled Alertmanager pods' Security Context | `true` | +| `alertmanager.podSecurityContext.fsGroup` | Set Alertmanager pod's Security Context fsGroup | `1001` | +| `alertmanager.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `alertmanager.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `alertmanager.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `alertmanager.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `alertmanager.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `false` | +| `alertmanager.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `alertmanager.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `alertmanager.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `alertmanager.existingConfigmap` | The name of an existing ConfigMap with your custom configuration for Alertmanager | `""` | +| `alertmanager.existingConfigmapKey` | The name of the key with the Alertmanager config file | `""` | +| `alertmanager.command` | Override default container command (useful when using custom images) | `[]` | +| `alertmanager.args` | Override default container args (useful when using custom images) | `[]` | +| `alertmanager.extraArgs` | Additional arguments passed to the Prometheus server container | `[]` | +| `alertmanager.hostAliases` | Alertmanager pods host aliases | `[]` | +| `alertmanager.podLabels` | Extra labels for Alertmanager pods | `{}` | +| `alertmanager.podAnnotations` | Annotations for Alertmanager pods | `{}` | +| `alertmanager.podAffinityPreset` | Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `alertmanager.podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `alertmanager.pdb.create` | Enable/disable a Pod Disruption Budget creation | `false` | +| `alertmanager.pdb.minAvailable` | Minimum number/percentage of pods that should remain scheduled | `1` | +| `alertmanager.pdb.maxUnavailable` | Maximum number/percentage of pods that may be made unavailable | `""` | +| `alertmanager.nodeAffinityPreset.type` | Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `alertmanager.nodeAffinityPreset.key` | Node label key to match. Ignored if `affinity` is set | `""` | +| `alertmanager.nodeAffinityPreset.values` | Node label values to match. Ignored if `affinity` is set | `[]` | +| `alertmanager.affinity` | Affinity for Alertmanager pods assignment | `{}` | +| `alertmanager.nodeSelector` | Node labels for Alertmanager pods assignment | `{}` | +| `alertmanager.tolerations` | Tolerations for Alertmanager pods assignment | `[]` | +| `alertmanager.updateStrategy.type` | Alertmanager statefulset strategy type | `RollingUpdate` | +| `alertmanager.podManagementPolicy` | Statefulset Pod management policy, it needs to be Parallel to be able to complete the cluster join | `OrderedReady` | +| `alertmanager.priorityClassName` | Alertmanager pods' priorityClassName | `""` | +| `alertmanager.topologySpreadConstraints` | Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template | `[]` | +| `alertmanager.schedulerName` | Name of the k8s scheduler (other than default) for Alertmanager pods | `""` | +| `alertmanager.terminationGracePeriodSeconds` | Seconds Redmine pod needs to terminate gracefully | `""` | +| `alertmanager.lifecycleHooks` | for the Alertmanager container(s) to automate configuration before or after startup | `{}` | +| `alertmanager.extraEnvVars` | Array with extra environment variables to add to Alertmanager nodes | `[]` | +| `alertmanager.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for Alertmanager nodes | `""` | +| `alertmanager.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for Alertmanager nodes | `""` | +| `alertmanager.extraVolumes` | Optionally specify extra list of additional volumes for the Alertmanager pod(s) | `[]` | +| `alertmanager.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the Alertmanager container(s) | `[]` | +| `alertmanager.sidecars` | Add additional sidecar containers to the Alertmanager pod(s) | `[]` | +| `alertmanager.initContainers` | Add additional init containers to the Alertmanager pod(s) | `[]` | +| `alertmanager.ingress.enabled` | Enable ingress record generation for Alertmanager | `false` | +| `alertmanager.ingress.pathType` | Ingress path type | `ImplementationSpecific` | +| `alertmanager.ingress.hostname` | Default host for the ingress record | `alertmanager.prometheus.local` | +| `alertmanager.ingress.ingressClassName` | IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+) | `""` | +| `alertmanager.ingress.path` | Default path for the ingress record | `/` | +| `alertmanager.ingress.annotations` | Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. | `{}` | +| `alertmanager.ingress.tls` | Enable TLS configuration for the host defined at `ingress.hostname` parameter | `false` | +| `alertmanager.ingress.selfSigned` | Create a TLS secret for this ingress record using self-signed certificates generated by Helm | `false` | +| `alertmanager.ingress.extraHosts` | An array with additional hostname(s) to be covered with the ingress record | `[]` | +| `alertmanager.ingress.extraPaths` | An array with additional arbitrary paths that may need to be added to the ingress under the main host | `[]` | +| `alertmanager.ingress.extraTls` | TLS configuration for additional hostname(s) to be covered with this ingress record | `[]` | +| `alertmanager.ingress.secrets` | Custom TLS certificates as secrets | `[]` | +| `alertmanager.ingress.extraRules` | Additional rules to be covered with this ingress record | `[]` | +| `alertmanager.serviceAccount.create` | Specifies whether a ServiceAccount should be created | `true` | +| `alertmanager.serviceAccount.name` | The name of the ServiceAccount to use. | `""` | +| `alertmanager.serviceAccount.annotations` | Additional Service Account annotations (evaluated as a template) | `{}` | +| `alertmanager.serviceAccount.automountServiceAccountToken` | Automount service account token for the server service account | `true` | +| `alertmanager.service.type` | Alertmanager service type | `LoadBalancer` | +| `alertmanager.service.ports.http` | Alertmanager service HTTP port | `80` | +| `alertmanager.service.ports.cluster` | Alertmanager cluster HA port | `9094` | +| `alertmanager.service.nodePorts.http` | Node port for HTTP | `""` | +| `alertmanager.service.clusterIP` | Alertmanager service Cluster IP | `""` | +| `alertmanager.service.loadBalancerIP` | Alertmanager service Load Balancer IP | `""` | +| `alertmanager.service.loadBalancerClass` | Alertmanager service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) | `""` | +| `alertmanager.service.loadBalancerSourceRanges` | Alertmanager service Load Balancer sources | `[]` | +| `alertmanager.service.externalTrafficPolicy` | Alertmanager service external traffic policy | `Cluster` | +| `alertmanager.service.annotations` | Additional custom annotations for Alertmanager service | `{}` | +| `alertmanager.service.extraPorts` | Extra ports to expose in Alertmanager service (normally used with the `sidecars` value) | `[]` | +| `alertmanager.service.sessionAffinity` | Control where client requests go, to the same pod or round-robin | `None` | +| `alertmanager.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `alertmanager.persistence.enabled` | Enable Alertmanager data persistence using VolumeClaimTemplates | `false` | +| `alertmanager.persistence.mountPath` | Path to mount the volume at. | `/bitnami/alertmanager/data` | +| `alertmanager.persistence.subPath` | The subdirectory of the volume to mount to, useful in dev environments and one PV for multiple services | `""` | +| `alertmanager.persistence.storageClass` | PVC Storage Class for Concourse worker data volume | `""` | +| `alertmanager.persistence.accessModes` | PVC Access Mode for Concourse worker volume | `["ReadWriteOnce"]` | +| `alertmanager.persistence.size` | PVC Storage Request for Concourse worker volume | `8Gi` | +| `alertmanager.persistence.annotations` | Annotations for the PVC | `{}` | +| `alertmanager.persistence.selector` | Selector to match an existing Persistent Volume (this value is evaluated as a template) | `{}` | + +### Prometheus server Parameters + +| Name | Description | Value | +| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- | +| `server.image.registry` | Prometheus image registry | `REGISTRY_NAME` | +| `server.image.repository` | Prometheus image repository | `REPOSITORY_NAME/prometheus` | +| `server.image.digest` | Prometheus image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag image tag (immutable tags are recommended) | `""` | +| `server.image.pullPolicy` | Prometheus image pull policy | `IfNotPresent` | +| `server.image.pullSecrets` | Prometheus image pull secrets | `[]` | +| `server.configuration` | Promethus configuration. This content will be stored in the the prometheus.yaml file and the content can be a template. | `""` | +| `server.alertingRules` | Prometheus alerting rules. This content will be stored in the the rules.yaml file and the content can be a template. | `{}` | +| `server.extraScrapeConfigs` | Promethus configuration, useful to declare new scrape_configs. This content will be merged with the 'server.configuration' value and stored in the the prometheus.yaml file. | `[]` | +| `server.replicaCount` | Number of Prometheus replicas to deploy | `1` | +| `server.containerPorts.http` | Prometheus HTTP container port | `9090` | +| `server.livenessProbe.enabled` | Enable livenessProbe on Prometheus containers | `true` | +| `server.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `5` | +| `server.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `20` | +| `server.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `3` | +| `server.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `3` | +| `server.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `server.readinessProbe.enabled` | Enable readinessProbe on Prometheus containers | `true` | +| `server.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `server.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `server.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `2` | +| `server.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `5` | +| `server.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `server.startupProbe.enabled` | Enable startupProbe on Prometheus containers | `false` | +| `server.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `2` | +| `server.startupProbe.periodSeconds` | Period seconds for startupProbe | `5` | +| `server.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `2` | +| `server.startupProbe.failureThreshold` | Failure threshold for startupProbe | `10` | +| `server.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `server.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `server.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `server.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `server.resources.limits` | The resources limits for the Prometheus containers | `{}` | +| `server.resources.requests` | The requested resources for the Prometheus containers | `{}` | +| `server.podSecurityContext.enabled` | Enabled Prometheus pods' Security Context | `true` | +| `server.podSecurityContext.fsGroup` | Set Prometheus pod's Security Context fsGroup | `1001` | +| `server.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `server.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `server.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `server.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `server.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `false` | +| `server.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `server.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `server.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `server.existingConfigmap` | The name of an existing ConfigMap with your custom configuration for Prometheus | `""` | +| `server.existingConfigmapKey` | The name of the key with the Prometheus config file | `""` | +| `server.command` | Override default container command (useful when using custom images) | `[]` | +| `server.args` | Override default container args (useful when using custom images) | `[]` | +| `server.extraArgs` | Additional arguments passed to the Prometheus server container | `[]` | +| `server.hostAliases` | Prometheus pods host aliases | `[]` | +| `server.podLabels` | Extra labels for Prometheus pods | `{}` | +| `server.podAnnotations` | Annotations for Prometheus pods | `{}` | +| `server.podAffinityPreset` | Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `server.podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `server.pdb.create` | Enable/disable a Pod Disruption Budget creation | `false` | +| `server.pdb.minAvailable` | Minimum number/percentage of pods that should remain scheduled | `1` | +| `server.pdb.maxUnavailable` | Maximum number/percentage of pods that may be made unavailable | `""` | +| `server.nodeAffinityPreset.type` | Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `server.nodeAffinityPreset.key` | Node label key to match. Ignored if `affinity` is set | `""` | +| `server.nodeAffinityPreset.values` | Node label values to match. Ignored if `affinity` is set | `[]` | +| `server.affinity` | Affinity for Prometheus pods assignment | `{}` | +| `server.nodeSelector` | Node labels for Prometheus pods assignment | `{}` | +| `server.tolerations` | Tolerations for Prometheus pods assignment | `[]` | +| `server.updateStrategy.type` | Prometheus deployment strategy type. If persistence is enabled, strategy type should be set to Recreate to avoid dead locks. | `RollingUpdate` | +| `server.priorityClassName` | Prometheus pods' priorityClassName | `""` | +| `server.topologySpreadConstraints` | Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template | `[]` | +| `server.schedulerName` | Name of the k8s scheduler (other than default) for Prometheus pods | `""` | +| `server.terminationGracePeriodSeconds` | Seconds Redmine pod needs to terminate gracefully | `""` | +| `server.lifecycleHooks` | for the Prometheus container(s) to automate configuration before or after startup | `{}` | +| `server.extraEnvVars` | Array with extra environment variables to add to Prometheus nodes | `[]` | +| `server.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for Prometheus nodes | `""` | +| `server.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for Prometheus nodes | `""` | +| `server.extraVolumes` | Optionally specify extra list of additional volumes for the Prometheus pod(s) | `[]` | +| `server.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the Prometheus container(s) | `[]` | +| `server.sidecars` | Add additional sidecar containers to the Prometheus pod(s) | `[]` | +| `server.initContainers` | Add additional init containers to the Prometheus pod(s) | `[]` | +| `server.routePrefix` | Prefix for the internal routes of web endpoints | `/` | +| `server.remoteWrite` | The remote_write spec configuration for Prometheus | `[]` | +| `server.scrapeInterval` | Interval between consecutive scrapes. Example: "1m" | `""` | +| `server.scrapeTimeout` | Interval between consecutive scrapes. Example: "10s" | `""` | +| `server.evaluationInterval` | Interval between consecutive evaluations. Example: "1m" | `""` | +| `server.enableAdminAPI` | Enable Prometheus adminitrative API | `false` | +| `server.enableRemoteWriteReceiver` | Enable Prometheus to be used as a receiver for the Prometheus remote write protocol. | `false` | +| `server.enableFeatures` | Enable access to Prometheus disabled features. | `[]` | +| `server.logLevel` | Log level for Prometheus | `info` | +| `server.logFormat` | Log format for Prometheus | `logfmt` | +| `server.retention` | Metrics retention days | `10d` | +| `server.retentionSize` | Maximum size of metrics | `0` | +| `server.alertingEndpoints` | Alertmanagers to which alerts will be sent | `[]` | +| `server.externalLabels` | External labels to add to any time series or alerts when communicating with external systems | `{}` | +| `server.thanos.create` | Create a Thanos sidecar container | `false` | +| `server.thanos.image.registry` | Thanos image registry | `REGISTRY_NAME` | +| `server.thanos.image.repository` | Thanos image name | `REPOSITORY_NAME/thanos` | +| `server.thanos.image.digest` | Thanos image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `server.thanos.image.pullPolicy` | Thanos image pull policy | `IfNotPresent` | +| `server.thanos.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `server.thanos.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `server.thanos.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `server.thanos.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `server.thanos.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `server.thanos.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `false` | +| `server.thanos.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `server.thanos.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `server.thanos.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `server.thanos.prometheusUrl` | Override default prometheus url `http://localhost:9090` | `""` | +| `server.thanos.extraArgs` | Additional arguments passed to the thanos sidecar container | `[]` | +| `server.thanos.objectStorageConfig.secretName` | Support mounting a Secret for the objectStorageConfig of the sideCar container. | `""` | +| `server.thanos.objectStorageConfig.secretKey` | Secret key with the configuration file. | `thanos.yaml` | +| `server.thanos.extraVolumeMounts` | Additional volumeMounts from `server.volumes` for thanos sidecar container | `[]` | +| `server.thanos.resources.limits` | The resources limits for the Thanos sidecar container | `{}` | +| `server.thanos.resources.requests` | The resources requests for the Thanos sidecar container | `{}` | +| `server.thanos.livenessProbe.enabled` | Turn on and off liveness probe | `true` | +| `server.thanos.livenessProbe.initialDelaySeconds` | Delay before liveness probe is initiated | `0` | +| `server.thanos.livenessProbe.periodSeconds` | How often to perform the probe | `5` | +| `server.thanos.livenessProbe.timeoutSeconds` | When the probe times out | `3` | +| `server.thanos.livenessProbe.failureThreshold` | Minimum consecutive failures for the probe | `120` | +| `server.thanos.livenessProbe.successThreshold` | Minimum consecutive successes for the probe | `1` | +| `server.thanos.readinessProbe.enabled` | Turn on and off readiness probe | `true` | +| `server.thanos.readinessProbe.initialDelaySeconds` | Delay before readiness probe is initiated | `0` | +| `server.thanos.readinessProbe.periodSeconds` | How often to perform the probe | `5` | +| `server.thanos.readinessProbe.timeoutSeconds` | When the probe times out | `3` | +| `server.thanos.readinessProbe.failureThreshold` | Minimum consecutive failures for the probe | `120` | +| `server.thanos.readinessProbe.successThreshold` | Minimum consecutive successes for the probe | `1` | +| `server.thanos.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `server.thanos.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `server.thanos.service.type` | Kubernetes service type | `ClusterIP` | +| `server.thanos.service.ports.grpc` | Thanos service port | `10901` | +| `server.thanos.service.clusterIP` | Specific cluster IP when service type is cluster IP. Use `None` to create headless service by default. | `None` | +| `server.thanos.service.nodePorts.grpc` | Specify the nodePort value for the LoadBalancer and NodePort service types. | `""` | +| `server.thanos.service.loadBalancerIP` | `loadBalancerIP` if service type is `LoadBalancer` | `""` | +| `server.thanos.service.loadBalancerClass` | Thanos service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) | `""` | +| `server.thanos.service.loadBalancerSourceRanges` | Address that are allowed when svc is `LoadBalancer` | `[]` | +| `server.thanos.service.annotations` | Additional annotations for Prometheus service | `{}` | +| `server.thanos.service.extraPorts` | Additional ports to expose from the Thanos sidecar container | `[]` | +| `server.thanos.service.externalTrafficPolicy` | Prometheus service external traffic policy | `Cluster` | +| `server.thanos.service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` | +| `server.thanos.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `server.thanos.ingress.enabled` | Enable ingress controller resource | `false` | +| `server.thanos.ingress.pathType` | Ingress path type | `ImplementationSpecific` | +| `server.thanos.ingress.hostname` | Default host for the ingress record | `thanos.prometheus.local` | +| `server.thanos.ingress.path` | Default path for the ingress record | `/` | +| `server.thanos.ingress.annotations` | Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. | `{}` | +| `server.thanos.ingress.ingressClassName` | IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+) | `""` | +| `server.thanos.ingress.tls` | Enable TLS configuration for the host defined at `ingress.hostname` parameter | `false` | +| `server.thanos.ingress.selfSigned` | Create a TLS secret for this ingress record using self-signed certificates generated by Helm | `false` | +| `server.thanos.ingress.extraHosts` | An array with additional hostname(s) to be covered with the ingress record | `[]` | +| `server.thanos.ingress.extraPaths` | An array with additional arbitrary paths that may need to be added to the ingress under the main host | `[]` | +| `server.thanos.ingress.extraTls` | TLS configuration for additional hostname(s) to be covered with this ingress record | `[]` | +| `server.thanos.ingress.secrets` | Custom TLS certificates as secrets | `[]` | +| `server.thanos.ingress.extraRules` | The list of additional rules to be added to this ingress record. Evaluated as a template | `[]` | +| `server.ingress.enabled` | Enable ingress record generation for Prometheus | `false` | +| `server.ingress.pathType` | Ingress path type | `ImplementationSpecific` | +| `server.ingress.hostname` | Default host for the ingress record | `server.prometheus.local` | +| `server.ingress.ingressClassName` | IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+) | `""` | +| `server.ingress.path` | Default path for the ingress record | `/` | +| `server.ingress.annotations` | Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. | `{}` | +| `server.ingress.tls` | Enable TLS configuration for the host defined at `ingress.hostname` parameter | `false` | +| `server.ingress.selfSigned` | Create a TLS secret for this ingress record using self-signed certificates generated by Helm | `false` | +| `server.ingress.extraHosts` | An array with additional hostname(s) to be covered with the ingress record | `[]` | +| `server.ingress.extraPaths` | An array with additional arbitrary paths that may need to be added to the ingress under the main host | `[]` | +| `server.ingress.extraTls` | TLS configuration for additional hostname(s) to be covered with this ingress record | `[]` | +| `server.ingress.secrets` | Custom TLS certificates as secrets | `[]` | +| `server.ingress.extraRules` | Additional rules to be covered with this ingress record | `[]` | +| `server.serviceAccount.create` | Specifies whether a ServiceAccount should be created | `true` | +| `server.serviceAccount.name` | The name of the ServiceAccount to use. | `""` | +| `server.serviceAccount.annotations` | Additional Service Account annotations (evaluated as a template) | `{}` | +| `server.serviceAccount.automountServiceAccountToken` | Automount service account token for the server service account | `true` | +| `server.service.type` | Prometheus service type | `LoadBalancer` | +| `server.service.ports.http` | Prometheus service HTTP port | `80` | +| `server.service.nodePorts.http` | Node port for HTTP | `""` | +| `server.service.clusterIP` | Prometheus service Cluster IP | `""` | +| `server.service.loadBalancerIP` | Prometheus service Load Balancer IP | `""` | +| `server.service.loadBalancerClass` | Prometheus service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) | `""` | +| `server.service.loadBalancerSourceRanges` | Prometheus service Load Balancer sources | `[]` | +| `server.service.externalTrafficPolicy` | Prometheus service external traffic policy | `Cluster` | +| `server.service.annotations` | Additional custom annotations for Prometheus service | `{}` | +| `server.service.extraPorts` | Extra ports to expose in Prometheus service (normally used with the `sidecars` value) | `[]` | +| `server.service.sessionAffinity` | Control where client requests go, to the same pod or round-robin. ClientIP by default. | `ClientIP` | +| `server.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `server.persistence.enabled` | Enable persistence using Persistent Volume Claims. If you have multiple instances (server.repicacount > 1), please considere using an external storage service like Thanos or Grafana Mimir | `false` | +| `server.persistence.mountPath` | Path to mount the volume at. | `/bitnami/prometheus/data` | +| `server.persistence.subPath` | The subdirectory of the volume to mount to, useful in dev environments and one PV for multiple services | `""` | +| `server.persistence.storageClass` | Storage class of backing PVC | `""` | +| `server.persistence.annotations` | Persistent Volume Claim annotations | `{}` | +| `server.persistence.accessModes` | Persistent Volume Access Modes | `["ReadWriteOnce"]` | +| `server.persistence.size` | Size of data volume | `8Gi` | +| `server.persistence.existingClaim` | The name of an existing PVC to use for persistence | `""` | +| `server.persistence.selector` | Selector to match an existing Persistent Volume for WordPress data PVC | `{}` | +| `server.persistence.dataSource` | Custom PVC data source | `{}` | +| `server.rbac.create` | Specifies whether RBAC resources should be created | `true` | +| `server.rbac.rules` | Custom RBAC rules to set | `[]` | + +### Init Container Parameters + +| Name | Description | Value | +| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------- | -------------------------- | +| `volumePermissions.enabled` | Enable init container that changes the owner/group of the PV mount point to `runAsUser:fsGroup` | `false` | +| `volumePermissions.image.registry` | OS Shell + Utility image registry | `REGISTRY_NAME` | +| `volumePermissions.image.repository` | OS Shell + Utility image repository | `REPOSITORY_NAME/os-shell` | +| `volumePermissions.image.pullPolicy` | OS Shell + Utility image pull policy | `IfNotPresent` | +| `volumePermissions.image.pullSecrets` | OS Shell + Utility image pull secrets | `[]` | +| `volumePermissions.resources.limits` | The resources limits for the init container | `{}` | +| `volumePermissions.resources.requests` | The requested resources for the init container | `{}` | +| `volumePermissions.containerSecurityContext.runAsUser` | Set init container's Security Context runAsUser | `0` | + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +helm install my-release --set alertmanager.enabled=true \ + oci://REGISTRY_NAME/REPOSITORY_NAME/prometheus +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The above command install Prometheus chart with Alertmanager. + +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 oci://REGISTRY_NAME/REPOSITORY_NAME/prometheus +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> **Tip**: You can use the default [values.yaml](https://github.com/bitnami/charts/tree/main/bitnami/prometheus/values.yaml) + +## Configuration and installation details + +### [Rolling VS Immutable tags](https://docs.bitnami.com/tutorials/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. + +### Deploy extra resources + +There are cases where you may want to deploy extra objects, such a ConfigMap containing your app's configuration or some extra deployment with a micro service used by your app. For covering this case, the chart allows adding the full specification of other objects using the `extraDeploy` parameter. + +### Setting Pod's affinity + +This chart allows you to set your custom affinity using the `XXX.affinity` parameter(s). Find more information about Pod's affinity in the [kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). + +As an alternative, you can use of the preset configurations for pod affinity, pod anti-affinity, and node affinity available at the [bitnami/common](https://github.com/bitnami/charts/tree/main/bitnami/common#affinities) chart. To do so, set the `XXX.podAffinityPreset`, `XXX.podAntiAffinityPreset`, or `XXX.nodeAffinityPreset` parameters. + +### Integrate Prometheus and Alertmanager with Thanos + +You can integrate Prometheus & Alertmanager with Thanos using this chart and the [Bitnami Thanos chart](https://github.com/bitnami/charts/tree/main/bitnami/thanos) following the steps below: + +> Note: in this example we will use MinIO® (subchart) as the Objstore. Every component will be deployed in the "monitoring" namespace. + +- Create a **values.yaml** like the one below for Thanos: + +```yaml +objstoreConfig: |- + type: s3 + config: + bucket: thanos + endpoint: {{ include "thanos.minio.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:9000 + access_key: minio + secret_key: minio123 + insecure: true +query: + dnsDiscovery: + sidecarsService: prometheus-thanos + sidecarsNamespace: monitoring +bucketweb: + enabled: true +compactor: + enabled: true +storegateway: + enabled: true +ruler: + enabled: true + alertmanagers: + - http://prometheus-alertmanager.monitoring.svc.cluster.local:9093 + config: |- + groups: + - name: "metamonitoring" + rules: + - alert: "PrometheusDown" + expr: absent(up{prometheus="monitoring/prometheus"}) +metrics: + enabled: true + serviceMonitor: + enabled: true +minio: + enabled: true + auth: + rootPassword: minio123 + rootUser: minio + monitoringBuckets: thanos + accessKey: + password: minio + secretKey: + password: minio123 +``` + +- Install Prometheus and Thanos charts: + +For Helm 3: + +```console +kubectl create namespace monitoring +helm install prometheus \ + --set prometheus.thanos.create=true \ + --namespace monitoring \ + oci://REGISTRY_NAME/REPOSITORY_NAME/prometheus +helm install thanos \ + --values values.yaml \ + --namespace monitoring \ + oci://REGISTRY_NAME/REPOSITORY_NAME/thanos +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +That's all! Now you have Thanos fully integrated with Prometheus and Alertmanager. + +### Integrate Prometheus with Grafana Mimir + +You can integrate Prometheus with Grafana Mimir using this chart and the [Bitnami Grafana Mimir chart](https://github.com/bitnami/charts/tree/main/bitnami/grafana-mimir) adding a `remoteWrite` entry: + +- Create a **values.yaml** like the one below for Prometheus: + +```yaml +server: + remoteWrite: + - url: http://grafana-mimir-gateway.svc.cluster.local/api/v1/push + headers: + X-Scope-OrgID: demo +``` + +- Install Prometheus and Grafana Mimir charts: + +For Helm 3: + +```console +kubectl create namespace monitoring +helm install prometheus \ + --values values.yaml \ + --namespace monitoring \ + oci://REGISTRY_NAME/REPOSITORY_NAME/prometheus +helm install grafana-mimir \ + oci://REGISTRY_NAME/REPOSITORY_NAME/grafana-mimir +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +That's all! Now you have Prometheus integrated with Grafana Mimir. + +### Integrate Prometheus with Grafana + +You can integrate Prometheus with Grafana Dashboard using this chart and the [Bitnami Grafana chart](https://github.com/bitnami/charts/tree/main/bitnami/grafana) just adding the prometheus datasources: + +- Create a **values.yaml** like the one below for Grafana: + +```yaml +datasources: + secretDefinition: + apiVersion: 1 + datasources: + - name: Prometheus + type: prometheus + access: proxy + orgId: 1 + url: http://prometheus.monitoring.svc.cluster.local + version: 1 + editable: true + isDefault: true + - name: Alertmanager + uid: alertmanager + type: alertmanager + access: proxy + orgId: 1 + url: http://prometheus-alertmanager.monitoring.svc.cluster.local:9093 + version: 1 + editable: true +``` + +- Install Prometheus and Grafana charts: + +For Helm 3: + +```console +kubectl create namespace monitoring +helm install prometheus \ + --namespace monitoring \ + oci://REGISTRY_NAME/REPOSITORY_NAME/prometheus +helm install grafana-mimir \ + --values values.yaml \ + --namespace monitoring \ + oci://REGISTRY_NAME/REPOSITORY_NAME/grafana +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +### How to add new targets + +By default this helm chart will monitor its own targets: prometheus and alertmanager. Additional ones can be added setting a list with the [scrape_configs](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config) in the value `server.extraScrapeConfigs`. Here there is a simple example for wordpress (deployed in the default namespace): + +```yaml +server: + extraScrapeConfigs: + - job_name: wordpress + kubernetes_sd_configs: + - role: endpoints + namespaces: + names: + - default + metrics_path: /metrics + relabel_configs: + - source_labels: + - job + target_label: __tmp_wordpress_job_name + - action: keep + source_labels: + - __meta_kubernetes_service_label_app_kubernetes_io_instance + - __meta_kubernetes_service_labelpresent_app_kubernetes_io_instance + regex: (wordpress);true + - action: keep + source_labels: + - __meta_kubernetes_service_label_app_kubernetes_io_name + - __meta_kubernetes_service_labelpresent_app_kubernetes_io_name + regex: (wordpress);true + - action: keep + source_labels: + - __meta_kubernetes_endpoint_port_name + regex: metrics + - source_labels: + - __meta_kubernetes_endpoint_address_target_kind + - __meta_kubernetes_endpoint_address_target_name + separator: ; + regex: Node;(.*) + replacement: ${1} + target_label: node + - source_labels: + - __meta_kubernetes_endpoint_address_target_kind + - __meta_kubernetes_endpoint_address_target_name + separator: ; + regex: Pod;(.*) + replacement: ${1} + target_label: pod + - source_labels: + - __meta_kubernetes_namespace + target_label: namespace + - source_labels: + - __meta_kubernetes_service_name + target_label: service + - source_labels: + - __meta_kubernetes_pod_name + target_label: pod + - source_labels: + - __meta_kubernetes_pod_container_name + target_label: container + - action: drop + source_labels: + - __meta_kubernetes_pod_phase + regex: (Failed|Succeeded) + - source_labels: + - __meta_kubernetes_service_name + target_label: job + replacement: ${1} + - target_label: endpoint + replacement: metrics + - source_labels: + - __address__ + target_label: __tmp_hash + modulus: 1 + action: hashmod + - source_labels: + - __tmp_hash + regex: 0 + action: keep +``` + +## Troubleshooting + +Find more information about how to deal with common errors related to Bitnami's Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues). + +## License + +Copyright © 2024 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/backing-services/prometheus/charts/common-2.13.3.tgz b/backing-services/prometheus/charts/common-2.13.3.tgz new file mode 100644 index 0000000..3fe4889 Binary files /dev/null and b/backing-services/prometheus/charts/common-2.13.3.tgz differ diff --git a/backing-services/prometheus/hospital-bahman-production.values.yaml b/backing-services/prometheus/hospital-bahman-production.values.yaml new file mode 100644 index 0000000..0c16697 --- /dev/null +++ b/backing-services/prometheus/hospital-bahman-production.values.yaml @@ -0,0 +1,26 @@ +alertmanager: + enabled: false + image: + registry: 172.16.16.1:30516 + repository: bitnami/alertmanager + tag: 0.26.0-debian-11-r45 + digest: "" + +server: + image: + registry: 172.16.16.1:30516 + repository: bitnami/prometheus + tag: 2.48.1-debian-11-r0 + service: + type: NodePort + configuration: | + global: + scrape_interval: 15s # Set the scrape interval to every 15 seconds + evaluation_interval: 15s + + scrape_configs: + - job_name: 'node_exporters' + static_configs: + - targets: + - '45.159.150.146:9100' + - '45.149.78.193:9100' \ No newline at end of file diff --git a/backing-services/prometheus/templates/NOTES.txt b/backing-services/prometheus/templates/NOTES.txt new file mode 100644 index 0000000..b82c5f4 --- /dev/null +++ b/backing-services/prometheus/templates/NOTES.txt @@ -0,0 +1,123 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +** Please be patient while the chart is being deployed ** + +{{- if .Values.diagnosticMode.enabled }} +The chart has been deployed in diagnostic mode. All probes have been disabled and the command has been overwritten with: + + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 4 }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 4 }} + +Get the list of pods by executing: + + kubectl get pods --namespace {{ include "common.names.namespace" . | quote }} -l app.kubernetes.io/instance={{ .Release.Name }} + +Access the pod you want to debug by executing + + kubectl exec --namespace {{ include "common.names.namespace" . | quote }} -ti -- bash + +In order to replicate the container startup scripts execute this command: + + /opt/bitnami/prometheus/bin/prometheus --config.file=/opt/bitnami/prometheus/conf/prometheus.yml --storage.tsdb.path=/opt/bitnami/prometheus/data --web.console.libraries=/opt/bitnami/prometheus/conf/console_libraries --web.console.templates=/opt/bitnami/prometheus/conf/consoles + +{{- else }} + +Prometheus can be accessed via port "{{ .Values.server.service.ports.http }}" on the following DNS name from within your cluster: + + {{ template "common.names.fullname" . }}.{{ include "common.names.namespace" . }}.svc.cluster.local + +To access Prometheus from outside the cluster execute the following commands: + +{{- if .Values.server.ingress.enabled }} + + You should be able to access your new Prometheus installation through + + {{ ternary "https" "http" .Values.server.ingress.tls }}://{{ .Values.server.ingress.hostname }} + +{{- else if contains "LoadBalancer" .Values.server.service.type }} + + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + Watch the status with: 'kubectl get svc --namespace {{ include "common.names.namespace" . }} -w {{ template "common.names.fullname" . }}' + +{{- $port:=.Values.server.service.ports.http | toString }} + + export SERVICE_IP=$(kubectl get svc --namespace {{ include "common.names.namespace" . }} {{ template "common.names.fullname" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") + echo "Prometheus URL: http://$SERVICE_IP{{- if ne $port "80" }}:{{ .Values.server.service.ports.http }}{{ end }}/" + +{{- else if contains "ClusterIP" .Values.server.service.type }} + + echo "Prometheus URL: http://127.0.0.1:9090/" + kubectl port-forward --namespace {{ include "common.names.namespace" . }} svc/{{ template "common.names.fullname" . }} 9090:{{ .Values.server.service.ports.http }} + +{{- else if contains "NodePort" .Values.server.service.type }} + + export NODE_PORT=$(kubectl get --namespace {{ include "common.names.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "common.names.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ include "common.names.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo "Prometheus URL: http://$NODE_IP:$NODE_PORT/" + +{{- end }} + +{{- if and .Values.server.thanos.create }} + +Thanos Sidecar can be accessed via port "{{ .Values.server.thanos.service.ports.grpc }}" on the following DNS name from within your cluster: + + {{ template "prometheus.thanos-sidecar.fullname" . }}.{{ include "common.names.namespace" . }}.svc.cluster.local + +{{- if .Values.server.thanos.ingress.enabled }} + + You should be able to access your new Thanos Sidecar installation through + + {{ ternary "https" "http" .Values.server.thanos.ingress.tls }}://{{ .Values.server.thanos.ingress.hostname }} + +{{- end }} +{{- end }} +{{- end }} + +{{- if .Values.alertmanager.enabled }} + +Watch the Alertmanager StatefulSet status using the command: + + kubectl get sts -w --namespace {{ include "common.names.namespace" . }} -l app.kubernetes.io/name={{ template "prometheus.alertmanager.fullname" . }},app.kubernetes.io/instance={{ .Release.Name }} + +Alertmanager can be accessed via port "{{ .Values.alertmanager.service.ports.http }}" on the following DNS name from within your cluster: + + {{ template "prometheus.alertmanager.fullname" . }}.{{ include "common.names.namespace" . }}.svc.cluster.local + +To access Alertmanager from outside the cluster execute the following commands: + +{{- if .Values.alertmanager.ingress.enabled }} + + You should be able to access your new Prometheus installation through + + {{ ternary "https" "http" .Values.alertmanager.ingress.tls }}://{{ .Values.alertmanager.ingress.hostname }} + +{{- else if contains "LoadBalancer" .Values.alertmanager.service.type }} + + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + Watch the status with: 'kubectl get svc --namespace {{ include "common.names.namespace" . }} -w {{ template "prometheus.alertmanager.fullname" . }}' + +{{- $port:=.Values.alertmanager.service.ports.http | toString }} + + export SERVICE_IP=$(kubectl get svc --namespace {{ include "common.names.namespace" . }} {{ template "prometheus.alertmanager.fullname" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") + echo "Alertmanager URL: http://$SERVICE_IP{{- if ne $port "80" }}:{{ .Values.alertmanager.service.ports.http }}{{ end }}/" + +{{- else if contains "ClusterIP" .Values.alertmanager.service.type }} + + echo "Alertmanager URL: http://127.0.0.1:9093/" + kubectl port-forward --namespace {{ include "common.names.namespace" . }} svc/{{ template "prometheus.alertmanager.fullname" . }} 9093:{{ .Values.alertmanager.service.ports.http }} + +{{- else if contains "NodePort" .Values.alertmanager.service.type }} + + export NODE_PORT=$(kubectl get --namespace {{ include "common.names.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "prometheus.alertmanager.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ include "common.names.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo "Alertmanager URL: http://$NODE_IP:$NODE_PORT/" + +{{- end }} +{{- end }} + +{{- include "common.warnings.rollingTag" .Values.server.image }} +{{- include "common.warnings.rollingTag" .Values.server.thanos.image }} +{{- include "common.warnings.rollingTag" .Values.volumePermissions.image }} +{{- include "prometheus.server.validateValues" . }} diff --git a/backing-services/prometheus/templates/_helpers.tpl b/backing-services/prometheus/templates/_helpers.tpl new file mode 100644 index 0000000..64153cc --- /dev/null +++ b/backing-services/prometheus/templates/_helpers.tpl @@ -0,0 +1,156 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* +Return the proper image name +*/}} +{{- define "prometheus.server.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.server.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper image name +*/}} +{{- define "prometheus.alertmanager.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.alertmanager.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper image name +*/}} +{{- define "prometheus.server.thanosImage" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.server.thanos.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return Prometheus server name +*/}} +{{- define "prometheus.server.fullname" -}} + {{- printf "%s-server" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" }} +{{- end -}} + +{{/* +Return Prometheus server name +*/}} +{{- define "prometheus.server.fullname.namespace" -}} + {{- printf "%s-server" (include "common.names.fullname.namespace" .) | trunc 63 | trimSuffix "-" }} +{{- end -}} + +{{/* +Return the proper image name (for the init container volume-permissions image) +*/}} +{{- define "prometheus.volumePermissions.image" -}} +{{- include "common.images.image" ( dict "imageRoot" .Values.volumePermissions.image "global" .Values.global ) -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "prometheus.imagePullSecrets" -}} +{{- include "common.images.renderPullSecrets" (dict "images" (list .Values.server.image .Values.volumePermissions.image .Values.server.thanos.image .Values.alertmanager.image) "context" $) -}} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "prometheus.server.serviceAccountName" -}} +{{- if .Values.server.serviceAccount.create -}} + {{ default (include "prometheus.server.fullname" .) .Values.server.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.server.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Compile all warnings into a single message. +*/}} +{{- define "prometheus.server.validateValues" -}} +{{- $messages := list -}} +{{- $messages := append $messages (include "prometheus.server.validateValues.thanosObjectStorageConfig" .) -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message -}} +{{- end -}} +{{- end -}} + +{{/* +Validate thanos objectStorageConfig. +*/}} +{{- define "prometheus.server.validateValues.thanosObjectStorageConfig" -}} +{{- if (and .Values.server.thanos.objectStorageConfig (or (not (hasKey .Values.server.thanos.objectStorageConfig "secretKey")) (not (hasKey .Values.server.thanos.objectStorageConfig "secretName")) ))}} + {{- printf "'server.thanos.objectStorageConfig.secretKey' and 'server.thanos.objectStorageConfi.secretName' are mandatory" }} +{{- end }} +{{- end }} + +{{/* +Get the Prometheus configuration configmap. +*/}} +{{- define "prometheus.server.configmapName" -}} +{{- if .Values.server.existingConfigmap -}} + {{- include "common.tplvalues.render" (dict "value" .Values.server.existingConfigmap "context" .) -}} +{{- else }} + {{- include "prometheus.server.fullname" . -}} +{{- end -}} +{{- end -}} + +{{/* +Get the Prometheus configuration configmap key. +*/}} +{{- define "prometheus.server.configmapKey" -}} +{{- if .Values.server.existingConfigmapKey -}} + {{- include "common.tplvalues.render" (dict "value" .Values.server.existingConfigmapKey "context" .) -}} +{{- else }} + {{- printf "prometheus.yaml" -}} +{{- end -}} +{{- end -}} + +{{/* +Get the Prometheus Alertmanager configuration configmap key. +*/}} +{{- define "prometheus.alertmanager.configmapKey" -}} +{{- if .Values.alertmanager.existingConfigmapKey -}} + {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.existingConfigmapKey "context" .) -}} +{{- else }} + {{- printf "alertmanager.yaml" -}} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account to use in alertmanager +*/}} +{{- define "prometheus.alertmanager.serviceAccountName" -}} +{{- if .Values.alertmanager.serviceAccount.create -}} + {{ default (include "prometheus.alertmanager.fullname" .) .Values.alertmanager.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.alertmanager.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Return Thanos sidecar service/ingress name +*/}} +{{- define "prometheus.thanos-sidecar.fullname" -}} + {{- printf "%s-thanos" (include "common.names.fullname" .) }} +{{- end -}} + +{{/* +Return Alertmanager name +*/}} +{{- define "prometheus.alertmanager.fullname" -}} + {{- printf "%s-alertmanager" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" }} +{{- end -}} + +{{/* +Get the Alertmanager configuration configmap. +*/}} +{{- define "prometheus.alertmanager.configmapName" -}} +{{- if .Values.alertmanager.existingConfigmap -}} + {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.existingConfigmap "context" .) -}} +{{- else }} + {{- include "prometheus.alertmanager.fullname" . -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/prometheus/templates/_scrape_config.tpl b/backing-services/prometheus/templates/_scrape_config.tpl new file mode 100644 index 0000000..ea669ea --- /dev/null +++ b/backing-services/prometheus/templates/_scrape_config.tpl @@ -0,0 +1,86 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* +Return the prometheus scrape configuration for kubernetes objects. +Usage: +{{ include "prometheus.scrape_config" (dict "component" "alertmanager" "context" $) }} +*/}} +{{- define "prometheus.scrape_config" -}} +kubernetes_sd_configs: + - role: endpoints + namespaces: + names: + - {{ include "common.names.namespace" .context }} +metrics_path: /metrics +relabel_configs: + - source_labels: + - job + target_label: __tmp_prometheus_job_name + - action: keep + source_labels: + - __meta_kubernetes_service_label_app_kubernetes_io_component + - __meta_kubernetes_service_labelpresent_app_kubernetes_io_component + regex: ({{ .component }});true + - action: keep + source_labels: + - __meta_kubernetes_service_label_app_kubernetes_io_instance + - __meta_kubernetes_service_labelpresent_app_kubernetes_io_instance + regex: ({{ .context.Release.Name }});true + - action: keep + source_labels: + - __meta_kubernetes_service_label_app_kubernetes_io_name + - __meta_kubernetes_service_labelpresent_app_kubernetes_io_name + regex: (prometheus);true + - action: keep + source_labels: + - __meta_kubernetes_endpoint_port_name + regex: http + - source_labels: + - __meta_kubernetes_endpoint_address_target_kind + - __meta_kubernetes_endpoint_address_target_name + separator: ; + regex: Node;(.*) + replacement: ${1} + target_label: node + - source_labels: + - __meta_kubernetes_endpoint_address_target_kind + - __meta_kubernetes_endpoint_address_target_name + separator: ; + regex: Pod;(.*) + replacement: ${1} + target_label: pod + - source_labels: + - __meta_kubernetes_namespace + target_label: namespace + - source_labels: + - __meta_kubernetes_service_name + target_label: service + - source_labels: + - __meta_kubernetes_pod_name + target_label: pod + - source_labels: + - __meta_kubernetes_pod_container_name + target_label: container + - action: drop + source_labels: + - __meta_kubernetes_pod_phase + regex: (Failed|Succeeded) + - source_labels: + - __meta_kubernetes_service_name + target_label: job + replacement: ${1} + - target_label: endpoint + replacement: http + - source_labels: + - __address__ + target_label: __tmp_hash + modulus: 1 + action: hashmod + - source_labels: + - __tmp_hash + regex: 0 + action: keep +{{- end -}} \ No newline at end of file diff --git a/backing-services/prometheus/templates/alertmanager/configmap.yaml b/backing-services/prometheus/templates/alertmanager/configmap.yaml new file mode 100644 index 0000000..70b4181 --- /dev/null +++ b/backing-services/prometheus/templates/alertmanager/configmap.yaml @@ -0,0 +1,23 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.alertmanager.enabled (not .Values.alertmanager.existingConfigmap) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "prometheus.alertmanager.fullname" . | quote }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.alertmanager.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: alertmanager + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + {{ include "prometheus.alertmanager.configmapKey" . }}: + {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.configuration "context" $) | toYaml | nindent 4 }} +{{- end }} diff --git a/backing-services/prometheus/templates/alertmanager/ingress.yaml b/backing-services/prometheus/templates/alertmanager/ingress.yaml new file mode 100644 index 0000000..94d52c1 --- /dev/null +++ b/backing-services/prometheus/templates/alertmanager/ingress.yaml @@ -0,0 +1,63 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.alertmanager.enabled .Values.alertmanager.ingress.enabled }} +apiVersion: {{ include "common.capabilities.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ include "prometheus.alertmanager.fullname" . | quote }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.alertmanager.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: alertmanager + {{- if or .Values.alertmanager.ingress.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.alertmanager.ingress.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.alertmanager.ingress.ingressClassName (eq "true" (include "common.ingress.supportsIngressClassname" .)) }} + ingressClassName: {{ .Values.alertmanager.ingress.ingressClassName | quote }} + {{- end }} + rules: + {{- if .Values.alertmanager.ingress.hostname }} + - host: {{ .Values.alertmanager.ingress.hostname }} + http: + paths: + {{- if .Values.alertmanager.ingress.extraPaths }} + {{- toYaml .Values.alertmanager.ingress.extraPaths | nindent 10 }} + {{- end }} + - path: {{ .Values.alertmanager.ingress.path }} + {{- if eq "true" (include "common.ingress.supportsPathType" .) }} + pathType: {{ .Values.alertmanager.ingress.pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "prometheus.alertmanager.fullname" .) "servicePort" "http" "context" $) | nindent 14 }} + {{- end }} + {{- range .Values.alertmanager.ingress.extraHosts }} + - host: {{ .name | quote }} + http: + paths: + - path: {{ default "/" .path }} + {{- if eq "true" (include "common.ingress.supportsPathType" $) }} + pathType: {{ default "ImplementationSpecific" .pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "prometheus.alertmanager.fullname" $) "servicePort" "http" "context" $) | nindent 14 }} + {{- end }} + {{- if .Values.alertmanager.ingress.extraRules }} + {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.ingress.extraRules "context" $) | nindent 4 }} + {{- end }} + {{- if or (and .Values.alertmanager.ingress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.alertmanager.ingress.annotations )) .Values.alertmanager.ingress.selfSigned)) .Values.alertmanager.ingress.extraTls }} + tls: + {{- if and .Values.alertmanager.ingress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.alertmanager.ingress.annotations )) .Values.alertmanager.ingress.selfSigned) }} + - hosts: + - {{ .Values.alertmanager.ingress.hostname | quote }} + secretName: {{ printf "%s-tls" .Values.alertmanager.ingress.hostname }} + {{- end }} + {{- if .Values.alertmanager.ingress.extraTls }} + {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.ingress.extraTls "context" $) | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/prometheus/templates/alertmanager/pdb.yaml b/backing-services/prometheus/templates/alertmanager/pdb.yaml new file mode 100644 index 0000000..8453cdf --- /dev/null +++ b/backing-services/prometheus/templates/alertmanager/pdb.yaml @@ -0,0 +1,33 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- $replicaCount := int .Values.alertmanager.replicaCount }} +{{- if and .Values.alertmanager.enabled .Values.alertmanager.pdb.create (gt $replicaCount 1) }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "prometheus.alertmanager.fullname" . | quote }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.alertmanager.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: alertmanager + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.alertmanager.pdb.minAvailable }} + minAvailable: {{ .Values.alertmanager.pdb.minAvailable }} + {{- end }} + {{- if .Values.alertmanager.pdb.maxUnavailable }} + maxUnavailable: {{ .Values.alertmanager.pdb.maxUnavailable }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.alertmanager.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: alertmanager +{{- end }} diff --git a/backing-services/prometheus/templates/alertmanager/service-account.yaml b/backing-services/prometheus/templates/alertmanager/service-account.yaml new file mode 100644 index 0000000..8ef2522 --- /dev/null +++ b/backing-services/prometheus/templates/alertmanager/service-account.yaml @@ -0,0 +1,22 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.alertmanager.enabled .Values.alertmanager.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "prometheus.alertmanager.serviceAccountName" . | quote }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.alertmanager.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: alertmanager + {{- if or .Values.alertmanager.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.alertmanager.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.alertmanager.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/backing-services/prometheus/templates/alertmanager/service-headless.yaml b/backing-services/prometheus/templates/alertmanager/service-headless.yaml new file mode 100644 index 0000000..fc4f95d --- /dev/null +++ b/backing-services/prometheus/templates/alertmanager/service-headless.yaml @@ -0,0 +1,40 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.alertmanager.enabled (gt (int .Values.alertmanager.replicaCount) 1) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-headless" (include "prometheus.alertmanager.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.alertmanager.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: alertmanager + {{- if or .Values.alertmanager.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.alertmanager.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + ports: + - name: tcp-cluster + port: {{ .Values.alertmanager.service.ports.cluster }} + protocol: TCP + targetPort: tcp-cluster + - name: udp-cluster + port: {{ .Values.alertmanager.service.ports.cluster }} + protocol: UDP + targetPort: udp-cluster + {{- if .Values.alertmanager.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.alertmanager.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: alertmanager +{{- end }} diff --git a/backing-services/prometheus/templates/alertmanager/service.yaml b/backing-services/prometheus/templates/alertmanager/service.yaml new file mode 100644 index 0000000..6e413c0 --- /dev/null +++ b/backing-services/prometheus/templates/alertmanager/service.yaml @@ -0,0 +1,61 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.alertmanager.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "prometheus.alertmanager.fullname" . | quote }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.alertmanager.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: alertmanager + {{- if or .Values.alertmanager.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.alertmanager.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.alertmanager.service.type }} + {{- if and .Values.alertmanager.service.clusterIP (eq .Values.alertmanager.service.type "ClusterIP") }} + clusterIP: {{ .Values.alertmanager.service.clusterIP }} + {{- end }} + {{- if .Values.alertmanager.service.sessionAffinity }} + sessionAffinity: {{ .Values.alertmanager.service.sessionAffinity }} + {{- end }} + {{- if .Values.alertmanager.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + {{- if or (eq .Values.alertmanager.service.type "LoadBalancer") (eq .Values.alertmanager.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.alertmanager.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.alertmanager.service.type "LoadBalancer") (not (empty .Values.alertmanager.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ .Values.alertmanager.service.loadBalancerSourceRanges }} + {{- end }} + {{- if and (eq .Values.alertmanager.service.type "LoadBalancer") (not (empty .Values.alertmanager.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.alertmanager.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.alertmanager.service.type "LoadBalancer") (not (empty .Values.alertmanager.service.loadBalancerClass)) }} + loadBalancerClass: {{ .Values.alertmanager.service.loadBalancerClass }} + {{- end }} + ports: + - name: http + port: {{ .Values.alertmanager.service.ports.http }} + protocol: TCP + targetPort: http + {{- if and (or (eq .Values.alertmanager.service.type "NodePort") (eq .Values.alertmanager.service.type "LoadBalancer")) (not (empty .Values.alertmanager.service.nodePorts.http)) }} + nodePort: {{ .Values.alertmanager.service.nodePorts.http }} + {{- else if eq .Values.alertmanager.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.alertmanager.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.alertmanager.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: alertmanager +{{- end }} diff --git a/backing-services/prometheus/templates/alertmanager/statefulset.yaml b/backing-services/prometheus/templates/alertmanager/statefulset.yaml new file mode 100644 index 0000000..e1a69c8 --- /dev/null +++ b/backing-services/prometheus/templates/alertmanager/statefulset.yaml @@ -0,0 +1,241 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.alertmanager.enabled }} +{{- $clusterPort := .Values.alertmanager.containerPorts.cluster }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ include "prometheus.alertmanager.fullname" . | quote }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.alertmanager.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: alertmanager + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.alertmanager.replicaCount }} + podManagementPolicy: {{ .Values.alertmanager.podManagementPolicy | quote }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.alertmanager.podLabels .Values.commonLabels $versionLabel ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: alertmanager + serviceName: {{ printf "%s-headless" (include "prometheus.alertmanager.fullname" .) }} + {{- if .Values.alertmanager.updateStrategy }} + updateStrategy: {{- toYaml .Values.alertmanager.updateStrategy | nindent 4 }} + {{- end }} + template: + metadata: + {{- if .Values.alertmanager.podAnnotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.podAnnotations "context" $) | nindent 8 }} + {{- end }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: alertmanager + spec: + serviceAccountName: {{ template "prometheus.alertmanager.serviceAccountName" . }} + {{- include "prometheus.imagePullSecrets" . | nindent 6 }} + {{- if .Values.alertmanager.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.alertmanager.affinity }} + affinity: {{- include "common.tplvalues.render" ( dict "value" .Values.alertmanager.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.alertmanager.podAffinityPreset "component" "alertmanager" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.alertmanager.podAntiAffinityPreset "component" "alertmanager" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.alertmanager.nodeAffinityPreset.type "key" .Values.alertmanager.nodeAffinityPreset.key "values" .Values.alertmanager.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.alertmanager.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" ( dict "value" .Values.alertmanager.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.alertmanager.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.tolerations "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.alertmanager.priorityClassName }} + priorityClassName: {{ .Values.alertmanager.priorityClassName | quote }} + {{- end }} + {{- if .Values.alertmanager.schedulerName }} + schedulerName: {{ .Values.alertmanager.schedulerName | quote }} + {{- end }} + {{- if .Values.alertmanager.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.alertmanager.podSecurityContext.enabled }} + securityContext: {{- omit .Values.alertmanager.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.alertmanager.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.alertmanager.terminationGracePeriodSeconds }} + {{- end }} + initContainers: + {{- if and .Values.volumePermissions.enabled .Values.alertmanager.persistence.enabled }} + - name: volume-permissions + image: {{ include "prometheus.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - sh + - -ec + - | + mkdir -p {{ .Values.alertmanager.persistence.mountPath }} + find {{ .Values.alertmanager.persistence.mountPath }} -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | xargs -r chown -R {{ .Values.alertmanager.containerSecurityContext.runAsUser }}:{{ .Values.alertmanager.podSecurityContext.fsGroup }} + {{- if .Values.alertmanager.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.alertmanager.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: data + mountPath: {{ .Values.alertmanager.persistence.mountPath }} + {{- if .Values.alertmanager.persistence.subPath }} + subPath: {{ .Values.alertmanager.persistence.subPath }} + {{- end }} + {{- end }} + {{- if .Values.alertmanager.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.initContainers "context" $) | nindent 8 }} + {{- end }} + containers: + - name: alertmanager + image: {{ template "prometheus.alertmanager.image" . }} + imagePullPolicy: {{ .Values.alertmanager.image.pullPolicy }} + {{- if .Values.alertmanager.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.alertmanager.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.alertmanager.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.alertmanager.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.args "context" $) | nindent 12 }} + {{- else }} + args: + - "--config.file=/opt/bitnami/alertmanager/conf/{{ include "prometheus.alertmanager.configmapKey" . }}" + - "--storage.path=/opt/bitnami/alertmanager/data" + - "--web.listen-address=0.0.0.0:{{ .Values.alertmanager.containerPorts.http }}" + {{- if gt (int .Values.alertmanager.replicaCount) 1 }} + - "--cluster.advertise-address=[$(POD_IP)]:{{ $clusterPort }}" + - "--cluster.listen-address=0.0.0.0:{{ $clusterPort }}" + {{- $fullName := include "prometheus.alertmanager.fullname" . }} + {{- range $i := until (int .Values.alertmanager.replicaCount) }} + - "--cluster.peer={{ $fullName }}-{{ $i }}.{{ $fullName }}-headless.{{ include "common.names.namespace" $ }}.svc.{{ $.Values.clusterDomain }}:{{ $clusterPort }}" + {{- end }} + {{- end }} + {{- if .Values.alertmanager.extraArgs }} + {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.extraArgs "context" $) | nindent 12 }} + {{- end }} + {{- end }} + env: + - name: POD_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + {{- if .Values.alertmanager.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.alertmanager.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.alertmanager.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.alertmanager.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.alertmanager.extraEnvVarsSecret "context" $) }} + {{- end }} + {{- if .Values.alertmanager.resources }} + resources: {{- toYaml .Values.alertmanager.resources | nindent 12 }} + {{- end }} + ports: + - name: http + containerPort: {{ .Values.alertmanager.containerPorts.http }} + - name: tcp-cluster + containerPort: {{ $clusterPort }} + protocol: TCP + - name: udp-cluster + containerPort: {{ $clusterPort }} + protocol: UDP + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.alertmanager.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.alertmanager.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.alertmanager.livenessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: /-/healthy + port: http + {{- end }} + {{- if .Values.alertmanager.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.alertmanager.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.alertmanager.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: /-/ready + port: http + {{- end }} + {{- if .Values.alertmanager.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.alertmanager.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.alertmanager.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: http + {{- end }} + {{- end }} + {{- if .Values.alertmanager.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + volumeMounts: + - name: config + mountPath: /opt/bitnami/alertmanager/conf + readOnly: true + - name: data + mountPath: {{ .Values.alertmanager.persistence.mountPath }} + {{- if .Values.alertmanager.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.alertmanager.sidecars }} + {{- include "common.tplvalues.render" ( dict "value" .Values.alertmanager.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: config + configMap: + name: {{ include "prometheus.alertmanager.configmapName" . }} + {{- if not .Values.alertmanager.persistence.enabled }} + - name: data + emptyDir: {} + {{- end}} + {{- if .Values.alertmanager.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.extraVolumes "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.alertmanager.persistence.enabled }} + volumeClaimTemplates: + - metadata: + name: data + {{- if or .Values.alertmanager.persistence.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.alertmanager.persistence.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.commonLabels }} + labels: {{- include "common.tplvalues.render" (dict "value" .Values.commonLabels "context" $) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.alertmanager.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.alertmanager.persistence.size | quote }} + {{- if .Values.alertmanager.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.alertmanager.persistence.selector "context" $) | nindent 10 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" .Values.alertmanager.persistence "global" .Values.global) | nindent 8 }} + {{- end }} +{{- end }} diff --git a/backing-services/prometheus/templates/extra-list.yaml b/backing-services/prometheus/templates/extra-list.yaml new file mode 100644 index 0000000..2d35a58 --- /dev/null +++ b/backing-services/prometheus/templates/extra-list.yaml @@ -0,0 +1,9 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/backing-services/prometheus/templates/server/clusterrole.yaml b/backing-services/prometheus/templates/server/clusterrole.yaml new file mode 100644 index 0000000..da65fb7 --- /dev/null +++ b/backing-services/prometheus/templates/server/clusterrole.yaml @@ -0,0 +1,51 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.server.rbac.create }} +kind: ClusterRole +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ include "prometheus.server.fullname.namespace" . }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: server + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: + # These rules come from + - apiGroups: + - "" + resources: + - nodes + - nodes/proxy + - nodes/metrics + - services + - endpoints + - pods + - ingresses + - configmaps + verbs: + - get + - list + - watch + - apiGroups: + - "extensions" + - "networking.k8s.io" + resources: + - ingresses/status + - ingresses + verbs: + - get + - list + - watch + - nonResourceURLs: + - "/metrics" + verbs: + - get + {{- if .Values.server.rbac.rules }} + {{- include "common.tplvalues.render" ( dict "value" .Values.server.rbac.rules "context" $ ) | nindent 2 }} + {{- end }} +{{- end }} diff --git a/backing-services/prometheus/templates/server/clusterrolebinding.yaml b/backing-services/prometheus/templates/server/clusterrolebinding.yaml new file mode 100644 index 0000000..e4b3583 --- /dev/null +++ b/backing-services/prometheus/templates/server/clusterrolebinding.yaml @@ -0,0 +1,25 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.server.rbac.create }} +kind: ClusterRoleBinding +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ template "prometheus.server.fullname.namespace" . }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: server + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "prometheus.server.fullname.namespace" . }} +subjects: + - kind: ServiceAccount + name: {{ template "prometheus.server.serviceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} +{{- end }} diff --git a/backing-services/prometheus/templates/server/configmap.yaml b/backing-services/prometheus/templates/server/configmap.yaml new file mode 100644 index 0000000..36d64f7 --- /dev/null +++ b/backing-services/prometheus/templates/server/configmap.yaml @@ -0,0 +1,23 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if not .Values.existingConfigmap }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "prometheus.server.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: server + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + {{ include "prometheus.server.configmapKey" . }}: + {{- include "common.tplvalues.render" (dict "value" .Values.server.configuration "context" $) | toYaml | nindent 4 }} + rules.yaml: + {{- include "common.tplvalues.render" (dict "value" .Values.server.alertingRules "context" $) | toYaml | nindent 4 }} +{{- end }} diff --git a/backing-services/prometheus/templates/server/deployment.yaml b/backing-services/prometheus/templates/server/deployment.yaml new file mode 100644 index 0000000..4cff5c9 --- /dev/null +++ b/backing-services/prometheus/templates/server/deployment.yaml @@ -0,0 +1,274 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} +kind: Deployment +metadata: + name: {{ template "prometheus.server.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: server + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.server.replicaCount }} + {{- if .Values.server.updateStrategy }} + strategy: {{- toYaml .Values.server.updateStrategy | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.server.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: server + template: + metadata: + annotations: + checksum/configmap: {{ include (print $.Template.BasePath "/server/configmap.yaml") . | sha256sum }} + {{- if .Values.server.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.podAnnotations "context" $) | nindent 8 }} + {{- end }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: server + spec: + serviceAccountName: {{ template "prometheus.server.serviceAccountName" . }} + {{- include "prometheus.imagePullSecrets" . | nindent 6 }} + {{- if .Values.server.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.server.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.server.affinity }} + affinity: {{- include "common.tplvalues.render" ( dict "value" .Values.server.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.server.podAffinityPreset "component" "server" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.server.podAntiAffinityPreset "component" "server" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.server.nodeAffinityPreset.type "key" .Values.server.nodeAffinityPreset.key "values" .Values.server.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.server.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" ( dict "value" .Values.server.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.server.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.server.tolerations "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.server.priorityClassName }} + priorityClassName: {{ .Values.server.priorityClassName | quote }} + {{- end }} + {{- if .Values.server.schedulerName }} + schedulerName: {{ .Values.server.schedulerName | quote }} + {{- end }} + {{- if .Values.server.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.server.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.server.podSecurityContext.enabled }} + securityContext: {{- omit .Values.server.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.server.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.server.terminationGracePeriodSeconds }} + {{- end }} + initContainers: + {{- if and .Values.volumePermissions.enabled .Values.server.persistence.enabled }} + - name: volume-permissions + image: {{ include "prometheus.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - sh + - -ec + - | + mkdir -p {{ .Values.server.persistence.mountPath }} + find {{ .Values.server.persistence.mountPath }} -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | xargs -r chown -R {{ .Values.server.containerSecurityContext.runAsUser }}:{{ .Values.server.podSecurityContext.fsGroup }} + securityContext: {{- include "common.tplvalues.render" (dict "value" .Values.volumePermissions.containerSecurityContext "context" $) | nindent 12 }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: data + mountPath: {{ .Values.server.persistence.mountPath }} + {{- if .Values.server.persistence.subPath }} + subPath: {{ .Values.server.persistence.subPath }} + {{- end }} + {{- end }} + {{- if .Values.server.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.initContainers "context" $) | nindent 8 }} + {{- end }} + containers: + - name: prometheus + image: {{ template "prometheus.server.image" . }} + imagePullPolicy: {{ .Values.server.image.pullPolicy }} + {{- if .Values.server.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.server.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.server.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.server.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.server.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.server.args "context" $) | nindent 12 }} + {{- else }} + args: + - "--config.file=/opt/bitnami/prometheus/conf/{{ include "prometheus.server.configmapKey" . }}" + - "--storage.tsdb.path={{ .Values.server.persistence.mountPath }}" + - "--storage.tsdb.retention.time={{ .Values.server.retention }}" + - "--storage.tsdb.retention.size={{ .Values.server.retentionSize }}" + - "--log.level={{ .Values.server.logLevel }}" + - "--log.format={{ .Values.server.logFormat }}" + - "--web.listen-address=:{{ .Values.server.containerPorts.http }}" + - "--web.console.libraries=/opt/bitnami/prometheus/conf/console_libraries" + - "--web.console.templates=/opt/bitnami/prometheus/conf/consoles" + {{- if .Values.server.enableAdminAPI}} + - "--web.enable-admin-api" + {{- end }} + {{- if .Values.server.enableRemoteWriteReceiver }} + - "--web.enable-remote-write-receiver" + {{- end }} + {{- if .Values.server.routePrefix }} + - "--web.route-prefix={{ .Values.server.routePrefix }}" + {{- end }} + {{- if .Values.server.enableFeatures }} + - "--enable-feature={{ join "," .Values.server.enableFeatures }}" + {{- end }} + {{- if .Values.server.extraArgs }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.extraArgs "context" $) | nindent 12 }} + {{- end }} + {{- end }} + env: + {{- if .Values.server.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.server.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.server.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.server.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.server.extraEnvVarsSecret "context" $) }} + {{- end }} + {{- if .Values.server.resources }} + resources: {{- toYaml .Values.server.resources | nindent 12 }} + {{- end }} + ports: + - name: http + containerPort: {{ .Values.server.containerPorts.http }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.server.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.server.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.server.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.server.livenessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: /-/healthy + port: http + {{- end }} + {{- if .Values.server.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.server.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.server.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.server.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: /-/ready + port: http + {{- end }} + {{- if .Values.server.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.server.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.server.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.server.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: http + {{- end }} + {{- end }} + {{- if .Values.server.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.server.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + volumeMounts: + - name: config + mountPath: /opt/bitnami/prometheus/conf + readOnly: true + - name: data + mountPath: {{ .Values.server.persistence.mountPath }} + {{- if .Values.server.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.server.thanos.create }} + - name: thanos-sidecar + image: {{ template "prometheus.server.thanosImage" . }} + imagePullPolicy: {{ .Values.server.thanos.image.pullPolicy }} + args: + - sidecar + - --prometheus.url={{ default "http://localhost:9090" .Values.server.thanos.prometheusUrl }} + - --grpc-address=0.0.0.0:10901 + - --http-address=0.0.0.0:10902 + - --tsdb.path=/prometheus/ + {{- if .Values.server.thanos.objectStorageConfig.secretName }} + - --objstore.config=$(OBJSTORE_CONFIG) + {{- end }} + {{- if .Values.server.thanos.extraArgs }} + {{ toYaml .Values.server.thanos.extraArgs | indent 12 | trim }} + {{- end }} + {{- if .Values.server.thanos.objectStorageConfig.secretName }} + env: + - name: OBJSTORE_CONFIG + valueFrom: + secretKeyRef: + name: {{ .Values.server.thanos.objectStorageConfig.secretName }} + key: {{ .Values.server.thanos.objectStorageConfig.secretKey | default "thanos.yaml" }} + {{- end }} + {{- if .Values.server.thanos.resources }} + resources: {{- toYaml .Values.server.thanos.resources | nindent 12 }} + {{- end }} + ports: + - name: grpc + containerPort: 10901 + protocol: TCP + - name: http + containerPort: 10902 + protocol: TCP + volumeMounts: + - mountPath: /prometheus + name: data + {{- if .Values.server.thanos.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.thanos.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.server.thanos.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.server.thanos.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.server.thanos.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.server.thanos.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.server.thanos.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.server.thanos.livenessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: /-/healthy + port: http + scheme: HTTP + {{- end }} + {{- if .Values.server.thanos.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.server.thanos.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.server.thanos.livenessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.server.thanos.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: /-/ready + port: http + scheme: HTTP + {{- end }} + {{- end }} + {{- if .Values.server.sidecars }} + {{- include "common.tplvalues.render" ( dict "value" .Values.server.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: config + configMap: + name: {{ include "prometheus.server.configmapName" . }} + - name: data + {{- if .Values.server.persistence.enabled }} + persistentVolumeClaim: + claimName: {{ default (include "prometheus.server.fullname" .) .Values.server.persistence.existingClaim }} + {{- else }} + emptyDir: {} + {{- end }} + {{- if .Values.server.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.extraVolumes "context" $) | nindent 8 }} + {{- end }} diff --git a/backing-services/prometheus/templates/server/ingress.yaml b/backing-services/prometheus/templates/server/ingress.yaml new file mode 100644 index 0000000..9b8e073 --- /dev/null +++ b/backing-services/prometheus/templates/server/ingress.yaml @@ -0,0 +1,61 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.server.ingress.enabled }} +apiVersion: {{ include "common.capabilities.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ template "prometheus.server.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: alertmanager + {{- if or .Values.server.ingress.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.server.ingress.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.server.ingress.ingressClassName (eq "true" (include "common.ingress.supportsIngressClassname" .)) }} + ingressClassName: {{ .Values.server.ingress.ingressClassName | quote }} + {{- end }} + rules: + {{- if .Values.server.ingress.hostname }} + - host: {{ .Values.server.ingress.hostname }} + http: + paths: + {{- if .Values.server.ingress.extraPaths }} + {{- toYaml .Values.server.ingress.extraPaths | nindent 10 }} + {{- end }} + - path: {{ .Values.server.ingress.path }} + {{- if eq "true" (include "common.ingress.supportsPathType" .) }} + pathType: {{ .Values.server.ingress.pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "prometheus.server.fullname" .) "servicePort" "http" "context" $) | nindent 14 }} + {{- end }} + {{- range .Values.server.ingress.extraHosts }} + - host: {{ .name | quote }} + http: + paths: + - path: {{ default "/" .path }} + {{- if eq "true" (include "common.ingress.supportsPathType" $) }} + pathType: {{ default "ImplementationSpecific" .pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "prometheus.server.fullname" $) "servicePort" "http" "context" $) | nindent 14 }} + {{- end }} + {{- if .Values.server.ingress.extraRules }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.ingress.extraRules "context" $) | nindent 4 }} + {{- end }} + {{- if or (and .Values.server.ingress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.server.ingress.annotations )) .Values.server.ingress.selfSigned)) .Values.server.ingress.extraTls }} + tls: + {{- if and .Values.server.ingress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.server.ingress.annotations )) .Values.server.ingress.selfSigned) }} + - hosts: + - {{ .Values.server.ingress.hostname | quote }} + secretName: {{ printf "%s-tls" .Values.server.ingress.hostname }} + {{- end }} + {{- if .Values.server.ingress.extraTls }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.ingress.extraTls "context" $) | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/prometheus/templates/server/pdb.yaml b/backing-services/prometheus/templates/server/pdb.yaml new file mode 100644 index 0000000..9a34462 --- /dev/null +++ b/backing-services/prometheus/templates/server/pdb.yaml @@ -0,0 +1,31 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- $replicaCount := int .Values.replicaCount }} +{{- if and .Values.server.pdb.create (gt $replicaCount 1) }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "prometheus.server.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: server + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.server.pdb.minAvailable }} + minAvailable: {{ .Values.server.pdb.minAvailable }} + {{- end }} + {{- if .Values.server.pdb.maxUnavailable }} + maxUnavailable: {{ .Values.server.pdb.maxUnavailable }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.server.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: server +{{- end }} diff --git a/backing-services/prometheus/templates/server/pvc.yaml b/backing-services/prometheus/templates/server/pvc.yaml new file mode 100644 index 0000000..9f17fd4 --- /dev/null +++ b/backing-services/prometheus/templates/server/pvc.yaml @@ -0,0 +1,34 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.server.persistence.enabled (not .Values.server.persistence.existingClaim) -}} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ include "prometheus.server.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: server + {{- if or .Values.server.persistence.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.server.persistence.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + accessModes: + {{- range .Values.server.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.server.persistence.size | quote }} + {{- if .Values.server.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.server.persistence.selector "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.server.persistence.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.server.persistence.dataSource "context" $) | nindent 4 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" .Values.server.persistence "global" .Values.global) | nindent 2 }} +{{- end -}} diff --git a/backing-services/prometheus/templates/server/service-account.yaml b/backing-services/prometheus/templates/server/service-account.yaml new file mode 100644 index 0000000..1119b0f --- /dev/null +++ b/backing-services/prometheus/templates/server/service-account.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.server.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "prometheus.server.serviceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: server + {{- if or .Values.server.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.server.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.server.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/backing-services/prometheus/templates/server/service.yaml b/backing-services/prometheus/templates/server/service.yaml new file mode 100644 index 0000000..c8a2232 --- /dev/null +++ b/backing-services/prometheus/templates/server/service.yaml @@ -0,0 +1,57 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ template "prometheus.server.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: server + {{- if or .Values.server.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.server.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.server.service.type }} + {{- if and .Values.server.service.clusterIP (eq .Values.server.service.type "ClusterIP") }} + clusterIP: {{ .Values.server.service.clusterIP }} + {{- end }} + {{- if .Values.server.service.sessionAffinity }} + sessionAffinity: {{ .Values.server.service.sessionAffinity }} + {{- end }} + {{- if .Values.server.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.server.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + {{- if or (eq .Values.server.service.type "LoadBalancer") (eq .Values.server.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.server.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.server.service.type "LoadBalancer") (not (empty .Values.server.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ .Values.server.service.loadBalancerSourceRanges }} + {{- end }} + {{- if and (eq .Values.server.service.type "LoadBalancer") (not (empty .Values.server.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.server.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.server.service.type "LoadBalancer") (not (empty .Values.server.service.loadBalancerClass)) }} + loadBalancerClass: {{ .Values.server.service.loadBalancerClass }} + {{- end }} + ports: + - name: http + port: {{ .Values.server.service.ports.http }} + targetPort: http + protocol: TCP + {{- if and (or (eq .Values.server.service.type "NodePort") (eq .Values.server.service.type "LoadBalancer")) (not (empty .Values.server.service.nodePorts.http)) }} + nodePort: {{ .Values.server.service.nodePorts.http }} + {{- else if eq .Values.server.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.server.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.server.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: server diff --git a/backing-services/prometheus/templates/server/thanos-ingress.yaml b/backing-services/prometheus/templates/server/thanos-ingress.yaml new file mode 100644 index 0000000..ece63af --- /dev/null +++ b/backing-services/prometheus/templates/server/thanos-ingress.yaml @@ -0,0 +1,62 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.server.thanos.create .Values.server.thanos.ingress.enabled }} +apiVersion: {{ include "common.capabilities.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ template "prometheus.thanos-sidecar.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: server + app.kubernetes.io/subcomponent: thanos + {{- if or .Values.server.thanos.ingress.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.server.thanos.ingress.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.server.thanos.ingress.ingressClassName (include "common.ingress.supportsIngressClassname" .) }} + ingressClassName: {{ .Values.server.thanos.ingress.ingressClassName | quote }} + {{- end }} + rules: + {{- if .Values.server.thanos.ingress.hostname }} + - host: {{ .Values.server.thanos.ingress.hostname }} + http: + paths: + {{- if .Values.server.thanos.ingress.extraPaths }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.thanos.ingress.extraPaths "context" $) | nindent 10 }} + {{- end }} + - path: {{ .Values.server.thanos.ingress.path }} + {{- if eq "true" (include "common.ingress.supportsPathType" .) }} + pathType: {{ .Values.server.thanos.ingress.pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "prometheus.thanos-sidecar.fullname" $) "servicePort" "grpc" "context" $) | nindent 14 }} + {{- end }} + {{- range .Values.server.thanos.ingress.extraHosts }} + - host: {{ .name | quote }} + http: + paths: + - path: {{ default "/" .path }} + {{- if eq "true" (include "common.ingress.supportsPathType" $) }} + pathType: {{ default "ImplementationSpecific" .pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "prometheus.thanos-sidecar.fullname" $) "servicePort" "grpc" "context" $) | nindent 14 }} + {{- end }} + {{- if .Values.server.thanos.ingress.extraRules }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.thanos.ingress.extraRules "context" $) | nindent 4 }} + {{- end }} + {{- if or (and .Values.server.thanos.ingress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.server.thanos.ingress.annotations )) .Values.server.thanos.ingress.selfSigned)) .Values.server.thanos.ingress.extraTls }} + tls: + {{- if and .Values.server.thanos.ingress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.server.thanos.ingress.annotations )) .Values.server.thanos.ingress.selfSigned) }} + - hosts: + - {{ .Values.server.thanos.ingress.hostname | quote }} + secretName: {{ printf "%s-tls" .Values.server.thanos.ingress.hostname }} + {{- end }} + {{- if .Values.server.thanos.ingress.extraTls }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.thanos.ingress.extraTls "context" $) | nindent 4 }} + {{- end }} + {{- end }} +{{- end -}} diff --git a/backing-services/prometheus/templates/server/thanos-service.yaml b/backing-services/prometheus/templates/server/thanos-service.yaml new file mode 100644 index 0000000..bea2548 --- /dev/null +++ b/backing-services/prometheus/templates/server/thanos-service.yaml @@ -0,0 +1,58 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.server.thanos.create }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "prometheus.thanos-sidecar.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: server + app.kubernetes.io/subcomponent: thanos + {{- if or .Values.server.thanos.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.server.thanos.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.server.thanos.service.type }} + {{- if and (eq .Values.server.thanos.service.type "LoadBalancer") (not (empty .Values.server.thanos.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.server.thanos.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.server.thanos.service.type "LoadBalancer") (not (empty .Values.server.thanos.service.loadBalancerClass)) }} + loadBalancerClass: {{ .Values.server.thanos.service.loadBalancerClass }} + {{- end }} + {{- if and (eq .Values.server.thanos.service.type "LoadBalancer") (not (empty .Values.server.thanos.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ .Values.server.thanos.service.loadBalancerSourceRanges }} + {{- end }} + {{- if and .Values.server.thanos.service.clusterIP (eq .Values.server.thanos.service.type "ClusterIP") }} + clusterIP: {{ .Values.server.thanos.service.clusterIP }} + {{- end }} + {{- if .Values.server.thanos.service.sessionAffinity }} + sessionAffinity: {{ .Values.server.thanos.service.sessionAffinity }} + {{- end }} + {{- if .Values.server.thanos.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.server.thanos.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + {{- if or (eq .Values.server.thanos.service.type "LoadBalancer") (eq .Values.server.thanos.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.server.thanos.service.externalTrafficPolicy | quote }} + {{- end }} + ports: + - name: grpc + port: {{ .Values.server.thanos.service.ports.grpc }} + targetPort: grpc + protocol: TCP + {{- if and .Values.server.thanos.service.nodePorts.grpc (or (eq .Values.server.thanos.service.type "NodePort") (eq .Values.server.thanos.service.type "LoadBalancer")) }} + nodePort: {{ .Values.server.thanos.service.nodePorts.grpc }} + {{- end }} + {{- if .Values.server.thanos.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.thanos.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.server.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: server +{{- end }} diff --git a/backing-services/prometheus/templates/tls-secret.yaml b/backing-services/prometheus/templates/tls-secret.yaml new file mode 100644 index 0000000..22a67a5 --- /dev/null +++ b/backing-services/prometheus/templates/tls-secret.yaml @@ -0,0 +1,138 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if or .Values.server.ingress.enabled + (and .Values.alertmanager.enabled .Values.alertmanager.ingress.enabled) + (and .Values.server.thanos.create .Values.server.thanos.ingress.enabled) }} +{{- if .Values.server.ingress.secrets }} +{{- range .Values.server.ingress.secrets }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .name }} + namespace: {{ include "common.names.namespace" $ | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $.Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: server + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ .certificate | b64enc }} + tls.key: {{ .key | b64enc }} +--- +{{- end }} +{{- end }} +{{- if .Values.alertmanager.ingress.secrets }} +{{- range .Values.alertmanager.ingress.secrets }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .name }} + namespace: {{ include "common.names.namespace" $ | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $.Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: alertmanager + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ .certificate | b64enc }} + tls.key: {{ .key | b64enc }} +--- +{{- end }} +{{- end }} +{{- if .Values.server.thanos.ingress.secrets }} +{{- range .Values.server.thanos.ingress.secrets }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .name }} + namespace: {{ include "common.names.namespace" $ | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $.Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: server + app.kubernetes.io/subcomponent: thanos + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ .certificate | b64enc }} + tls.key: {{ .key | b64enc }} +--- +{{- end }} +{{- end }} +{{- if (or (and .Values.server.ingress.tls .Values.server.ingress.selfSigned) + (and .Values.alertmanager.ingress.tls .Values.alertmanager.ingress.selfSigned) + (and .Values.server.thanos.ingress.tls .Values.server.thanos.ingress.selfSigned)) }} +{{- $ca := genCA "prometheus-ca" 365 }} +{{- if and .Values.server.ingress.tls .Values.server.ingress.selfSigned }} +{{- $secretName := printf "%s-tls" .Values.server.ingress.hostname }} +{{- $cert := genSignedCert .Values.server.ingress.hostname nil (list .Values.server.ingress.hostname) 365 $ca }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: server + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.crt" "defaultValue" $cert.Cert "context" $) }} + tls.key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.key" "defaultValue" $cert.Key "context" $) }} + ca.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }} +--- +{{- end }} +{{- if and .Values.alertmanager.ingress.tls .Values.alertmanager.ingress.selfSigned }} +{{- $secretName := printf "%s-tls" .Values.alertmanager.ingress.hostname }} +{{- $cert := genSignedCert .Values.alertmanager.ingress.hostname nil (list .Values.alertmanager.ingress.hostname) 365 $ca }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: alertmanager + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.crt" "defaultValue" $cert.Cert "context" $) }} + tls.key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.key" "defaultValue" $cert.Key "context" $) }} + ca.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }} +{{- end }} +--- +{{- if and .Values.server.thanos.ingress.tls .Values.server.thanos.ingress.selfSigned }} +{{- $secretName := printf "%s-tls" .Values.server.thanos.ingress.hostname }} +{{- $cert := genSignedCert .Values.server.thanos.ingress.hostname nil (list .Values.server.thanos.ingress.hostname) 365 $ca }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: prometheus + app.kubernetes.io/component: server + app.kubernetes.io/subcomponent: thanos + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.crt" "defaultValue" $cert.Cert "context" $) }} + tls.key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.key" "defaultValue" $cert.Key "context" $) }} + ca.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }} +{{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/prometheus/values.schema.json b/backing-services/prometheus/values.schema.json new file mode 100644 index 0000000..aa0cc46 --- /dev/null +++ b/backing-services/prometheus/values.schema.json @@ -0,0 +1,1954 @@ +{ + "title": "Chart Values", + "type": "object", + "properties": { + "global": { + "type": "object", + "properties": { + "imageRegistry": { + "type": "string", + "description": "Global Docker image registry", + "default": "" + }, + "imagePullSecrets": { + "type": "array", + "description": "Global Docker registry secret names as an array", + "default": [], + "items": {} + }, + "storageClass": { + "type": "string", + "description": "Global StorageClass for Persistent Volume(s)", + "default": "" + } + } + }, + "kubeVersion": { + "type": "string", + "description": "Override Kubernetes version", + "default": "" + }, + "nameOverride": { + "type": "string", + "description": "String to partially override common.names.name", + "default": "" + }, + "fullnameOverride": { + "type": "string", + "description": "String to fully override common.names.fullname", + "default": "" + }, + "namespaceOverride": { + "type": "string", + "description": "String to fully override common.names.namespace", + "default": "" + }, + "commonLabels": { + "type": "object", + "description": "Labels to add to all deployed objects", + "default": {} + }, + "commonAnnotations": { + "type": "object", + "description": "Annotations to add to all deployed objects", + "default": {} + }, + "clusterDomain": { + "type": "string", + "description": "Kubernetes cluster domain name", + "default": "cluster.local" + }, + "extraDeploy": { + "type": "array", + "description": "Array of extra objects to deploy with the release", + "default": [], + "items": {} + }, + "diagnosticMode": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable diagnostic mode (all probes will be disabled and the command will be overridden)", + "default": false + }, + "command": { + "type": "array", + "description": "Command to override all containers in the deployment", + "default": [ + "sleep" + ], + "items": { + "type": "string" + } + }, + "args": { + "type": "array", + "description": "Args to override all containers in the deployment", + "default": [ + "infinity" + ], + "items": { + "type": "string" + } + } + } + }, + "ingress": { + "type": "object", + "properties": { + "apiVersion": { + "type": "string", + "description": "Force Ingress API version (automatically detected if not set)", + "default": "" + } + } + }, + "alertmanager": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Alertmanager enabled", + "default": true + }, + "image": { + "type": "object", + "properties": { + "registry": { + "type": "string", + "description": "Alertmanager image registry", + "default": "docker.io" + }, + "repository": { + "type": "string", + "description": "Alertmanager image repository", + "default": "bitnami/alertmanager" + }, + "tag": { + "type": "string", + "description": "Alertmanager image tag (immutable tags are recommended)", + "default": "0.25.0-debian-11-r48" + }, + "digest": { + "type": "string", + "description": "Alertmanager image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag image tag (immutable tags are recommended)", + "default": "" + }, + "pullPolicy": { + "type": "string", + "description": "Alertmanager image pull policy", + "default": "IfNotPresent" + }, + "pullSecrets": { + "type": "array", + "description": "Alertmanager image pull secrets", + "default": [], + "items": {} + } + } + }, + "configuration": { + "type": "string", + "description": "Alertmanager configuration. This content will be stored in the the alertmanager.yaml file and the content can be a template.", + "default": "receivers:\n - name: default-receiver\nroute:\n group_wait: 10s\n group_interval: 5m\n receiver: default-receiver\n repeat_interval: 3h\n" + }, + "replicaCount": { + "type": "number", + "description": "Number of Alertmanager replicas to deploy", + "default": 1 + }, + "containerPorts": { + "type": "object", + "properties": { + "http": { + "type": "number", + "description": "Alertmanager HTTP container port", + "default": 9093 + }, + "cluster": { + "type": "number", + "description": "Alertmanager Cluster HA port", + "default": 9094 + } + } + }, + "livenessProbe": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable livenessProbe on Alertmanager containers", + "default": true + }, + "initialDelaySeconds": { + "type": "number", + "description": "Initial delay seconds for livenessProbe", + "default": 5 + }, + "periodSeconds": { + "type": "number", + "description": "Period seconds for livenessProbe", + "default": 20 + }, + "timeoutSeconds": { + "type": "number", + "description": "Timeout seconds for livenessProbe", + "default": 3 + }, + "failureThreshold": { + "type": "number", + "description": "Failure threshold for livenessProbe", + "default": 3 + }, + "successThreshold": { + "type": "number", + "description": "Success threshold for livenessProbe", + "default": 1 + } + } + }, + "readinessProbe": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable readinessProbe on Alertmanager containers", + "default": true + }, + "initialDelaySeconds": { + "type": "number", + "description": "Initial delay seconds for readinessProbe", + "default": 5 + }, + "periodSeconds": { + "type": "number", + "description": "Period seconds for readinessProbe", + "default": 10 + }, + "timeoutSeconds": { + "type": "number", + "description": "Timeout seconds for readinessProbe", + "default": 2 + }, + "failureThreshold": { + "type": "number", + "description": "Failure threshold for readinessProbe", + "default": 5 + }, + "successThreshold": { + "type": "number", + "description": "Success threshold for readinessProbe", + "default": 1 + } + } + }, + "startupProbe": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable startupProbe on Alertmanager containers", + "default": false + }, + "initialDelaySeconds": { + "type": "number", + "description": "Initial delay seconds for startupProbe", + "default": 2 + }, + "periodSeconds": { + "type": "number", + "description": "Period seconds for startupProbe", + "default": 5 + }, + "timeoutSeconds": { + "type": "number", + "description": "Timeout seconds for startupProbe", + "default": 2 + }, + "failureThreshold": { + "type": "number", + "description": "Failure threshold for startupProbe", + "default": 10 + }, + "successThreshold": { + "type": "number", + "description": "Success threshold for startupProbe", + "default": 1 + } + } + }, + "customLivenessProbe": { + "type": "object", + "description": "Custom livenessProbe that overrides the default one", + "default": {} + }, + "customReadinessProbe": { + "type": "object", + "description": "Custom readinessProbe that overrides the default one", + "default": {} + }, + "customStartupProbe": { + "type": "object", + "description": "Custom startupProbe that overrides the default one", + "default": {} + }, + "resources": { + "type": "object", + "properties": { + "limits": { + "type": "object", + "description": "The resources limits for the Alertmanager containers", + "default": {} + }, + "requests": { + "type": "object", + "description": "The requested resources for the Alertmanager containers", + "default": {} + } + } + }, + "podSecurityContext": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled Alertmanager pods' Security Context", + "default": true + }, + "fsGroup": { + "type": "number", + "description": "Set Alertmanager pod's Security Context fsGroup", + "default": 1001 + } + } + }, + "containerSecurityContext": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled Alertmanager containers' Security Context", + "default": true + }, + "runAsUser": { + "type": "number", + "description": "Set Alertmanager containers' Security Context runAsUser", + "default": 1001 + }, + "runAsNonRoot": { + "type": "boolean", + "description": "Set Alertmanager containers' Security Context runAsNonRoot", + "default": true + }, + "readOnlyRootFilesystem": { + "type": "boolean", + "description": "Set Alertmanager containers' Security Context runAsNonRoot", + "default": false + } + } + }, + "existingConfigmap": { + "type": "string", + "description": "The name of an existing ConfigMap with your custom configuration for Alertmanager", + "default": "" + }, + "existingConfigmapKey": { + "type": "string", + "description": "The name of the key with the Alertmanager config file", + "default": "" + }, + "command": { + "type": "array", + "description": "Override default container command (useful when using custom images)", + "default": [], + "items": {} + }, + "args": { + "type": "array", + "description": "Override default container args (useful when using custom images)", + "default": [], + "items": {} + }, + "extraArgs": { + "type": "array", + "description": "Additional arguments passed to the Prometheus server container", + "default": [], + "items": {} + }, + "hostAliases": { + "type": "array", + "description": "Alertmanager pods host aliases", + "default": [], + "items": {} + }, + "podLabels": { + "type": "object", + "description": "Extra labels for Alertmanager pods", + "default": {} + }, + "podAnnotations": { + "type": "object", + "description": "Annotations for Alertmanager pods", + "default": {} + }, + "podAffinityPreset": { + "type": "string", + "description": "Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard`", + "default": "" + }, + "podAntiAffinityPreset": { + "type": "string", + "description": "Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard`", + "default": "soft" + }, + "pdb": { + "type": "object", + "properties": { + "create": { + "type": "boolean", + "description": "Enable/disable a Pod Disruption Budget creation", + "default": false + }, + "minAvailable": { + "type": "number", + "description": "Minimum number/percentage of pods that should remain scheduled", + "default": 1 + }, + "maxUnavailable": { + "type": "string", + "description": "Maximum number/percentage of pods that may be made unavailable", + "default": "" + } + } + }, + "nodeAffinityPreset": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard`", + "default": "" + }, + "key": { + "type": "string", + "description": "Node label key to match. Ignored if `affinity` is set", + "default": "" + }, + "values": { + "type": "array", + "description": "Node label values to match. Ignored if `affinity` is set", + "default": [], + "items": {} + } + } + }, + "affinity": { + "type": "object", + "description": "Affinity for Alertmanager pods assignment", + "default": {} + }, + "nodeSelector": { + "type": "object", + "description": "Node labels for Alertmanager pods assignment", + "default": {} + }, + "tolerations": { + "type": "array", + "description": "Tolerations for Alertmanager pods assignment", + "default": [], + "items": {} + }, + "updateStrategy": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Alertmanager statefulset strategy type", + "default": "RollingUpdate" + } + } + }, + "podManagementPolicy": { + "type": "string", + "description": "Statefulset Pod management policy, it needs to be Parallel to be able to complete the cluster join", + "default": "OrderedReady" + }, + "priorityClassName": { + "type": "string", + "description": "Alertmanager pods' priorityClassName", + "default": "" + }, + "topologySpreadConstraints": { + "type": "array", + "description": "Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template", + "default": [], + "items": {} + }, + "schedulerName": { + "type": "string", + "description": "Name of the k8s scheduler (other than default) for Alertmanager pods", + "default": "" + }, + "terminationGracePeriodSeconds": { + "type": "string", + "description": "Seconds Redmine pod needs to terminate gracefully", + "default": "" + }, + "lifecycleHooks": { + "type": "object", + "description": "for the Alertmanager container(s) to automate configuration before or after startup", + "default": {} + }, + "extraEnvVars": { + "type": "array", + "description": "Array with extra environment variables to add to Alertmanager nodes", + "default": [], + "items": {} + }, + "extraEnvVarsCM": { + "type": "string", + "description": "Name of existing ConfigMap containing extra env vars for Alertmanager nodes", + "default": "" + }, + "extraEnvVarsSecret": { + "type": "string", + "description": "Name of existing Secret containing extra env vars for Alertmanager nodes", + "default": "" + }, + "extraVolumes": { + "type": "array", + "description": "Optionally specify extra list of additional volumes for the Alertmanager pod(s)", + "default": [], + "items": {} + }, + "extraVolumeMounts": { + "type": "array", + "description": "Optionally specify extra list of additional volumeMounts for the Alertmanager container(s)", + "default": [], + "items": {} + }, + "sidecars": { + "type": "array", + "description": "Add additional sidecar containers to the Alertmanager pod(s)", + "default": [], + "items": {} + }, + "initContainers": { + "type": "array", + "description": "Add additional init containers to the Alertmanager pod(s)", + "default": [], + "items": {} + }, + "ingress": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable ingress record generation for Alertmanager", + "default": false + }, + "pathType": { + "type": "string", + "description": "Ingress path type", + "default": "ImplementationSpecific" + }, + "hostname": { + "type": "string", + "description": "Default host for the ingress record", + "default": "alertmanager.prometheus.local" + }, + "ingressClassName": { + "type": "string", + "description": "IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+)", + "default": "" + }, + "path": { + "type": "string", + "description": "Default path for the ingress record", + "default": "/" + }, + "annotations": { + "type": "object", + "description": "Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations.", + "default": {} + }, + "tls": { + "type": "boolean", + "description": "Enable TLS configuration for the host defined at `ingress.hostname` parameter", + "default": false + }, + "selfSigned": { + "type": "boolean", + "description": "Create a TLS secret for this ingress record using self-signed certificates generated by Helm", + "default": false + }, + "extraHosts": { + "type": "array", + "description": "An array with additional hostname(s) to be covered with the ingress record", + "default": [], + "items": {} + }, + "extraPaths": { + "type": "array", + "description": "An array with additional arbitrary paths that may need to be added to the ingress under the main host", + "default": [], + "items": {} + }, + "extraTls": { + "type": "array", + "description": "TLS configuration for additional hostname(s) to be covered with this ingress record", + "default": [], + "items": {} + }, + "secrets": { + "type": "array", + "description": "Custom TLS certificates as secrets", + "default": [], + "items": {} + }, + "extraRules": { + "type": "array", + "description": "Additional rules to be covered with this ingress record", + "default": [], + "items": {} + } + } + }, + "serviceAccount": { + "type": "object", + "properties": { + "create": { + "type": "boolean", + "description": "Specifies whether a ServiceAccount should be created", + "default": true + }, + "name": { + "type": "string", + "description": "The name of the ServiceAccount to use.", + "default": "" + }, + "annotations": { + "type": "object", + "description": "Additional Service Account annotations (evaluated as a template)", + "default": {} + }, + "automountServiceAccountToken": { + "type": "boolean", + "description": "Automount service account token for the server service account", + "default": true + } + } + }, + "service": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Alertmanager service type", + "default": "LoadBalancer" + }, + "ports": { + "type": "object", + "properties": { + "http": { + "type": "number", + "description": "Alertmanager service HTTP port", + "default": 80 + }, + "cluster": { + "type": "number", + "description": "Alertmanager cluster HA port", + "default": 9094 + } + } + }, + "nodePorts": { + "type": "object", + "properties": { + "http": { + "type": "string", + "description": "Node port for HTTP", + "default": "" + } + } + }, + "clusterIP": { + "type": "string", + "description": "Alertmanager service Cluster IP", + "default": "" + }, + "loadBalancerIP": { + "type": "string", + "description": "Alertmanager service Load Balancer IP", + "default": "" + }, + "loadBalancerSourceRanges": { + "type": "array", + "description": "Alertmanager service Load Balancer sources", + "default": [], + "items": {} + }, + "externalTrafficPolicy": { + "type": "string", + "description": "Alertmanager service external traffic policy", + "default": "Cluster" + }, + "annotations": { + "type": "object", + "description": "Additional custom annotations for Alertmanager service", + "default": {} + }, + "extraPorts": { + "type": "array", + "description": "Extra ports to expose in Alertmanager service (normally used with the `sidecars` value)", + "default": [], + "items": {} + }, + "sessionAffinity": { + "type": "string", + "description": "Control where client requests go, to the same pod or round-robin", + "default": "None" + }, + "sessionAffinityConfig": { + "type": "object", + "description": "Additional settings for the sessionAffinity", + "default": {} + } + } + }, + "persistence": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable Alertmanager data persistence using VolumeClaimTemplates", + "default": false + }, + "mountPath": { + "type": "string", + "description": "Path to mount the volume at.", + "default": "/bitnami/alertmanager/data" + }, + "subPath": { + "type": "string", + "description": "The subdirectory of the volume to mount to, useful in dev environments and one PV for multiple services", + "default": "" + }, + "storageClass": { + "type": "string", + "description": "PVC Storage Class for Concourse worker data volume", + "default": "" + }, + "accessModes": { + "type": "array", + "description": "PVC Access Mode for Concourse worker volume", + "default": [ + "ReadWriteOnce" + ], + "items": { + "type": "string" + } + }, + "size": { + "type": "string", + "description": "PVC Storage Request for Concourse worker volume", + "default": "8Gi" + }, + "annotations": { + "type": "object", + "description": "Annotations for the PVC", + "default": {} + }, + "selector": { + "type": "object", + "description": "Selector to match an existing Persistent Volume (this value is evaluated as a template)", + "default": {} + } + } + } + } + }, + "server": { + "type": "object", + "properties": { + "image": { + "type": "object", + "properties": { + "registry": { + "type": "string", + "description": "Prometheus image registry", + "default": "docker.io" + }, + "repository": { + "type": "string", + "description": "Prometheus image repository", + "default": "bitnami/prometheus" + }, + "tag": { + "type": "string", + "description": "Prometheus image tag (immutable tags are recommended)", + "default": "2.44.0-debian-11-r0" + }, + "digest": { + "type": "string", + "description": "Prometheus image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag image tag (immutable tags are recommended)", + "default": "" + }, + "pullPolicy": { + "type": "string", + "description": "Prometheus image pull policy", + "default": "IfNotPresent" + }, + "pullSecrets": { + "type": "array", + "description": "Prometheus image pull secrets", + "default": [], + "items": {} + } + } + }, + "configuration": { + "type": "string", + "description": "Promethus configuration. This content will be stored in the the prometheus.yaml file and the content can be a template.", + "default": "global:\n {{- if .Values.server.scrapeInterval }}\n scrape_interval: {{ .Values.server.scrapeInterval }}\n {{- end }}\n {{- if .Values.server.scrapeTimeout }}\n scrape_timeout: {{ .Values.server.scrapeTimeout }}\n {{- end }}\n {{- if .Values.server.evaluationInterval }}\n evaluation_interval: {{ .Values.server.evaluationInterval }}\n {{- end }}\n external_labels:\n monitor: {{ template \"common.names.fullname\" . }}\n {{- if .Values.server.externalLabels }}\n {{- include \"common.tplvalues.render\" (dict \"value\" .Values.server.externalLabels \"context\" $) | nindent 4 }}\n {{- end }}\n{{- if .Values.server.remoteWrite }}\nremote_write: {{- include \"common.tplvalues.render\" (dict \"value\" .Values.server.remoteWrite \"context\" $) | nindent 4 }}\n{{- end }}\nscrape_configs:\n - job_name: prometheus\n {{- include \"prometheus.scrape_config\" (dict \"component\" \"server\" \"context\" $) | nindent 4 }}\n{{- if .Values.alertmanager.enabled }}\n - job_name: alertmanager\n {{- include \"prometheus.scrape_config\" (dict \"component\" \"alertmanager\" \"context\" $) | nindent 4 }}\n{{- end }}\n{{- if .Values.server.extraScrapeConfigs}}\n{{- include \"common.tplvalues.render\" (dict \"value\" .Values.server.extraScrapeConfigs \"context\" $) | nindent 2 }}\n{{- end }}\n{{- if or .Values.alertmanager.enabled .Values.server.alertingEndpoints}}\nalerting:\n alertmanagers:\n {{- if .Values.server.alertingEndpoints }}\n {{- include \"common.tplvalues.render\" (dict \"value\" .Values.server.alertingEndpoints \"context\" $) | nindent 4 }}\n {{- end }}\n - scheme: HTTP\n static_configs:\n - targets: [ {{ printf \"%s:%d\" (include \"prometheus.alertmanager.fullname\" .) (int .Values.alertmanager.service.ports.http) }}]\nrule_files:\n - rules.yaml\n{{- end }}\n" + }, + "alertingRules": { + "type": "object", + "description": "Prometheus alerting rules. This content will be stored in the the rules.yaml file and the content can be a template.", + "default": {} + }, + "extraScrapeConfigs": { + "type": "array", + "description": "Promethus configuration, useful to declare new scrape_configs. This content will be merged with the 'server.configuration' value and stored in the the prometheus.yaml file.", + "default": [], + "items": {} + }, + "replicaCount": { + "type": "number", + "description": "Number of Prometheus replicas to deploy", + "default": 1 + }, + "containerPorts": { + "type": "object", + "properties": { + "http": { + "type": "number", + "description": "Prometheus HTTP container port", + "default": 9090 + } + } + }, + "livenessProbe": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable livenessProbe on Prometheus containers", + "default": true + }, + "initialDelaySeconds": { + "type": "number", + "description": "Initial delay seconds for livenessProbe", + "default": 5 + }, + "periodSeconds": { + "type": "number", + "description": "Period seconds for livenessProbe", + "default": 20 + }, + "timeoutSeconds": { + "type": "number", + "description": "Timeout seconds for livenessProbe", + "default": 3 + }, + "failureThreshold": { + "type": "number", + "description": "Failure threshold for livenessProbe", + "default": 3 + }, + "successThreshold": { + "type": "number", + "description": "Success threshold for livenessProbe", + "default": 1 + } + } + }, + "readinessProbe": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable readinessProbe on Prometheus containers", + "default": true + }, + "initialDelaySeconds": { + "type": "number", + "description": "Initial delay seconds for readinessProbe", + "default": 5 + }, + "periodSeconds": { + "type": "number", + "description": "Period seconds for readinessProbe", + "default": 10 + }, + "timeoutSeconds": { + "type": "number", + "description": "Timeout seconds for readinessProbe", + "default": 2 + }, + "failureThreshold": { + "type": "number", + "description": "Failure threshold for readinessProbe", + "default": 5 + }, + "successThreshold": { + "type": "number", + "description": "Success threshold for readinessProbe", + "default": 1 + } + } + }, + "startupProbe": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable startupProbe on Prometheus containers", + "default": false + }, + "initialDelaySeconds": { + "type": "number", + "description": "Initial delay seconds for startupProbe", + "default": 2 + }, + "periodSeconds": { + "type": "number", + "description": "Period seconds for startupProbe", + "default": 5 + }, + "timeoutSeconds": { + "type": "number", + "description": "Timeout seconds for startupProbe", + "default": 2 + }, + "failureThreshold": { + "type": "number", + "description": "Failure threshold for startupProbe", + "default": 10 + }, + "successThreshold": { + "type": "number", + "description": "Success threshold for startupProbe", + "default": 1 + } + } + }, + "customLivenessProbe": { + "type": "object", + "description": "Custom livenessProbe that overrides the default one", + "default": {} + }, + "customReadinessProbe": { + "type": "object", + "description": "Custom readinessProbe that overrides the default one", + "default": {} + }, + "customStartupProbe": { + "type": "object", + "description": "Custom startupProbe that overrides the default one", + "default": {} + }, + "resources": { + "type": "object", + "properties": { + "limits": { + "type": "object", + "description": "The resources limits for the Prometheus containers", + "default": {} + }, + "requests": { + "type": "object", + "description": "The requested resources for the Prometheus containers", + "default": {} + } + } + }, + "podSecurityContext": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled Prometheus pods' Security Context", + "default": true + }, + "fsGroup": { + "type": "number", + "description": "Set Prometheus pod's Security Context fsGroup", + "default": 1001 + } + } + }, + "containerSecurityContext": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled Prometheus containers' Security Context", + "default": true + }, + "runAsUser": { + "type": "number", + "description": "Set Prometheus containers' Security Context runAsUser", + "default": 1001 + }, + "runAsNonRoot": { + "type": "boolean", + "description": "Set Prometheus containers' Security Context runAsNonRoot", + "default": true + }, + "readOnlyRootFilesystem": { + "type": "boolean", + "description": "Set Prometheus containers' Security Context runAsNonRoot", + "default": false + } + } + }, + "existingConfigmap": { + "type": "string", + "description": "The name of an existing ConfigMap with your custom configuration for Prometheus", + "default": "" + }, + "existingConfigmapKey": { + "type": "string", + "description": "The name of the key with the Prometheus config file", + "default": "" + }, + "command": { + "type": "array", + "description": "Override default container command (useful when using custom images)", + "default": [], + "items": {} + }, + "args": { + "type": "array", + "description": "Override default container args (useful when using custom images)", + "default": [], + "items": {} + }, + "extraArgs": { + "type": "array", + "description": "Additional arguments passed to the Prometheus server container", + "default": [], + "items": {} + }, + "hostAliases": { + "type": "array", + "description": "Prometheus pods host aliases", + "default": [], + "items": {} + }, + "podLabels": { + "type": "object", + "description": "Extra labels for Prometheus pods", + "default": {} + }, + "podAnnotations": { + "type": "object", + "description": "Annotations for Prometheus pods", + "default": {} + }, + "podAffinityPreset": { + "type": "string", + "description": "Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard`", + "default": "" + }, + "podAntiAffinityPreset": { + "type": "string", + "description": "Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard`", + "default": "soft" + }, + "pdb": { + "type": "object", + "properties": { + "create": { + "type": "boolean", + "description": "Enable/disable a Pod Disruption Budget creation", + "default": false + }, + "minAvailable": { + "type": "number", + "description": "Minimum number/percentage of pods that should remain scheduled", + "default": 1 + }, + "maxUnavailable": { + "type": "string", + "description": "Maximum number/percentage of pods that may be made unavailable", + "default": "" + } + } + }, + "nodeAffinityPreset": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard`", + "default": "" + }, + "key": { + "type": "string", + "description": "Node label key to match. Ignored if `affinity` is set", + "default": "" + }, + "values": { + "type": "array", + "description": "Node label values to match. Ignored if `affinity` is set", + "default": [], + "items": {} + } + } + }, + "affinity": { + "type": "object", + "description": "Affinity for Prometheus pods assignment", + "default": {} + }, + "nodeSelector": { + "type": "object", + "description": "Node labels for Prometheus pods assignment", + "default": {} + }, + "tolerations": { + "type": "array", + "description": "Tolerations for Prometheus pods assignment", + "default": [], + "items": {} + }, + "updateStrategy": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Prometheus deployment strategy type. If persistence is enabled, strategy type should be set to Recreate to avoid dead locks.", + "default": "RollingUpdate" + } + } + }, + "priorityClassName": { + "type": "string", + "description": "Prometheus pods' priorityClassName", + "default": "" + }, + "topologySpreadConstraints": { + "type": "array", + "description": "Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template", + "default": [], + "items": {} + }, + "schedulerName": { + "type": "string", + "description": "Name of the k8s scheduler (other than default) for Prometheus pods", + "default": "" + }, + "terminationGracePeriodSeconds": { + "type": "string", + "description": "Seconds Redmine pod needs to terminate gracefully", + "default": "" + }, + "lifecycleHooks": { + "type": "object", + "description": "for the Prometheus container(s) to automate configuration before or after startup", + "default": {} + }, + "extraEnvVars": { + "type": "array", + "description": "Array with extra environment variables to add to Prometheus nodes", + "default": [], + "items": {} + }, + "extraEnvVarsCM": { + "type": "string", + "description": "Name of existing ConfigMap containing extra env vars for Prometheus nodes", + "default": "" + }, + "extraEnvVarsSecret": { + "type": "string", + "description": "Name of existing Secret containing extra env vars for Prometheus nodes", + "default": "" + }, + "extraVolumes": { + "type": "array", + "description": "Optionally specify extra list of additional volumes for the Prometheus pod(s)", + "default": [], + "items": {} + }, + "extraVolumeMounts": { + "type": "array", + "description": "Optionally specify extra list of additional volumeMounts for the Prometheus container(s)", + "default": [], + "items": {} + }, + "sidecars": { + "type": "array", + "description": "Add additional sidecar containers to the Prometheus pod(s)", + "default": [], + "items": {} + }, + "initContainers": { + "type": "array", + "description": "Add additional init containers to the Prometheus pod(s)", + "default": [], + "items": {} + }, + "routePrefix": { + "type": "string", + "description": "Prefix for the internal routes of web endpoints", + "default": "/" + }, + "remoteWrite": { + "type": "array", + "description": "The remote_write spec configuration for Prometheus", + "default": [], + "items": {} + }, + "scrapeInterval": { + "type": "string", + "description": "Interval between consecutive scrapes. Example: \"1m\"", + "default": "" + }, + "scrapeTimeout": { + "type": "string", + "description": "Interval between consecutive scrapes. Example: \"10s\"", + "default": "" + }, + "evaluationInterval": { + "type": "string", + "description": "Interval between consecutive evaluations. Example: \"1m\"", + "default": "" + }, + "enableAdminAPI": { + "type": "boolean", + "description": "Enable Prometheus adminitrative API", + "default": false + }, + "enableRemoteWriteReceiver": { + "type": "boolean", + "description": "Enable Prometheus to be used as a receiver for the Prometheus remote write protocol.", + "default": false + }, + "enableFeatures": { + "type": "array", + "description": "Enable access to Prometheus disabled features.", + "default": [], + "items": {} + }, + "logLevel": { + "type": "string", + "description": "Log level for Prometheus", + "default": "info" + }, + "logFormat": { + "type": "string", + "description": "Log format for Prometheus", + "default": "logfmt" + }, + "retention": { + "type": "string", + "description": "Metrics retention days", + "default": "10d" + }, + "retentionSize": { + "type": "string", + "description": "Maximum size of metrics", + "default": "0" + }, + "alertingEndpoints": { + "type": "array", + "description": "Alertmanagers to which alerts will be sent", + "default": [], + "items": {} + }, + "externalLabels": { + "type": "object", + "description": "External labels to add to any time series or alerts when communicating with external systems", + "default": {} + }, + "thanos": { + "type": "object", + "properties": { + "create": { + "type": "boolean", + "description": "Create a Thanos sidecar container", + "default": false + }, + "image": { + "type": "object", + "properties": { + "registry": { + "type": "string", + "description": "Thanos image registry", + "default": "docker.io" + }, + "repository": { + "type": "string", + "description": "Thanos image name", + "default": "bitnami/thanos" + }, + "tag": { + "type": "string", + "description": "Thanos image tag", + "default": "0.31.0-scratch-r3" + }, + "digest": { + "type": "string", + "description": "Thanos image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag", + "default": "" + }, + "pullPolicy": { + "type": "string", + "description": "Thanos image pull policy", + "default": "IfNotPresent" + }, + "pullSecrets": { + "type": "array", + "description": "Specify docker-registry secret names as an array", + "default": [], + "items": {} + } + } + }, + "containerSecurityContext": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable container security context", + "default": true + }, + "readOnlyRootFilesystem": { + "type": "boolean", + "description": "mount / (root) as a readonly filesystem", + "default": false + }, + "allowPrivilegeEscalation": { + "type": "boolean", + "description": "Switch privilegeEscalation possibility on or off", + "default": false + }, + "runAsNonRoot": { + "type": "boolean", + "description": "Force the container to run as a non root user", + "default": true + }, + "capabilities": { + "type": "object", + "properties": { + "drop": { + "type": "array", + "description": "Linux Kernel capabilities which should be dropped", + "default": [ + "ALL" + ], + "items": { + "type": "string" + } + } + } + } + } + }, + "prometheusUrl": { + "type": "string", + "description": "Override default prometheus url `http://localhost:9090`", + "default": "" + }, + "extraArgs": { + "type": "array", + "description": "Additional arguments passed to the thanos sidecar container", + "default": [], + "items": {} + }, + "objectStorageConfig": { + "type": "object", + "properties": { + "secretName": { + "type": "string", + "description": "Support mounting a Secret for the objectStorageConfig of the sideCar container.", + "default": "" + }, + "secretKey": { + "type": "string", + "description": "Secret key with the configuration file.", + "default": "thanos.yaml" + } + } + }, + "extraVolumeMounts": { + "type": "array", + "description": "Additional volumeMounts from `server.volumes` for thanos sidecar container", + "default": [], + "items": {} + }, + "resources": { + "type": "object", + "properties": { + "limits": { + "type": "object", + "description": "The resources limits for the Thanos sidecar container", + "default": {} + }, + "requests": { + "type": "object", + "description": "The resources requests for the Thanos sidecar container", + "default": {} + } + } + }, + "livenessProbe": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Turn on and off liveness probe", + "default": true + }, + "initialDelaySeconds": { + "type": "number", + "description": "Delay before liveness probe is initiated", + "default": 0 + }, + "periodSeconds": { + "type": "number", + "description": "How often to perform the probe", + "default": 5 + }, + "timeoutSeconds": { + "type": "number", + "description": "When the probe times out", + "default": 3 + }, + "failureThreshold": { + "type": "number", + "description": "Minimum consecutive failures for the probe", + "default": 120 + }, + "successThreshold": { + "type": "number", + "description": "Minimum consecutive successes for the probe", + "default": 1 + } + } + }, + "readinessProbe": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Turn on and off readiness probe", + "default": true + }, + "initialDelaySeconds": { + "type": "number", + "description": "Delay before readiness probe is initiated", + "default": 0 + }, + "periodSeconds": { + "type": "number", + "description": "How often to perform the probe", + "default": 5 + }, + "timeoutSeconds": { + "type": "number", + "description": "When the probe times out", + "default": 3 + }, + "failureThreshold": { + "type": "number", + "description": "Minimum consecutive failures for the probe", + "default": 120 + }, + "successThreshold": { + "type": "number", + "description": "Minimum consecutive successes for the probe", + "default": 1 + } + } + }, + "customLivenessProbe": { + "type": "object", + "description": "Custom livenessProbe that overrides the default one", + "default": {} + }, + "customReadinessProbe": { + "type": "object", + "description": "Custom readinessProbe that overrides the default one", + "default": {} + }, + "service": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Kubernetes service type", + "default": "ClusterIP" + }, + "ports": { + "type": "object", + "properties": { + "grpc": { + "type": "number", + "description": "Thanos service port", + "default": 10901 + } + } + }, + "clusterIP": { + "type": "string", + "description": "Specific cluster IP when service type is cluster IP. Use `None` to create headless service by default.", + "default": "None" + }, + "nodePorts": { + "type": "object", + "properties": { + "grpc": { + "type": "string", + "description": "Specify the nodePort value for the LoadBalancer and NodePort service types.", + "default": "" + } + } + }, + "loadBalancerIP": { + "type": "string", + "description": "`loadBalancerIP` if service type is `LoadBalancer`", + "default": "" + }, + "loadBalancerSourceRanges": { + "type": "array", + "description": "Address that are allowed when svc is `LoadBalancer`", + "default": [], + "items": {} + }, + "annotations": { + "type": "object", + "description": "Additional annotations for Prometheus service", + "default": {} + }, + "extraPorts": { + "type": "array", + "description": "Additional ports to expose from the Thanos sidecar container", + "default": [], + "items": {} + }, + "externalTrafficPolicy": { + "type": "string", + "description": "Prometheus service external traffic policy", + "default": "Cluster" + }, + "sessionAffinity": { + "type": "string", + "description": "Session Affinity for Kubernetes service, can be \"None\" or \"ClientIP\"", + "default": "None" + }, + "sessionAffinityConfig": { + "type": "object", + "description": "Additional settings for the sessionAffinity", + "default": {} + } + } + }, + "ingress": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable ingress controller resource", + "default": false + }, + "pathType": { + "type": "string", + "description": "Ingress path type", + "default": "ImplementationSpecific" + }, + "hostname": { + "type": "string", + "description": "Default host for the ingress record", + "default": "thanos.prometheus.local" + }, + "path": { + "type": "string", + "description": "Default path for the ingress record", + "default": "/" + }, + "annotations": { + "type": "object", + "description": "Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations.", + "default": {} + }, + "ingressClassName": { + "type": "string", + "description": "IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+)", + "default": "" + }, + "tls": { + "type": "boolean", + "description": "Enable TLS configuration for the host defined at `ingress.hostname` parameter", + "default": false + }, + "selfSigned": { + "type": "boolean", + "description": "Create a TLS secret for this ingress record using self-signed certificates generated by Helm", + "default": false + }, + "extraHosts": { + "type": "array", + "description": "An array with additional hostname(s) to be covered with the ingress record", + "default": [], + "items": {} + }, + "extraPaths": { + "type": "array", + "description": "An array with additional arbitrary paths that may need to be added to the ingress under the main host", + "default": [], + "items": {} + }, + "extraTls": { + "type": "array", + "description": "TLS configuration for additional hostname(s) to be covered with this ingress record", + "default": [], + "items": {} + }, + "secrets": { + "type": "array", + "description": "Custom TLS certificates as secrets", + "default": [], + "items": {} + }, + "extraRules": { + "type": "array", + "description": "The list of additional rules to be added to this ingress record. Evaluated as a template", + "default": [], + "items": {} + } + } + } + } + }, + "ingress": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable ingress record generation for Prometheus", + "default": false + }, + "pathType": { + "type": "string", + "description": "Ingress path type", + "default": "ImplementationSpecific" + }, + "hostname": { + "type": "string", + "description": "Default host for the ingress record", + "default": "server.prometheus.local" + }, + "ingressClassName": { + "type": "string", + "description": "IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+)", + "default": "" + }, + "path": { + "type": "string", + "description": "Default path for the ingress record", + "default": "/" + }, + "annotations": { + "type": "object", + "description": "Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations.", + "default": {} + }, + "tls": { + "type": "boolean", + "description": "Enable TLS configuration for the host defined at `ingress.hostname` parameter", + "default": false + }, + "selfSigned": { + "type": "boolean", + "description": "Create a TLS secret for this ingress record using self-signed certificates generated by Helm", + "default": false + }, + "extraHosts": { + "type": "array", + "description": "An array with additional hostname(s) to be covered with the ingress record", + "default": [], + "items": {} + }, + "extraPaths": { + "type": "array", + "description": "An array with additional arbitrary paths that may need to be added to the ingress under the main host", + "default": [], + "items": {} + }, + "extraTls": { + "type": "array", + "description": "TLS configuration for additional hostname(s) to be covered with this ingress record", + "default": [], + "items": {} + }, + "secrets": { + "type": "array", + "description": "Custom TLS certificates as secrets", + "default": [], + "items": {} + }, + "extraRules": { + "type": "array", + "description": "Additional rules to be covered with this ingress record", + "default": [], + "items": {} + } + } + }, + "serviceAccount": { + "type": "object", + "properties": { + "create": { + "type": "boolean", + "description": "Specifies whether a ServiceAccount should be created", + "default": true + }, + "name": { + "type": "string", + "description": "The name of the ServiceAccount to use.", + "default": "" + }, + "annotations": { + "type": "object", + "description": "Additional Service Account annotations (evaluated as a template)", + "default": {} + }, + "automountServiceAccountToken": { + "type": "boolean", + "description": "Automount service account token for the server service account", + "default": true + } + } + }, + "service": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Prometheus service type", + "default": "LoadBalancer" + }, + "ports": { + "type": "object", + "properties": { + "http": { + "type": "number", + "description": "Prometheus service HTTP port", + "default": 80 + } + } + }, + "nodePorts": { + "type": "object", + "properties": { + "http": { + "type": "string", + "description": "Node port for HTTP", + "default": "" + } + } + }, + "clusterIP": { + "type": "string", + "description": "Prometheus service Cluster IP", + "default": "" + }, + "loadBalancerIP": { + "type": "string", + "description": "Prometheus service Load Balancer IP", + "default": "" + }, + "loadBalancerSourceRanges": { + "type": "array", + "description": "Prometheus service Load Balancer sources", + "default": [], + "items": {} + }, + "externalTrafficPolicy": { + "type": "string", + "description": "Prometheus service external traffic policy", + "default": "Cluster" + }, + "annotations": { + "type": "object", + "description": "Additional custom annotations for Prometheus service", + "default": {} + }, + "extraPorts": { + "type": "array", + "description": "Extra ports to expose in Prometheus service (normally used with the `sidecars` value)", + "default": [], + "items": {} + }, + "sessionAffinity": { + "type": "string", + "description": "Control where client requests go, to the same pod or round-robin. ClientIP by default.", + "default": "ClientIP" + }, + "sessionAffinityConfig": { + "type": "object", + "description": "Additional settings for the sessionAffinity", + "default": {} + } + } + }, + "persistence": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable persistence using Persistent Volume Claims. If you have multiple instances (server.repicacount > 1), please considere using an external storage service like Thanos or Grafana Mimir", + "default": false + }, + "mountPath": { + "type": "string", + "description": "Path to mount the volume at.", + "default": "/bitnami/prometheus/data" + }, + "subPath": { + "type": "string", + "description": "The subdirectory of the volume to mount to, useful in dev environments and one PV for multiple services", + "default": "" + }, + "storageClass": { + "type": "string", + "description": "Storage class of backing PVC", + "default": "" + }, + "annotations": { + "type": "object", + "description": "Persistent Volume Claim annotations", + "default": {} + }, + "accessModes": { + "type": "array", + "description": "Persistent Volume Access Modes", + "default": [ + "ReadWriteOnce" + ], + "items": { + "type": "string" + } + }, + "size": { + "type": "string", + "description": "Size of data volume", + "default": "8Gi" + }, + "existingClaim": { + "type": "string", + "description": "The name of an existing PVC to use for persistence", + "default": "" + }, + "selector": { + "type": "object", + "description": "Selector to match an existing Persistent Volume for WordPress data PVC", + "default": {} + }, + "dataSource": { + "type": "object", + "description": "Custom PVC data source", + "default": {} + } + } + }, + "rbac": { + "type": "object", + "properties": { + "create": { + "type": "boolean", + "description": "Specifies whether RBAC resources should be created", + "default": true + }, + "rules": { + "type": "array", + "description": "Custom RBAC rules to set", + "default": [], + "items": {} + } + } + } + } + }, + "volumePermissions": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable init container that changes the owner/group of the PV mount point to `runAsUser:fsGroup`", + "default": false + }, + "image": { + "type": "object", + "properties": { + "registry": { + "type": "string", + "description": "OS Shell + Utility image registry", + "default": "docker.io" + }, + "repository": { + "type": "string", + "description": "OS Shell + Utility image repository", + "default": "bitnami/os-shell" + }, + "tag": { + "type": "string", + "description": "OS Shell + Utility image tag (immutable tags are recommended)", + "default": "11-debian-11-r2" + }, + "pullPolicy": { + "type": "string", + "description": "OS Shell + Utility image pull policy", + "default": "IfNotPresent" + }, + "pullSecrets": { + "type": "array", + "description": "OS Shell + Utility image pull secrets", + "default": [], + "items": {} + } + } + }, + "resources": { + "type": "object", + "properties": { + "limits": { + "type": "object", + "description": "The resources limits for the init container", + "default": {} + }, + "requests": { + "type": "object", + "description": "The requested resources for the init container", + "default": {} + } + } + }, + "containerSecurityContext": { + "type": "object", + "properties": { + "runAsUser": { + "type": "number", + "description": "Set init container's Security Context runAsUser", + "default": 0 + } + } + } + } + } + } +} diff --git a/backing-services/prometheus/values.yaml b/backing-services/prometheus/values.yaml new file mode 100644 index 0000000..7451756 --- /dev/null +++ b/backing-services/prometheus/values.yaml @@ -0,0 +1,1549 @@ +# Copyright VMware, Inc. +# SPDX-License-Identifier: APACHE-2.0 + +## @section Global parameters +## 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, imagePullSecrets and storageClass +## + +## @param global.imageRegistry Global Docker image registry +## @param global.imagePullSecrets Global Docker registry secret names as an array +## @param global.storageClass Global StorageClass for Persistent Volume(s) +## +global: + imageRegistry: "" + ## E.g. + ## imagePullSecrets: + ## - myRegistryKeySecretName + ## + imagePullSecrets: [] + storageClass: "" + +## @section Common parameters +## + +## @param kubeVersion Override Kubernetes version +## +kubeVersion: "" +## @param nameOverride String to partially override common.names.name +## +nameOverride: "" +## @param fullnameOverride String to fully override common.names.fullname +## +fullnameOverride: "" +## @param namespaceOverride String to fully override common.names.namespace +## +namespaceOverride: "" +## @param commonLabels Labels to add to all deployed objects +## +commonLabels: {} +## @param commonAnnotations Annotations to add to all deployed objects +## +commonAnnotations: {} +## @param clusterDomain Kubernetes cluster domain name +## +clusterDomain: cluster.local +## @param extraDeploy Array of extra objects to deploy with the release +## +extraDeploy: [] + +## Enable diagnostic mode in the deployment +## +diagnosticMode: + ## @param diagnosticMode.enabled Enable diagnostic mode (all probes will be disabled and the command will be overridden) + ## + enabled: false + ## @param diagnosticMode.command Command to override all containers in the deployment + ## + command: + - sleep + ## @param diagnosticMode.args Args to override all containers in the deployment + ## + args: + - infinity +## @param ingress.apiVersion Force Ingress API version (automatically detected if not set) +## +ingress: + apiVersion: "" + +## @section Alertmanager Parameters +## +## Bitnami Alertmanager image +## ref: https://hub.docker.com/r/bitnami/alertmanager/tags/ +## @param alertmanager.enabled Alertmanager enabled +## @param alertmanager.image.registry [default: REGISTRY_NAME] Alertmanager image registry +## @param alertmanager.image.repository [default: REPOSITORY_NAME/alertmanager] Alertmanager image repository +## @skip alertmanager.image.tag Alertmanager image tag (immutable tags are recommended) +## @param alertmanager.image.digest Alertmanager image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag image tag (immutable tags are recommended) +## @param alertmanager.image.pullPolicy Alertmanager image pull policy +## @param alertmanager.image.pullSecrets Alertmanager image pull secrets +## +alertmanager: + enabled: true + image: + registry: docker.io + repository: bitnami/alertmanager + tag: 0.26.0-debian-11-r45 + digest: "" + ## 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + + ## @param alertmanager.configuration [string] Alertmanager configuration. This content will be stored in the the alertmanager.yaml file and the content can be a template. + ## ref: + ## + configuration: | + receivers: + - name: default-receiver + route: + group_wait: 10s + group_interval: 5m + receiver: default-receiver + repeat_interval: 3h + + ## @param alertmanager.replicaCount Number of Alertmanager replicas to deploy + ## + replicaCount: 1 + ## @param alertmanager.containerPorts.http Alertmanager HTTP container port + ## @param alertmanager.containerPorts.cluster Alertmanager Cluster HA port + ## + containerPorts: + http: 9093 + cluster: 9094 + ## Configure extra options for Alertmanager containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param alertmanager.livenessProbe.enabled Enable livenessProbe on Alertmanager containers + ## @param alertmanager.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param alertmanager.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param alertmanager.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param alertmanager.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param alertmanager.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 20 + timeoutSeconds: 3 + failureThreshold: 3 + successThreshold: 1 + ## @param alertmanager.readinessProbe.enabled Enable readinessProbe on Alertmanager containers + ## @param alertmanager.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param alertmanager.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param alertmanager.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param alertmanager.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param alertmanager.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 2 + failureThreshold: 5 + successThreshold: 1 + ## @param alertmanager.startupProbe.enabled Enable startupProbe on Alertmanager containers + ## @param alertmanager.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param alertmanager.startupProbe.periodSeconds Period seconds for startupProbe + ## @param alertmanager.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param alertmanager.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param alertmanager.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 2 + periodSeconds: 5 + timeoutSeconds: 2 + failureThreshold: 10 + successThreshold: 1 + ## @param alertmanager.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param alertmanager.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param alertmanager.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## Alertmanager resource requests and limits + ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## @param alertmanager.resources.limits The resources limits for the Alertmanager containers + ## @param alertmanager.resources.requests The requested resources for the Alertmanager containers + ## + resources: + limits: {} + requests: {} + ## Configure Pods Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param alertmanager.podSecurityContext.enabled Enabled Alertmanager pods' Security Context + ## @param alertmanager.podSecurityContext.fsGroup Set Alertmanager pod's Security Context fsGroup + ## + podSecurityContext: + enabled: true + fsGroup: 1001 + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param alertmanager.containerSecurityContext.enabled Enabled containers' Security Context + ## @param alertmanager.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param alertmanager.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param alertmanager.containerSecurityContext.privileged Set container's Security Context privileged + ## @param alertmanager.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param alertmanager.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param alertmanager.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param alertmanager.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: false + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + + ## @param alertmanager.existingConfigmap The name of an existing ConfigMap with your custom configuration for Alertmanager + ## + existingConfigmap: "" + ## @param alertmanager.existingConfigmapKey The name of the key with the Alertmanager config file + ## + existingConfigmapKey: "" + ## @param alertmanager.command Override default container command (useful when using custom images) + ## + command: [] + ## @param alertmanager.args Override default container args (useful when using custom images) + ## + args: [] + ## @param alertmanager.extraArgs Additional arguments passed to the Prometheus server container + ## extraArgs: + ## - --log.level=debug + ## - --tsdb.path=/data/ + ## + extraArgs: [] + ## @param alertmanager.hostAliases Alertmanager pods host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param alertmanager.podLabels Extra labels for Alertmanager pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param alertmanager.podAnnotations Annotations for Alertmanager pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param alertmanager.podAffinityPreset Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param alertmanager.podAntiAffinityPreset Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Pod Disruption Budget configuration + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb + ## @param alertmanager.pdb.create Enable/disable a Pod Disruption Budget creation + ## @param alertmanager.pdb.minAvailable Minimum number/percentage of pods that should remain scheduled + ## @param alertmanager.pdb.maxUnavailable Maximum number/percentage of pods that may be made unavailable + ## + pdb: + create: false + minAvailable: 1 + maxUnavailable: "" + + ## Node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param alertmanager.nodeAffinityPreset.type Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param alertmanager.nodeAffinityPreset.key Node label key to match. Ignored if `affinity` is set + ## + key: "" + ## @param alertmanager.nodeAffinityPreset.values Node label values to match. Ignored if `affinity` is set + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param alertmanager.affinity Affinity for Alertmanager pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## NOTE: `podAffinityPreset`, `podAntiAffinityPreset`, and `nodeAffinityPreset` will be ignored when it's set + ## + affinity: {} + ## @param alertmanager.nodeSelector Node labels for Alertmanager pods assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + ## @param alertmanager.tolerations Tolerations for Alertmanager pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param alertmanager.updateStrategy.type Alertmanager statefulset strategy type + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## + updateStrategy: + ## StrategyType + ## Can be set to RollingUpdate or OnDelete + ## + type: RollingUpdate + + ## @param alertmanager.podManagementPolicy Statefulset Pod management policy, it needs to be Parallel to be able to complete the cluster join + ## Ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#pod-management-policies + ## + podManagementPolicy: OrderedReady + ## @param alertmanager.priorityClassName Alertmanager pods' priorityClassName + ## + priorityClassName: "" + ## @param alertmanager.topologySpreadConstraints Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#spread-constraints-for-pods + ## + topologySpreadConstraints: [] + ## @param alertmanager.schedulerName Name of the k8s scheduler (other than default) for Alertmanager pods + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param alertmanager.terminationGracePeriodSeconds Seconds Redmine pod needs to terminate gracefully + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods + ## + terminationGracePeriodSeconds: "" + ## @param alertmanager.lifecycleHooks for the Alertmanager container(s) to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param alertmanager.extraEnvVars Array with extra environment variables to add to Alertmanager nodes + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param alertmanager.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for Alertmanager nodes + ## + extraEnvVarsCM: "" + ## @param alertmanager.extraEnvVarsSecret Name of existing Secret containing extra env vars for Alertmanager nodes + ## + extraEnvVarsSecret: "" + ## @param alertmanager.extraVolumes Optionally specify extra list of additional volumes for the Alertmanager pod(s) + ## + extraVolumes: [] + ## @param alertmanager.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the Alertmanager container(s) + ## + extraVolumeMounts: [] + ## @param alertmanager.sidecars Add additional sidecar containers to the Alertmanager pod(s) + ## e.g: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param alertmanager.initContainers Add additional init containers to the Alertmanager pod(s) + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + ## e.g: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## command: ['sh', '-c', 'echo "hello world"'] + ## + initContainers: [] + + ## Alertmanager ingress parameters + ## ref: http://kubernetes.io/docs/user-guide/ingress/ + ## + ingress: + ## @param alertmanager.ingress.enabled Enable ingress record generation for Alertmanager + ## + enabled: false + ## @param alertmanager.ingress.pathType Ingress path type + ## + pathType: ImplementationSpecific + + ## @param alertmanager.ingress.hostname Default host for the ingress record + ## + hostname: alertmanager.prometheus.local + ## @param alertmanager.ingress.ingressClassName IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+) + ## This is supported in Kubernetes 1.18+ and required if you have more than one IngressClass marked as the default for your cluster . + ## ref: https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/ + ## + ingressClassName: "" + ## @param alertmanager.ingress.path Default path for the ingress record + ## NOTE: You may need to set this to '/*' in order to use this with ALB ingress controllers + ## + path: / + ## @param alertmanager.ingress.annotations Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. + ## Use this parameter to set the required annotations for cert-manager, see + ## ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations + ## e.g: + ## annotations: + ## kubernetes.io/ingress.class: nginx + ## cert-manager.io/cluster-issuer: cluster-issuer-name + ## + annotations: {} + ## @param alertmanager.ingress.tls Enable TLS configuration for the host defined at `ingress.hostname` parameter + ## TLS certificates will be retrieved from a TLS secret with name: `{{- printf "%s-tls" .Values.ingress.hostname }}` + ## You can: + ## - Use the `ingress.secrets` parameter to create this TLS secret + ## - Rely on cert-manager to create it by setting the corresponding annotations + ## - Rely on Helm to create self-signed certificates by setting `ingress.selfSigned=true` + ## + tls: false + ## @param alertmanager.ingress.selfSigned Create a TLS secret for this ingress record using self-signed certificates generated by Helm + ## + selfSigned: false + ## @param alertmanager.ingress.extraHosts An array with additional hostname(s) to be covered with the ingress record + ## e.g: + ## extraHosts: + ## - name: prometheus.local + ## path: / + ## + extraHosts: [] + ## @param alertmanager.ingress.extraPaths An array with additional arbitrary paths that may need to be added to the ingress under the main host + ## e.g: + ## extraPaths: + ## - path: /* + ## backend: + ## serviceName: ssl-redirect + ## servicePort: use-annotation + ## + extraPaths: [] + ## @param alertmanager.ingress.extraTls TLS configuration for additional hostname(s) to be covered with this ingress record + ## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#tls + ## e.g: + ## extraTls: + ## - hosts: + ## - prometheus.local + ## secretName: prometheus.local-tls + ## + extraTls: [] + ## @param alertmanager.ingress.secrets Custom TLS certificates as secrets + ## NOTE: 'key' and 'certificate' are expected in PEM format + ## NOTE: 'name' should line up with a 'secretName' set further up + ## If it is not set and you're using cert-manager, this is unneeded, as it will create a secret for you with valid certificates + ## If it is not set and you're NOT using cert-manager either, self-signed certificates will be created valid for 365 days + ## It is also possible to create and manage the certificates outside of this helm chart + ## Please see README.md for more information + ## e.g: + ## secrets: + ## - name: prometheus.local-tls + ## key: |- + ## -----BEGIN RSA PRIVATE KEY----- + ## ... + ## -----END RSA PRIVATE KEY----- + ## certificate: |- + ## -----BEGIN CERTIFICATE----- + ## ... + ## -----END CERTIFICATE----- + ## + secrets: [] + ## @param alertmanager.ingress.extraRules Additional rules to be covered with this ingress record + ## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-rules + ## e.g: + ## extraRules: + ## - host: example.local + ## http: + ## path: / + ## backend: + ## service: + ## name: example-svc + ## port: + ## name: http + ## + extraRules: [] + + ## ServiceAccount configuration + ## + serviceAccount: + ## @param alertmanager.serviceAccount.create Specifies whether a ServiceAccount should be created + ## + create: true + ## @param alertmanager.serviceAccount.name The name of the ServiceAccount to use. + ## If not set and create is true, a name is generated using the common.names.fullname template + ## + name: "" + ## @param alertmanager.serviceAccount.annotations Additional Service Account annotations (evaluated as a template) + ## + annotations: {} + ## @param alertmanager.serviceAccount.automountServiceAccountToken Automount service account token for the server service account + ## + automountServiceAccountToken: true + + ## Alertmanager service parameters + ## + service: + ## @param alertmanager.service.type Alertmanager service type + ## + type: NodePort + ## @param alertmanager.service.ports.http Alertmanager service HTTP port + ## @param alertmanager.service.ports.cluster Alertmanager cluster HA port + ## + ports: + http: 80 + cluster: 9094 + ## Node ports to expose + ## @param alertmanager.service.nodePorts.http Node port for HTTP + ## NOTE: choose port between <30000-32767> + ## + nodePorts: + http: "" + ## @param alertmanager.service.clusterIP Alertmanager service Cluster IP + ## e.g.: + ## clusterIP: None + ## + clusterIP: "" + ## @param alertmanager.service.loadBalancerIP Alertmanager service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerIP: "" + ## @param alertmanager.service.loadBalancerClass Alertmanager service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerClass: "" + ## @param alertmanager.service.loadBalancerSourceRanges Alertmanager service Load Balancer sources + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param alertmanager.service.externalTrafficPolicy Alertmanager service external traffic policy + ## ref http://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param alertmanager.service.annotations Additional custom annotations for Alertmanager service + ## + annotations: {} + ## @param alertmanager.service.extraPorts Extra ports to expose in Alertmanager service (normally used with the `sidecars` value) + ## + extraPorts: [] + ## @param alertmanager.service.sessionAffinity Control where client requests go, to the same pod or round-robin + ## Values: ClientIP or None + ## ref: https://kubernetes.io/docs/user-guide/services/ + ## + sessionAffinity: None + ## @param alertmanager.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + + persistence: + ## @param alertmanager.persistence.enabled Enable Alertmanager data persistence using VolumeClaimTemplates + ## + enabled: false + ## @param alertmanager.persistence.mountPath Path to mount the volume at. + ## + mountPath: /bitnami/alertmanager/data + ## @param alertmanager.persistence.subPath The subdirectory of the volume to mount to, useful in dev environments and one PV for multiple services + ## + subPath: "" + ## @param alertmanager.persistence.storageClass PVC Storage Class for Concourse worker data volume + ## 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: "" + ## @param alertmanager.persistence.accessModes PVC Access Mode for Concourse worker volume + ## + accessModes: + - ReadWriteOnce + ## @param alertmanager.persistence.size PVC Storage Request for Concourse worker volume + ## + size: 8Gi + ## @param alertmanager.persistence.annotations Annotations for the PVC + ## + annotations: {} + ## @param alertmanager.persistence.selector Selector to match an existing Persistent Volume (this value is evaluated as a template) + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + +## @section Prometheus server Parameters +## +## Bitnami Prometheus image +## ref: https://hub.docker.com/r/bitnami/prometheus/tags/ +## @param server.image.registry [default: REGISTRY_NAME] Prometheus image registry +## @param server.image.repository [default: REPOSITORY_NAME/prometheus] Prometheus image repository +## @skip server.image.tag Prometheus image tag (immutable tags are recommended) +## @param server.image.digest Prometheus image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag image tag (immutable tags are recommended) +## @param server.image.pullPolicy Prometheus image pull policy +## @param server.image.pullSecrets Prometheus image pull secrets +## +server: + image: + registry: docker.io + repository: bitnami/prometheus + tag: 2.48.1-debian-11-r0 + digest: "" + ## 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + + ## @param server.configuration [string] Promethus configuration. This content will be stored in the the prometheus.yaml file and the content can be a template. + ## ref: + ## + configuration: | + global: + {{- if .Values.server.scrapeInterval }} + scrape_interval: {{ .Values.server.scrapeInterval }} + {{- end }} + {{- if .Values.server.scrapeTimeout }} + scrape_timeout: {{ .Values.server.scrapeTimeout }} + {{- end }} + {{- if .Values.server.evaluationInterval }} + evaluation_interval: {{ .Values.server.evaluationInterval }} + {{- end }} + external_labels: + monitor: {{ template "common.names.fullname" . }} + {{- if .Values.server.externalLabels }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.externalLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.server.remoteWrite }} + remote_write: {{- include "common.tplvalues.render" (dict "value" .Values.server.remoteWrite "context" $) | nindent 4 }} + {{- end }} + scrape_configs: + - job_name: prometheus + {{- include "prometheus.scrape_config" (dict "component" "server" "context" $) | nindent 4 }} + {{- if .Values.alertmanager.enabled }} + - job_name: alertmanager + {{- include "prometheus.scrape_config" (dict "component" "alertmanager" "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.server.extraScrapeConfigs}} + {{- include "common.tplvalues.render" (dict "value" .Values.server.extraScrapeConfigs "context" $) | nindent 2 }} + {{- end }} + {{- if or .Values.alertmanager.enabled .Values.server.alertingEndpoints}} + alerting: + alertmanagers: + {{- if .Values.server.alertingEndpoints }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.alertingEndpoints "context" $) | nindent 4 }} + {{- end }} + - scheme: HTTP + static_configs: + - targets: [ "{{ printf "%s.%s.svc.%s:%d" (include "prometheus.alertmanager.fullname" .) (include "common.names.namespace" .) .Values.clusterDomain (int .Values.alertmanager.service.ports.http) }}" ] + rule_files: + - rules.yaml + {{- end }} + + + ## @param server.alertingRules Prometheus alerting rules. This content will be stored in the the rules.yaml file and the content can be a template. + ## ref: + ## + alertingRules: {} + ## @param server.extraScrapeConfigs Promethus configuration, useful to declare new scrape_configs. This content will be merged with the 'server.configuration' value and stored in the the prometheus.yaml file. + ## ref: + ## + extraScrapeConfigs: [] + ## @param server.replicaCount Number of Prometheus replicas to deploy + ## + replicaCount: 1 + ## @param server.containerPorts.http Prometheus HTTP container port + ## + containerPorts: + http: 9090 + ## Configure extra options for Prometheus containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param server.livenessProbe.enabled Enable livenessProbe on Prometheus containers + ## @param server.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param server.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param server.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param server.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param server.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 20 + timeoutSeconds: 3 + failureThreshold: 3 + successThreshold: 1 + ## @param server.readinessProbe.enabled Enable readinessProbe on Prometheus containers + ## @param server.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param server.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param server.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param server.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param server.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 2 + failureThreshold: 5 + successThreshold: 1 + ## @param server.startupProbe.enabled Enable startupProbe on Prometheus containers + ## @param server.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param server.startupProbe.periodSeconds Period seconds for startupProbe + ## @param server.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param server.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param server.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 2 + periodSeconds: 5 + timeoutSeconds: 2 + failureThreshold: 10 + successThreshold: 1 + ## @param server.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param server.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param server.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## Prometheus resource requests and limits + ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## @param server.resources.limits The resources limits for the Prometheus containers + ## @param server.resources.requests The requested resources for the Prometheus containers + ## + resources: + limits: {} + requests: {} + ## Configure Pods Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param server.podSecurityContext.enabled Enabled Prometheus pods' Security Context + ## @param server.podSecurityContext.fsGroup Set Prometheus pod's Security Context fsGroup + ## + podSecurityContext: + enabled: true + fsGroup: 1001 + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param server.containerSecurityContext.enabled Enabled containers' Security Context + ## @param server.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param server.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param server.containerSecurityContext.privileged Set container's Security Context privileged + ## @param server.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param server.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param server.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param server.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: false + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + + ## @param server.existingConfigmap The name of an existing ConfigMap with your custom configuration for Prometheus + ## + existingConfigmap: "" + ## @param server.existingConfigmapKey The name of the key with the Prometheus config file + ## + existingConfigmapKey: "" + ## @param server.command Override default container command (useful when using custom images) + ## + command: [] + ## @param server.args Override default container args (useful when using custom images) + ## + args: [] + ## @param server.extraArgs Additional arguments passed to the Prometheus server container + ## extraArgs: + ## - --log.level=debug + ## - --tsdb.path=/data/ + ## + extraArgs: [] + ## @param server.hostAliases Prometheus pods host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param server.podLabels Extra labels for Prometheus pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param server.podAnnotations Annotations for Prometheus pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param server.podAffinityPreset Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param server.podAntiAffinityPreset Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Pod Disruption Budget configuration + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb + ## @param server.pdb.create Enable/disable a Pod Disruption Budget creation + ## @param server.pdb.minAvailable Minimum number/percentage of pods that should remain scheduled + ## @param server.pdb.maxUnavailable Maximum number/percentage of pods that may be made unavailable + ## + pdb: + create: false + minAvailable: 1 + maxUnavailable: "" + ## Node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param server.nodeAffinityPreset.type Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param server.nodeAffinityPreset.key Node label key to match. Ignored if `affinity` is set + ## + key: "" + ## @param server.nodeAffinityPreset.values Node label values to match. Ignored if `affinity` is set + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param server.affinity Affinity for Prometheus pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## NOTE: `podAffinityPreset`, `podAntiAffinityPreset`, and `nodeAffinityPreset` will be ignored when it's set + ## + affinity: {} + ## @param server.nodeSelector Node labels for Prometheus pods assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + ## @param server.tolerations Tolerations for Prometheus pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param server.updateStrategy.type Prometheus deployment strategy type. If persistence is enabled, strategy type should be set to Recreate to avoid dead locks. + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy + ## + updateStrategy: + ## StrategyType + ## Can be set to RollingUpdate or Recreate + ## + type: RollingUpdate + + ## @param server.priorityClassName Prometheus pods' priorityClassName + ## + priorityClassName: "" + ## @param server.topologySpreadConstraints Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#spread-constraints-for-pods + ## + topologySpreadConstraints: [] + ## @param server.schedulerName Name of the k8s scheduler (other than default) for Prometheus pods + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param server.terminationGracePeriodSeconds Seconds Redmine pod needs to terminate gracefully + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods + ## + terminationGracePeriodSeconds: "" + ## @param server.lifecycleHooks for the Prometheus container(s) to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param server.extraEnvVars Array with extra environment variables to add to Prometheus nodes + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param server.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for Prometheus nodes + ## + extraEnvVarsCM: "" + ## @param server.extraEnvVarsSecret Name of existing Secret containing extra env vars for Prometheus nodes + ## + extraEnvVarsSecret: "" + ## @param server.extraVolumes Optionally specify extra list of additional volumes for the Prometheus pod(s) + ## + extraVolumes: [] + ## @param server.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the Prometheus container(s) + ## + extraVolumeMounts: [] + ## @param server.sidecars Add additional sidecar containers to the Prometheus pod(s) + ## e.g: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param server.initContainers Add additional init containers to the Prometheus pod(s) + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + ## e.g: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## command: ['sh', '-c', 'echo "hello world"'] + ## + initContainers: [] + ## @param server.routePrefix Prefix for the internal routes of web endpoints + ##  + routePrefix: / + ## @param server.remoteWrite The remote_write spec configuration for Prometheus + ## + remoteWrite: [] + ## @param server.scrapeInterval Interval between consecutive scrapes. Example: "1m" + ## + scrapeInterval: "" + ## @param server.scrapeTimeout Interval between consecutive scrapes. Example: "10s" + ##  + scrapeTimeout: "" + ## @param server.evaluationInterval Interval between consecutive evaluations. Example: "1m" + ## + evaluationInterval: "" + ## @param server.enableAdminAPI Enable Prometheus adminitrative API + ## ref: https://prometheus.io/docs/prometheus/latest/querying/api/#tsdb-admin-apis + ## + enableAdminAPI: false + ## @param server.enableRemoteWriteReceiver Enable Prometheus to be used as a receiver for the Prometheus remote write protocol. + ## + enableRemoteWriteReceiver: false + ## @param server.enableFeatures Enable access to Prometheus disabled features. + ## ref: https://prometheus.io/docs/prometheus/latest/disabled_features/ + ## + enableFeatures: [] + ## @param server.logLevel Log level for Prometheus + ## + logLevel: info + ## @param server.logFormat Log format for Prometheus + ## + logFormat: logfmt + ## @param server.retention Metrics retention days + ## + retention: 10d + ## @param server.retentionSize Maximum size of metrics + ## + retentionSize: "0" + ## @param server.alertingEndpoints Alertmanagers to which alerts will be sent + ## ref: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#alertmanager_config + ## + alertingEndpoints: [] + ## @param server.externalLabels External labels to add to any time series or alerts when communicating with external systems + ## + externalLabels: {} + + ## Thanos sidecar container configuration + ## + thanos: + ## @param server.thanos.create Create a Thanos sidecar container + ## + create: false + ## Bitnami Thanos image + ## ref: https://hub.docker.com/r/bitnami/thanos/tags/ + ## @param server.thanos.image.registry [default: REGISTRY_NAME] Thanos image registry + ## @param server.thanos.image.repository [default: REPOSITORY_NAME/thanos] Thanos image name + ## @skip server.thanos.image.tag Thanos image tag + ## @param server.thanos.image.digest Thanos image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param server.thanos.image.pullPolicy Thanos image pull policy + ## @param server.thanos.image.pullSecrets Specify docker-registry secret names as an array + ## + image: + registry: docker.io + repository: bitnami/thanos + tag: 0.32.5-debian-11-r2 + digest: "" + ## Specify a imagePullPolicy. Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://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/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Thanos Sidecar container's securityContext + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param server.thanos.containerSecurityContext.enabled Enabled containers' Security Context + ## @param server.thanos.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param server.thanos.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param server.thanos.containerSecurityContext.privileged Set container's Security Context privileged + ## @param server.thanos.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param server.thanos.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param server.thanos.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param server.thanos.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: false + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## @param server.thanos.prometheusUrl Override default prometheus url `http://localhost:9090` + ## + prometheusUrl: "" + ## @param server.thanos.extraArgs Additional arguments passed to the thanos sidecar container + ## extraArgs: + ## - --log.level=debug + ## - --tsdb.path=/data/ + ## + extraArgs: [] + ## @param server.thanos.objectStorageConfig.secretName Support mounting a Secret for the objectStorageConfig of the sideCar container. + ## @param server.thanos.objectStorageConfig.secretKey Secret key with the configuration file. + ## ref: https://github.com/thanos-io/thanos/blob/main/docs/storage.md + ## objectStorageConfig: + ## secretName: thanos-objstore-config + ## secretKey: thanos.yaml + ## + objectStorageConfig: + secretName: "" + secretKey: thanos.yaml + ## ref: https://github.com/thanos-io/thanos/blob/main/docs/components/sidecar.md + ## @param server.thanos.extraVolumeMounts Additional volumeMounts from `server.volumes` for thanos sidecar container + ## extraVolumeMounts: + ## - name: my-secret-volume + ## mountPath: /etc/thanos/secrets/my-secret + ## + extraVolumeMounts: [] + ## Thanos sidecar container resource requests and limits. + ## ref: https://kubernetes.io/docs/user-guide/compute-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:'. + ## @param server.thanos.resources.limits The resources limits for the Thanos sidecar container + ## @param server.thanos.resources.requests The resources requests for the Thanos sidecar container + ## + resources: + ## Example: + ## limits: + ## cpu: 100m + ## memory: 128Mi + ## + limits: {} + ## Examples: + ## requests: + ## cpu: 100m + ## memory: 128Mi + ## + requests: {} + ## Configure extra options for liveness probe + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param server.thanos.livenessProbe.enabled Turn on and off liveness probe + ## @param server.thanos.livenessProbe.initialDelaySeconds Delay before liveness probe is initiated + ## @param server.thanos.livenessProbe.periodSeconds How often to perform the probe + ## @param server.thanos.livenessProbe.timeoutSeconds When the probe times out + ## @param server.thanos.livenessProbe.failureThreshold Minimum consecutive failures for the probe + ## @param server.thanos.livenessProbe.successThreshold Minimum consecutive successes for the probe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 0 + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 120 + successThreshold: 1 + ## Configure extra options for readiness probe + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param server.thanos.readinessProbe.enabled Turn on and off readiness probe + ## @param server.thanos.readinessProbe.initialDelaySeconds Delay before readiness probe is initiated + ## @param server.thanos.readinessProbe.periodSeconds How often to perform the probe + ## @param server.thanos.readinessProbe.timeoutSeconds When the probe times out + ## @param server.thanos.readinessProbe.failureThreshold Minimum consecutive failures for the probe + ## @param server.thanos.readinessProbe.successThreshold Minimum consecutive successes for the probe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 0 + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 120 + successThreshold: 1 + ## @param server.thanos.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param server.thanos.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## Thanos Sidecar Service + ## + service: + ## @param server.thanos.service.type Kubernetes service type + ## + type: ClusterIP + ## @param server.thanos.service.ports.grpc Thanos service port + ## + ports: + grpc: 10901 + ## @param server.thanos.service.clusterIP Specific cluster IP when service type is cluster IP. Use `None` to create headless service by default. + ## Use a "headless" service by default so it returns every pod's IP instead of loadbalancing requests. + ## + clusterIP: None + ## @param server.thanos.service.nodePorts.grpc Specify the nodePort value for the LoadBalancer and NodePort service types. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## e.g: + ## nodePort: 30901 + ## + nodePorts: + grpc: "" + ## @param server.thanos.service.loadBalancerIP `loadBalancerIP` if service type is `LoadBalancer` + ## Set the LoadBalancer service type to internal only + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param server.thanos.service.loadBalancerClass Thanos service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerClass: "" + ## @param server.thanos.service.loadBalancerSourceRanges Address that are allowed when svc is `LoadBalancer` + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param server.thanos.service.annotations Additional annotations for Prometheus service + ## + annotations: {} + ## @param server.thanos.service.extraPorts Additional ports to expose from the Thanos sidecar container + ## extraPorts: + ## - name: http + ## port: 10902 + ## targetPort: http + ## protocol: TCP + ## + extraPorts: [] + ## @param server.thanos.service.externalTrafficPolicy Prometheus service external traffic policy + ## ref http://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param server.thanos.service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param server.thanos.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + + ## Configure the ingress resource that allows you to access the + ## Thanos Sidecar installation. Set up the URL + ## ref: https://kubernetes.io/docs/user-guide/ingress/ + ## + ingress: + ## @param server.thanos.ingress.enabled Enable ingress controller resource + ## + enabled: false + ## @param server.thanos.ingress.pathType Ingress path type + ## + pathType: ImplementationSpecific + ## @param server.thanos.ingress.hostname Default host for the ingress record + ## + hostname: thanos.prometheus.local + ## @param server.thanos.ingress.path Default path for the ingress record + ## NOTE: You may need to set this to '/*' in order to use this with ALB ingress controllers + ## + path: / + ## @param server.thanos.ingress.annotations Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. + ## For a full list of possible ingress annotations, please see + ## ref: https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md + ## Use this parameter to set the required annotations for cert-manager, see + ## ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations + ## + ## Examples: + ## kubernetes.io/ingress.class: nginx + ## cert-manager.io/cluster-issuer: cluster-issuer-name + ## + annotations: {} + ## @param server.thanos.ingress.ingressClassName IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+) + ## This is supported in Kubernetes 1.18+ and required if you have more than one IngressClass marked as the default for your cluster . + ## ref: https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/ + ## + ingressClassName: "" + ## @param server.thanos.ingress.tls Enable TLS configuration for the host defined at `ingress.hostname` parameter + ## TLS certificates will be retrieved from a TLS secret with name: `{{- printf "%s-tls" .Values.ingress.hostname }}` + ## You can: + ## - Use the `ingress.secrets` parameter to create this TLS secret + ## - Relay on cert-manager to create it by setting `ingress.certManager=true` + ## - Relay on Helm to create self-signed certificates by setting `ingress.selfSigned=true` + ## + tls: false + ## @param server.thanos.ingress.selfSigned Create a TLS secret for this ingress record using self-signed certificates generated by Helm + ## + selfSigned: false + ## @param server.thanos.ingress.extraHosts An array with additional hostname(s) to be covered with the ingress record + ## e.g: + ## extraHosts: + ## - name: thanos.prometheus.local + ## path: / + ## + extraHosts: [] + ## @param server.thanos.ingress.extraPaths An array with additional arbitrary paths that may need to be added to the ingress under the main host + ## e.g: + ## extraPaths: + ## - path: /* + ## backend: + ## serviceName: ssl-redirect + ## servicePort: use-annotation + ## + extraPaths: [] + ## @param server.thanos.ingress.extraTls TLS configuration for additional hostname(s) to be covered with this ingress record + ## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#tls + ## e.g: + ## extraTls: + ## - hosts: + ## - thanos.prometheus.local + ## secretName: thanos.prometheus.local-tls + ## + extraTls: [] + ## @param server.thanos.ingress.secrets Custom TLS certificates as secrets + ## NOTE: 'key' and 'certificate' are expected in PEM format + ## NOTE: 'name' should line up with a 'secretName' set further up + ## If it is not set and you're using cert-manager, this is unneeded, as it will create a secret for you with valid certificates + ## If it is not set and you're NOT using cert-manager either, self-signed certificates will be created valid for 365 days + ## It is also possible to create and manage the certificates outside of this helm chart + ## Please see README.md for more information + ## e.g: + ## secrets: + ## - name: thanos.prometheus.local-tls + ## key: |- + ## -----BEGIN RSA PRIVATE KEY----- + ## ... + ## -----END RSA PRIVATE KEY----- + ## certificate: |- + ## -----BEGIN CERTIFICATE----- + ## ... + ## -----END CERTIFICATE----- + ## + secrets: [] + ## @param server.thanos.ingress.extraRules The list of additional rules to be added to this ingress record. Evaluated as a template + ## Useful when looking for additional customization, such as using different backend + ## + extraRules: [] + + ## Prometheus Server ingress parameters + ## ref: http://kubernetes.io/docs/user-guide/ingress/ + ## + ingress: + ## @param server.ingress.enabled Enable ingress record generation for Prometheus + ## + enabled: false + ## @param server.ingress.pathType Ingress path type + ## + pathType: ImplementationSpecific + ## @param server.ingress.hostname Default host for the ingress record + ## + hostname: server.prometheus.local + ## @param server.ingress.ingressClassName IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+) + ## This is supported in Kubernetes 1.18+ and required if you have more than one IngressClass marked as the default for your cluster . + ## ref: https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/ + ## + ingressClassName: "" + ## @param server.ingress.path Default path for the ingress record + ## NOTE: You may need to set this to '/*' in order to use this with ALB ingress controllers + ## + path: / + ## @param server.ingress.annotations Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. + ## Use this parameter to set the required annotations for cert-manager, see + ## ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations + ## e.g: + ## annotations: + ## kubernetes.io/ingress.class: nginx + ## cert-manager.io/cluster-issuer: cluster-issuer-name + ## + annotations: {} + ## @param server.ingress.tls Enable TLS configuration for the host defined at `ingress.hostname` parameter + ## TLS certificates will be retrieved from a TLS secret with name: `{{- printf "%s-tls" .Values.ingress.hostname }}` + ## You can: + ## - Use the `ingress.secrets` parameter to create this TLS secret + ## - Rely on cert-manager to create it by setting the corresponding annotations + ## - Rely on Helm to create self-signed certificates by setting `ingress.selfSigned=true` + ## + tls: false + ## @param server.ingress.selfSigned Create a TLS secret for this ingress record using self-signed certificates generated by Helm + ## + selfSigned: false + ## @param server.ingress.extraHosts An array with additional hostname(s) to be covered with the ingress record + ## e.g: + ## extraHosts: + ## - name: prometheus.local + ## path: / + ## + extraHosts: [] + ## @param server.ingress.extraPaths An array with additional arbitrary paths that may need to be added to the ingress under the main host + ## e.g: + ## extraPaths: + ## - path: /* + ## backend: + ## serviceName: ssl-redirect + ## servicePort: use-annotation + ## + extraPaths: [] + ## @param server.ingress.extraTls TLS configuration for additional hostname(s) to be covered with this ingress record + ## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#tls + ## e.g: + ## extraTls: + ## - hosts: + ## - prometheus.local + ## secretName: prometheus.local-tls + ## + extraTls: [] + ## @param server.ingress.secrets Custom TLS certificates as secrets + ## NOTE: 'key' and 'certificate' are expected in PEM format + ## NOTE: 'name' should line up with a 'secretName' set further up + ## If it is not set and you're using cert-manager, this is unneeded, as it will create a secret for you with valid certificates + ## If it is not set and you're NOT using cert-manager either, self-signed certificates will be created valid for 365 days + ## It is also possible to create and manage the certificates outside of this helm chart + ## Please see README.md for more information + ## e.g: + ## secrets: + ## - name: prometheus.local-tls + ## key: |- + ## -----BEGIN RSA PRIVATE KEY----- + ## ... + ## -----END RSA PRIVATE KEY----- + ## certificate: |- + ## -----BEGIN CERTIFICATE----- + ## ... + ## -----END CERTIFICATE----- + ## + secrets: [] + ## @param server.ingress.extraRules Additional rules to be covered with this ingress record + ## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-rules + ## e.g: + ## extraRules: + ## - host: example.local + ## http: + ## path: / + ## backend: + ## service: + ## name: example-svc + ## port: + ## name: http + ## + extraRules: [] + + ## ServiceAccount configuration + ## + serviceAccount: + ## @param server.serviceAccount.create Specifies whether a ServiceAccount should be created + ## + create: true + ## @param server.serviceAccount.name The name of the ServiceAccount to use. + ## If not set and create is true, a name is generated using the common.names.fullname template + ## + name: "" + ## @param server.serviceAccount.annotations Additional Service Account annotations (evaluated as a template) + ## + annotations: {} + ## @param server.serviceAccount.automountServiceAccountToken Automount service account token for the server service account + ## + automountServiceAccountToken: true + + ## Prometheus service parameters + ## + service: + ## @param server.service.type Prometheus service type + ## + type: LoadBalancer + ## @param server.service.ports.http Prometheus service HTTP port + ## + ports: + http: 80 + ## Node ports to expose + ## @param server.service.nodePorts.http Node port for HTTP + ## NOTE: choose port between <30000-32767> + ## + nodePorts: + http: "" + ## @param server.service.clusterIP Prometheus service Cluster IP + ## e.g.: + ## clusterIP: None + ## + clusterIP: "" + ## @param server.service.loadBalancerIP Prometheus service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerIP: "" + ## @param server.service.loadBalancerClass Prometheus service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerClass: "" + ## @param server.service.loadBalancerSourceRanges Prometheus service Load Balancer sources + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param server.service.externalTrafficPolicy Prometheus service external traffic policy + ## ref http://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param server.service.annotations Additional custom annotations for Prometheus service + ## + annotations: {} + ## @param server.service.extraPorts Extra ports to expose in Prometheus service (normally used with the `sidecars` value) + ## + extraPorts: [] + ## @param server.service.sessionAffinity Control where client requests go, to the same pod or round-robin. ClientIP by default. + ## Values: ClientIP or None + ## ref: https://kubernetes.io/docs/user-guide/services/ + ## + sessionAffinity: ClientIP + ## @param server.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + + ## Persistence Parameters + ## + + ## Enable persistence using Persistent Volume Claims + ## ref: https://kubernetes.io/docs/user-guide/persistent-volumes/ + ## + persistence: + ## @param server.persistence.enabled Enable persistence using Persistent Volume Claims. If you have multiple instances (server.repicacount > 1), please considere using an external storage service like Thanos or Grafana Mimir + ## + enabled: false + ## @param server.persistence.mountPath Path to mount the volume at. + ## + mountPath: /bitnami/prometheus/data + ## @param server.persistence.subPath The subdirectory of the volume to mount to, useful in dev environments and one PV for multiple services + ## + subPath: "" + ## @param server.persistence.storageClass Storage class of backing PVC + ## 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: "" + ## @param server.persistence.annotations Persistent Volume Claim annotations + ## + annotations: {} + ## @param server.persistence.accessModes Persistent Volume Access Modes + ## + accessModes: + - ReadWriteOnce + ## @param server.persistence.size Size of data volume + ## + size: 8Gi + ## @param server.persistence.existingClaim The name of an existing PVC to use for persistence + ## + existingClaim: "" + ## @param server.persistence.selector Selector to match an existing Persistent Volume for WordPress data PVC + ## If set, the PVC can't have a PV dynamically provisioned for it + ## E.g. + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## @param server.persistence.dataSource Custom PVC data source + ## + dataSource: {} + + # RBAC configuration + ## + rbac: + ## @param server.rbac.create Specifies whether RBAC resources should be created + ## + create: true + ## @param server.rbac.rules Custom RBAC rules to set + ## e.g: + ## rules: + ## - apiGroups: + ## - "" + ## resources: + ## - pods + ## verbs: + ## - get + ## - list + ## + rules: [] + +## @section Init Container Parameters +## + +## 'volumePermissions' init container parameters +## Changes the owner and group of the persistent volume mount point to runAsUser:fsGroup values +## based on the *podSecurityContext/*containerSecurityContext parameters +## +volumePermissions: + ## @param volumePermissions.enabled Enable init container that changes the owner/group of the PV mount point to `runAsUser:fsGroup` + ## + enabled: false + ## OS Shell + Utility image + ## ref: https://hub.docker.com/r/bitnami/os-shell/tags/ + ## @param volumePermissions.image.registry [default: REGISTRY_NAME] OS Shell + Utility image registry + ## @param volumePermissions.image.repository [default: REPOSITORY_NAME/os-shell] OS Shell + Utility image repository + ## @skip volumePermissions.image.tag OS Shell + Utility image tag (immutable tags are recommended) + ## @param volumePermissions.image.pullPolicy OS Shell + Utility image pull policy + ## @param volumePermissions.image.pullSecrets OS Shell + Utility image pull secrets + ## + image: + registry: docker.io + repository: bitnami/os-shell + tag: 11-debian-11-r92 + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Init container's resource requests and limits + ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## @param volumePermissions.resources.limits The resources limits for the init container + ## @param volumePermissions.resources.requests The requested resources for the init container + ## + resources: + limits: {} + requests: {} + ## Init container Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param volumePermissions.containerSecurityContext.runAsUser Set init container's Security Context runAsUser + ## NOTE: when runAsUser is set to special value "auto", init container will try to chown the + ## data folder to auto-determined user&group, using commands: `id -u`:`id -G | cut -d" " -f2` + ## "auto" is especially useful for OpenShift which has scc with dynamic user ids (and 0 is not allowed) + ## + containerSecurityContext: + runAsUser: 0 diff --git a/backing-services/rabbitmq/.helmignore b/backing-services/rabbitmq/.helmignore new file mode 100644 index 0000000..f0c1319 --- /dev/null +++ b/backing-services/rabbitmq/.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/backing-services/rabbitmq/Chart.lock b/backing-services/rabbitmq/Chart.lock new file mode 100644 index 0000000..07ceb38 --- /dev/null +++ b/backing-services/rabbitmq/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + version: 2.14.1 +digest: sha256:5ccbe5f1fe4459864a8c9d7329c400b678666b6cfb1450818a830bda81995bc3 +generated: "2023-12-22T11:41:05.575256104Z" diff --git a/backing-services/rabbitmq/Chart.yaml b/backing-services/rabbitmq/Chart.yaml new file mode 100644 index 0000000..1c1a575 --- /dev/null +++ b/backing-services/rabbitmq/Chart.yaml @@ -0,0 +1,33 @@ +# Copyright VMware, Inc. +# SPDX-License-Identifier: APACHE-2.0 + +annotations: + category: Infrastructure + licenses: Apache-2.0 + images: | + - name: os-shell + image: docker.io/bitnami/os-shell:11-debian-11-r93 + - name: rabbitmq + image: docker.io/bitnami/rabbitmq:3.12.12-debian-11-r0 +apiVersion: v2 +appVersion: 3.12.12 +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + tags: + - bitnami-common + version: 2.x.x +description: RabbitMQ is an open source general-purpose message broker that is designed for consistent, highly-available messaging scenarios (both synchronous and asynchronous). +home: https://bitnami.com +icon: https://bitnami.com/assets/stacks/rabbitmq/img/rabbitmq-stack-220x234.png +keywords: +- rabbitmq +- message queue +- AMQP +maintainers: +- name: VMware, Inc. + url: https://github.com/bitnami/charts +name: rabbitmq +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/rabbitmq +version: 12.6.2 diff --git a/backing-services/rabbitmq/README.md b/backing-services/rabbitmq/README.md new file mode 100644 index 0000000..bf1d2c4 --- /dev/null +++ b/backing-services/rabbitmq/README.md @@ -0,0 +1,750 @@ + + +# Bitnami package for RabbitMQ + +RabbitMQ is an open source general-purpose message broker that is designed for consistent, highly-available messaging scenarios (both synchronous and asynchronous). + +[Overview of RabbitMQ](https://www.rabbitmq.com) + +Trademarks: This software listing is packaged by Bitnami. The respective trademarks mentioned in the offering are owned by the respective companies, and use of them does not imply any affiliation or endorsement. + +## TL;DR + +```console +helm install my-release oci://registry-1.docker.io/bitnamicharts/rabbitmq +``` + +Looking to use RabbitMQ in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the enterprise edition of Bitnami Application Catalog. + +## Introduction + +This chart bootstraps a [RabbitMQ](https://github.com/bitnami/containers/tree/main/bitnami/rabbitmq) deployment on a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ +- 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 oci://REGISTRY_NAME/REPOSITORY_NAME/rabbitmq +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The command deploys RabbitMQ 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 + +### Global parameters + +| Name | Description | Value | +| ------------------------- | ----------------------------------------------- | ----- | +| `global.imageRegistry` | Global Docker image registry | `""` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | +| `global.storageClass` | Global StorageClass for Persistent Volume(s) | `""` | + +### RabbitMQ Image parameters + +| Name | Description | Value | +| ------------------- | -------------------------------------------------------------------------------------------------------- | -------------------------- | +| `image.registry` | RabbitMQ image registry | `REGISTRY_NAME` | +| `image.repository` | RabbitMQ image repository | `REPOSITORY_NAME/rabbitmq` | +| `image.digest` | RabbitMQ image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `image.pullPolicy` | RabbitMQ image pull policy | `IfNotPresent` | +| `image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `image.debug` | Set to true if you would like to see extra information on logs | `false` | + +### Common parameters + +| Name | Description | Value | +| -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- | +| `nameOverride` | String to partially override rabbitmq.fullname template (will maintain the release name) | `""` | +| `fullnameOverride` | String to fully override rabbitmq.fullname template | `""` | +| `namespaceOverride` | String to fully override common.names.namespace | `""` | +| `kubeVersion` | Force target Kubernetes version (using Helm capabilities if not set) | `""` | +| `clusterDomain` | Kubernetes Cluster Domain | `cluster.local` | +| `extraDeploy` | Array of extra objects to deploy with the release | `[]` | +| `commonAnnotations` | Annotations to add to all deployed objects | `{}` | +| `servicenameOverride` | String to partially override headless service name | `""` | +| `commonLabels` | Labels to add to all deployed objects | `{}` | +| `serviceBindings.enabled` | Create secret for service binding (Experimental) | `false` | +| `enableServiceLinks` | Whether information about services should be injected into pod's environment variable | `true` | +| `diagnosticMode.enabled` | Enable diagnostic mode (all probes will be disabled and the command will be overridden) | `false` | +| `diagnosticMode.command` | Command to override all containers in the deployment | `["sleep"]` | +| `diagnosticMode.args` | Args to override all containers in the deployment | `["infinity"]` | +| `hostAliases` | Deployment pod host aliases | `[]` | +| `dnsPolicy` | DNS Policy for pod | `""` | +| `dnsConfig` | DNS Configuration pod | `{}` | +| `auth.username` | RabbitMQ application username | `user` | +| `auth.password` | RabbitMQ application password | `""` | +| `auth.securePassword` | Whether to set the RabbitMQ password securely. This is incompatible with loading external RabbitMQ definitions and 'true' when not setting the auth.password parameter. | `true` | +| `auth.existingPasswordSecret` | Existing secret with RabbitMQ credentials (must contain a value for `rabbitmq-password` key) | `""` | +| `auth.enableLoopbackUser` | If enabled, the user `auth.username` can only connect from localhost | `false` | +| `auth.erlangCookie` | Erlang cookie to determine whether different nodes are allowed to communicate with each other | `""` | +| `auth.existingErlangSecret` | Existing secret with RabbitMQ Erlang cookie (must contain a value for `rabbitmq-erlang-cookie` key) | `""` | +| `auth.tls.enabled` | Enable TLS support on RabbitMQ | `false` | +| `auth.tls.autoGenerated` | Generate automatically self-signed TLS certificates | `false` | +| `auth.tls.failIfNoPeerCert` | When set to true, TLS connection will be rejected if client fails to provide a certificate | `true` | +| `auth.tls.sslOptionsVerify` | Should [peer verification](https://www.rabbitmq.com/ssl.html#peer-verification) be enabled? | `verify_peer` | +| `auth.tls.sslOptionsPassword.enabled` | Enable usage of password for private Key | `false` | +| `auth.tls.sslOptionsPassword.existingSecret` | Name of existing Secret containing the sslOptionsPassword | `""` | +| `auth.tls.sslOptionsPassword.key` | Enable Key referring to sslOptionsPassword in Secret specified in auth.tls.sslOptionsPassword.existingSecret | `""` | +| `auth.tls.sslOptionsPassword.password` | Use this string as Password. If set, auth.tls.sslOptionsPassword.existingSecret and auth.tls.sslOptionsPassword.key are ignored | `""` | +| `auth.tls.caCertificate` | Certificate Authority (CA) bundle content | `""` | +| `auth.tls.serverCertificate` | Server certificate content | `""` | +| `auth.tls.serverKey` | Server private key content | `""` | +| `auth.tls.existingSecret` | Existing secret with certificate content to RabbitMQ credentials | `""` | +| `auth.tls.existingSecretFullChain` | Whether or not the existing secret contains the full chain in the certificate (`tls.crt`). Will be used in place of `ca.cert` if `true`. | `false` | +| `auth.tls.overrideCaCertificate` | Existing secret with certificate content be mounted instead of the `ca.crt` coming from caCertificate or existingSecret/existingSecretFullChain. | `""` | +| `logs` | Path of the RabbitMQ server's Erlang log file. Value for the `RABBITMQ_LOGS` environment variable | `-` | +| `ulimitNofiles` | RabbitMQ Max File Descriptors | `65536` | +| `maxAvailableSchedulers` | RabbitMQ maximum available scheduler threads | `""` | +| `onlineSchedulers` | RabbitMQ online scheduler threads | `""` | +| `memoryHighWatermark.enabled` | Enable configuring Memory high watermark on RabbitMQ | `false` | +| `memoryHighWatermark.type` | Memory high watermark type. Either `absolute` or `relative` | `relative` | +| `memoryHighWatermark.value` | Memory high watermark value | `0.4` | +| `plugins` | List of default plugins to enable (should only be altered to remove defaults; for additional plugins use `extraPlugins`) | `rabbitmq_management rabbitmq_peer_discovery_k8s` | +| `communityPlugins` | List of Community plugins (URLs) to be downloaded during container initialization | `""` | +| `extraPlugins` | Extra plugins to enable (single string containing a space-separated list) | `rabbitmq_auth_backend_ldap` | +| `clustering.enabled` | Enable RabbitMQ clustering | `true` | +| `clustering.name` | RabbitMQ cluster name | `""` | +| `clustering.addressType` | Switch clustering mode. Either `ip` or `hostname` | `hostname` | +| `clustering.rebalance` | Rebalance master for queues in cluster when new replica is created | `false` | +| `clustering.forceBoot` | Force boot of an unexpectedly shut down cluster (in an unexpected order). | `false` | +| `clustering.partitionHandling` | Switch Partition Handling Strategy. Either `autoheal` or `pause_minority` or `pause_if_all_down` or `ignore` | `autoheal` | +| `loadDefinition.enabled` | Enable loading a RabbitMQ definitions file to configure RabbitMQ | `false` | +| `loadDefinition.file` | Name of the definitions file | `/app/load_definition.json` | +| `loadDefinition.existingSecret` | Existing secret with the load definitions file | `""` | +| `command` | Override default container command (useful when using custom images) | `[]` | +| `args` | Override default container args (useful when using custom images) | `[]` | +| `lifecycleHooks` | Overwrite livecycle for the RabbitMQ container(s) to automate configuration before or after startup | `{}` | +| `terminationGracePeriodSeconds` | Default duration in seconds k8s waits for container to exit before sending kill signal. | `120` | +| `extraEnvVars` | Extra environment variables to add to RabbitMQ pods | `[]` | +| `extraEnvVarsCM` | Name of existing ConfigMap containing extra environment variables | `""` | +| `extraEnvVarsSecret` | Name of existing Secret containing extra environment variables (in case of sensitive data) | `""` | +| `containerPorts.amqp` | | `5672` | +| `containerPorts.amqpTls` | | `5671` | +| `containerPorts.dist` | | `25672` | +| `containerPorts.manager` | | `15672` | +| `containerPorts.epmd` | | `4369` | +| `containerPorts.metrics` | | `9419` | +| `initScripts` | Dictionary of init scripts. Evaluated as a template. | `{}` | +| `initScriptsCM` | ConfigMap with the init scripts. Evaluated as a template. | `""` | +| `initScriptsSecret` | Secret containing `/docker-entrypoint-initdb.d` scripts to be executed at initialization time that contain sensitive data. Evaluated as a template. | `""` | +| `extraContainerPorts` | Extra ports to be included in container spec, primarily informational | `[]` | +| `configuration` | RabbitMQ Configuration file content: required cluster configuration | `""` | +| `tcpListenOptions.backlog` | Maximum size of the unaccepted TCP connections queue | `128` | +| `tcpListenOptions.nodelay` | When set to true, deactivates Nagle's algorithm. Default is true. Highly recommended for most users. | `true` | +| `tcpListenOptions.linger.lingerOn` | Enable Server socket lingering | `true` | +| `tcpListenOptions.linger.timeout` | Server Socket lingering timeout | `0` | +| `tcpListenOptions.keepalive` | When set to true, enables TCP keepalives | `false` | +| `configurationExistingSecret` | Existing secret with the configuration to use as rabbitmq.conf. | `""` | +| `extraConfiguration` | Configuration file content: extra configuration to be appended to RabbitMQ configuration | `""` | +| `extraConfigurationExistingSecret` | Existing secret with the extra configuration to append to `configuration`. | `""` | +| `advancedConfiguration` | Configuration file content: advanced configuration | `""` | +| `advancedConfigurationExistingSecret` | Existing secret with the advanced configuration file (must contain a key `advanced.config`). | `""` | +| `featureFlags` | that controls what features are considered to be enabled or available on all cluster nodes. | `""` | +| `ldap.enabled` | Enable LDAP support | `false` | +| `ldap.uri` | LDAP connection string. | `""` | +| `ldap.servers` | List of LDAP servers hostnames. This is valid only if ldap.uri is not set | `[]` | +| `ldap.port` | LDAP servers port. This is valid only if ldap.uri is not set | `""` | +| `ldap.userDnPattern` | Pattern used to translate the provided username into a value to be used for the LDAP bind. | `""` | +| `ldap.binddn` | DN of the account used to search in the LDAP server. | `""` | +| `ldap.bindpw` | Password for binddn account. | `""` | +| `ldap.basedn` | Base DN path where binddn account will search for the users. | `""` | +| `ldap.uidField` | Field used to match with the user name (uid, samAccountName, cn, etc). It matches with 'dn_lookup_attribute' in RabbitMQ configuration | `""` | +| `ldap.uidField` | Field used to match with the user name (uid, samAccountName, cn, etc). It matches with 'dn_lookup_attribute' in RabbitMQ configuration | `""` | +| `ldap.authorisationEnabled` | Enable LDAP authorisation. Please set 'advancedConfiguration' with tag, topic, resources and vhost mappings | `false` | +| `ldap.tls.enabled` | Enabled TLS configuration. | `false` | +| `ldap.tls.startTls` | Use STARTTLS instead of LDAPS. | `false` | +| `ldap.tls.skipVerify` | Skip any SSL verification (hostanames or certificates) | `false` | +| `ldap.tls.verify` | Verify connection. Valid values are 'verify_peer' or 'verify_none' | `verify_peer` | +| `ldap.tls.certificatesMountPath` | Where LDAP certifcates are mounted. | `/opt/bitnami/rabbitmq/ldap/certs` | +| `ldap.tls.certificatesSecret` | Secret with LDAP certificates. | `""` | +| `ldap.tls.CAFilename` | CA certificate filename. Should match with the CA entry key in the ldap.tls.certificatesSecret. | `""` | +| `ldap.tls.certFilename` | Client certificate filename to authenticate against the LDAP server. Should match with certificate the entry key in the ldap.tls.certificatesSecret. | `""` | +| `ldap.tls.certKeyFilename` | Client Key filename to authenticate against the LDAP server. Should match with certificate the entry key in the ldap.tls.certificatesSecret. | `""` | +| `extraVolumeMounts` | Optionally specify extra list of additional volumeMounts | `[]` | +| `extraVolumes` | Optionally specify extra list of additional volumes . | `[]` | +| `extraSecrets` | Optionally specify extra secrets to be created by the chart. | `{}` | +| `extraSecretsPrependReleaseName` | Set this flag to true if extraSecrets should be created with prepended. | `false` | + +### Statefulset parameters + +| Name | Description | Value | +| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | ---------------- | +| `replicaCount` | Number of RabbitMQ replicas to deploy | `1` | +| `schedulerName` | Use an alternate scheduler, e.g. "stork". | `""` | +| `podManagementPolicy` | Pod management policy | `OrderedReady` | +| `podLabels` | RabbitMQ Pod labels. Evaluated as a template | `{}` | +| `podAnnotations` | RabbitMQ Pod annotations. Evaluated as a template | `{}` | +| `updateStrategy.type` | Update strategy type for RabbitMQ statefulset | `RollingUpdate` | +| `statefulsetLabels` | RabbitMQ statefulset labels. Evaluated as a template | `{}` | +| `statefulsetAnnotations` | RabbitMQ statefulset annotations. Evaluated as a template | `{}` | +| `priorityClassName` | Name of the priority class to be used by RabbitMQ pods, priority class needs to be created beforehand | `""` | +| `podAffinityPreset` | Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `nodeAffinityPreset.type` | Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `nodeAffinityPreset.key` | Node label key to match Ignored if `affinity` is set. | `""` | +| `nodeAffinityPreset.values` | Node label values to match. Ignored if `affinity` is set. | `[]` | +| `affinity` | Affinity for pod assignment. Evaluated as a template | `{}` | +| `nodeSelector` | Node labels for pod assignment. Evaluated as a template | `{}` | +| `tolerations` | Tolerations for pod assignment. Evaluated as a template | `[]` | +| `topologySpreadConstraints` | Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template | `[]` | +| `podSecurityContext.enabled` | Enable RabbitMQ pods' Security Context | `true` | +| `podSecurityContext.fsGroup` | Set RabbitMQ pod's Security Context fsGroup | `1001` | +| `containerSecurityContext.enabled` | Enabled RabbitMQ containers' Security Context | `true` | +| `containerSecurityContext.runAsUser` | Set RabbitMQ containers' Security Context runAsUser | `1001` | +| `containerSecurityContext.runAsNonRoot` | Set RabbitMQ container's Security Context runAsNonRoot | `true` | +| `containerSecurityContext.allowPrivilegeEscalation` | Set container's privilege escalation | `false` | +| `containerSecurityContext.capabilities.drop` | Set container's Security Context runAsNonRoot | `["ALL"]` | +| `containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `resources.limits` | The resources limits for RabbitMQ containers | `{}` | +| `resources.requests` | The requested resources for RabbitMQ containers | `{}` | +| `livenessProbe.enabled` | Enable livenessProbe | `true` | +| `livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `120` | +| `livenessProbe.periodSeconds` | Period seconds for livenessProbe | `30` | +| `livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `20` | +| `livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `readinessProbe.enabled` | Enable readinessProbe | `true` | +| `readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `10` | +| `readinessProbe.periodSeconds` | Period seconds for readinessProbe | `30` | +| `readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `20` | +| `readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `3` | +| `readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `startupProbe.enabled` | Enable startupProbe | `false` | +| `startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `10` | +| `startupProbe.periodSeconds` | Period seconds for startupProbe | `30` | +| `startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `20` | +| `startupProbe.failureThreshold` | Failure threshold for startupProbe | `3` | +| `startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `customLivenessProbe` | Override default liveness probe | `{}` | +| `customReadinessProbe` | Override default readiness probe | `{}` | +| `customStartupProbe` | Define a custom startup probe | `{}` | +| `initContainers` | Add init containers to the RabbitMQ pod | `[]` | +| `sidecars` | Add sidecar containers to the RabbitMQ pod | `[]` | +| `pdb.create` | Enable/disable a Pod Disruption Budget creation | `false` | +| `pdb.minAvailable` | Minimum number/percentage of pods that should remain scheduled | `1` | +| `pdb.maxUnavailable` | Maximum number/percentage of pods that may be made unavailable | `""` | + +### RBAC parameters + +| Name | Description | Value | +| --------------------------------------------- | ------------------------------------------------------------------------------------------ | ------ | +| `serviceAccount.create` | Enable creation of ServiceAccount for RabbitMQ pods | `true` | +| `serviceAccount.name` | Name of the created serviceAccount | `""` | +| `serviceAccount.automountServiceAccountToken` | Auto-mount the service account token in the pod | `true` | +| `serviceAccount.annotations` | Annotations for service account. Evaluated as a template. Only used if `create` is `true`. | `{}` | +| `rbac.create` | Whether RBAC rules should be created | `true` | + +### Persistence parameters + +| Name | Description | Value | +| -------------------------------------------------- | ------------------------------------------------------------------------------ | -------------------------- | +| `persistence.enabled` | Enable RabbitMQ data persistence using PVC | `true` | +| `persistence.storageClass` | PVC Storage Class for RabbitMQ data volume | `""` | +| `persistence.selector` | Selector to match an existing Persistent Volume | `{}` | +| `persistence.accessModes` | PVC Access Modes for RabbitMQ data volume | `["ReadWriteOnce"]` | +| `persistence.existingClaim` | Provide an existing PersistentVolumeClaims | `""` | +| `persistence.mountPath` | The path the volume will be mounted at | `/bitnami/rabbitmq/mnesia` | +| `persistence.subPath` | The subdirectory of the volume to mount to | `""` | +| `persistence.size` | PVC Storage Request for RabbitMQ data volume | `8Gi` | +| `persistence.annotations` | Persistence annotations. Evaluated as a template | `{}` | +| `persistence.labels` | Persistence labels. Evaluated as a template | `{}` | +| `persistentVolumeClaimRetentionPolicy.enabled` | Enable Persistent volume retention policy for rabbitmq Statefulset | `false` | +| `persistentVolumeClaimRetentionPolicy.whenScaled` | Volume retention behavior when the replica count of the StatefulSet is reduced | `Retain` | +| `persistentVolumeClaimRetentionPolicy.whenDeleted` | Volume retention behavior that applies when the StatefulSet is deleted | `Retain` | + +### Exposure parameters + +| Name | Description | Value | +| --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | +| `service.type` | Kubernetes Service type | `ClusterIP` | +| `service.portEnabled` | Amqp port. Cannot be disabled when `auth.tls.enabled` is `false`. Listener can be disabled with `listeners.tcp = none`. | `true` | +| `service.distPortEnabled` | Erlang distribution server port | `true` | +| `service.managerPortEnabled` | RabbitMQ Manager port | `true` | +| `service.epmdPortEnabled` | RabbitMQ EPMD Discovery service port | `true` | +| `service.ports.amqp` | Amqp service port | `5672` | +| `service.ports.amqpTls` | Amqp TLS service port | `5671` | +| `service.ports.dist` | Erlang distribution service port | `25672` | +| `service.ports.manager` | RabbitMQ Manager service port | `15672` | +| `service.ports.metrics` | RabbitMQ Prometheues metrics service port | `9419` | +| `service.ports.epmd` | EPMD Discovery service port | `4369` | +| `service.portNames.amqp` | Amqp service port name | `amqp` | +| `service.portNames.amqpTls` | Amqp TLS service port name | `amqp-tls` | +| `service.portNames.dist` | Erlang distribution service port name | `dist` | +| `service.portNames.manager` | RabbitMQ Manager service port name | `http-stats` | +| `service.portNames.metrics` | RabbitMQ Prometheues metrics service port name | `metrics` | +| `service.portNames.epmd` | EPMD Discovery service port name | `epmd` | +| `service.nodePorts.amqp` | Node port for Ampq | `""` | +| `service.nodePorts.amqpTls` | Node port for Ampq TLS | `""` | +| `service.nodePorts.dist` | Node port for Erlang distribution | `""` | +| `service.nodePorts.manager` | Node port for RabbitMQ Manager | `""` | +| `service.nodePorts.epmd` | Node port for EPMD Discovery | `""` | +| `service.nodePorts.metrics` | Node port for RabbitMQ Prometheues metrics | `""` | +| `service.extraPorts` | Extra ports to expose in the service | `[]` | +| `service.loadBalancerSourceRanges` | Address(es) that are allowed when service is `LoadBalancer` | `[]` | +| `service.allocateLoadBalancerNodePorts` | Whether to allocate node ports when service type is LoadBalancer | `true` | +| `service.externalIPs` | Set the ExternalIPs | `[]` | +| `service.externalTrafficPolicy` | Enable client source IP preservation | `Cluster` | +| `service.loadBalancerIP` | Set the LoadBalancerIP | `""` | +| `service.clusterIP` | Kubernetes service Cluster IP | `""` | +| `service.labels` | Service labels. Evaluated as a template | `{}` | +| `service.annotations` | Service annotations. Evaluated as a template | `{}` | +| `service.annotationsHeadless` | Headless Service annotations. Evaluated as a template | `{}` | +| `service.headless.annotations` | Annotations for the headless service. | `{}` | +| `service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` | +| `service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `ingress.enabled` | Enable ingress resource for Management console | `false` | +| `ingress.path` | Path for the default host. You may need to set this to '/*' in order to use this with ALB ingress controllers. | `/` | +| `ingress.pathType` | Ingress path type | `ImplementationSpecific` | +| `ingress.hostname` | Default host for the ingress resource | `rabbitmq.local` | +| `ingress.annotations` | Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. | `{}` | +| `ingress.tls` | Enable TLS configuration for the hostname defined at `ingress.hostname` parameter | `false` | +| `ingress.selfSigned` | Set this to true in order to create a TLS secret for this ingress record | `false` | +| `ingress.extraHosts` | The list of additional hostnames to be covered with this ingress record. | `[]` | +| `ingress.extraPaths` | An array with additional arbitrary paths that may need to be added to the ingress under the main host | `[]` | +| `ingress.extraRules` | The list of additional rules to be added to this ingress record. Evaluated as a template | `[]` | +| `ingress.extraTls` | The tls configuration for additional hostnames to be covered with this ingress record. | `[]` | +| `ingress.secrets` | Custom TLS certificates as secrets | `[]` | +| `ingress.ingressClassName` | IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+) | `""` | +| `ingress.existingSecret` | It is you own the certificate as secret. | `""` | +| `networkPolicy.enabled` | Enable creation of NetworkPolicy resources | `false` | +| `networkPolicy.allowExternal` | Don't require client label for connections | `true` | +| `networkPolicy.additionalRules` | Additional NetworkPolicy Ingress "from" rules to set. Note that all rules are OR-ed. | `[]` | + +### Metrics Parameters + +| Name | Description | Value | +| ------------------------------------------ | -------------------------------------------------------------------------------------- | --------------------- | +| `metrics.enabled` | Enable exposing RabbitMQ metrics to be gathered by Prometheus | `false` | +| `metrics.plugins` | Plugins to enable Prometheus metrics in RabbitMQ | `rabbitmq_prometheus` | +| `metrics.podAnnotations` | Annotations for enabling prometheus to access the metrics endpoint | `{}` | +| `metrics.serviceMonitor.enabled` | Create ServiceMonitor Resource for scraping metrics using PrometheusOperator | `false` | +| `metrics.serviceMonitor.namespace` | Specify the namespace in which the serviceMonitor resource will be created | `""` | +| `metrics.serviceMonitor.interval` | Specify the interval at which metrics should be scraped | `30s` | +| `metrics.serviceMonitor.scrapeTimeout` | Specify the timeout after which the scrape is ended | `""` | +| `metrics.serviceMonitor.jobLabel` | The name of the label on the target service to use as the job name in prometheus. | `""` | +| `metrics.serviceMonitor.relabelings` | RelabelConfigs to apply to samples before scraping. | `[]` | +| `metrics.serviceMonitor.metricRelabelings` | MetricsRelabelConfigs to apply to samples before ingestion. | `[]` | +| `metrics.serviceMonitor.honorLabels` | honorLabels chooses the metric's labels on collisions with target labels | `false` | +| `metrics.serviceMonitor.targetLabels` | Used to keep given service's labels in target | `{}` | +| `metrics.serviceMonitor.podTargetLabels` | Used to keep given pod's labels in target | `{}` | +| `metrics.serviceMonitor.path` | Define the path used by ServiceMonitor to scrap metrics | `""` | +| `metrics.serviceMonitor.params` | Define the HTTP URL parameters used by ServiceMonitor | `{}` | +| `metrics.serviceMonitor.selector` | ServiceMonitor selector labels | `{}` | +| `metrics.serviceMonitor.labels` | Extra labels for the ServiceMonitor | `{}` | +| `metrics.serviceMonitor.annotations` | Extra annotations for the ServiceMonitor | `{}` | +| `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 | `""` | +| `metrics.prometheusRule.rules` | List of rules, used as template by Helm. | `[]` | + +### Init Container Parameters + +| Name | Description | Value | +| ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | +| `volumePermissions.enabled` | Enable init container that changes the owner and group of the persistent volume(s) mountpoint to `runAsUser:fsGroup` | `false` | +| `volumePermissions.image.registry` | Init container volume-permissions image registry | `REGISTRY_NAME` | +| `volumePermissions.image.repository` | Init container volume-permissions image repository | `REPOSITORY_NAME/os-shell` | +| `volumePermissions.image.digest` | Init container volume-permissions image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `volumePermissions.image.pullPolicy` | Init container volume-permissions image pull policy | `IfNotPresent` | +| `volumePermissions.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `volumePermissions.resources.limits` | Init container volume-permissions resource limits | `{}` | +| `volumePermissions.resources.requests` | Init container volume-permissions resource requests | `{}` | +| `volumePermissions.containerSecurityContext.runAsUser` | User ID for the init container | `0` | + +The above parameters map to the env variables defined in [bitnami/rabbitmq](https://github.com/bitnami/containers/tree/main/bitnami/rabbitmq). For more information please refer to the [bitnami/rabbitmq](https://github.com/bitnami/containers/tree/main/bitnami/rabbitmq) image documentation. + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +helm install my-release \ + --set auth.username=admin,auth.password=secretpassword,auth.erlangCookie=secretcookie \ + oci://REGISTRY_NAME/REPOSITORY_NAME/rabbitmq +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The above command sets the RabbitMQ admin username and password to `admin` and `secretpassword` respectively. Additionally the secure erlang cookie is set to `secretcookie`. + +> NOTE: Once this chart is deployed, it is not possible to change the application's access credentials, such as usernames or passwords, using Helm. To change these application credentials after deployment, delete any persistent volumes (PVs) used by the chart and re-deploy it, or use the application's built-in administrative tools if available. + +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 oci://REGISTRY_NAME/REPOSITORY_NAME/rabbitmq +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> **Tip**: You can use the default [values.yaml](https://github.com/bitnami/charts/tree/main/bitnami/rabbitmq/values.yaml) + +## Configuration and installation details + +### [Rolling vs Immutable tags](https://docs.bitnami.com/tutorials/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. + +### Set pod affinity + +This chart allows you to set your custom affinity using the `affinity` parameter. Find more information about Pod's affinity in the [kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). + +As an alternative, you can use of the preset configurations for pod affinity, pod anti-affinity, and node affinity available at the [bitnami/common](https://github.com/bitnami/charts/tree/main/bitnami/common#affinities) chart. To do so, set the `podAffinityPreset`, `podAntiAffinityPreset`, or `nodeAffinityPreset` parameters. + +### Scale horizontally + +To horizontally scale this chart once it has been deployed, two options are available: + +- Use the `kubectl scale` command. +- Upgrade the chart modifying the `replicaCount` parameter. + +> NOTE: It is mandatory to specify the password and Erlang cookie that was set the first time the chart was installed when upgrading the chart. + +When scaling down the solution, unnecessary RabbitMQ nodes are automatically stopped, but they are not removed from the cluster. You need to manually remove them by running the `rabbitmqctl forget_cluster_node` command. + +Refer to the chart documentation for [more information on scaling the Rabbit cluster horizontally](https://docs.bitnami.com/kubernetes/infrastructure/rabbitmq/administration/scale-deployment/). + +### Enable TLS support + +To enable TLS support, first generate the certificates as described in the [RabbitMQ documentation for SSL certificate generation](https://www.rabbitmq.com/ssl.html#automated-certificate-generation). + +Once the certificates are generated, you have two alternatives: + +- Create a secret with the certificates and associate the secret when deploying the chart +- Include the certificates in the *values.yaml* file when deploying the chart + +Set the *auth.tls.failIfNoPeerCert* parameter to *false* to allow a TLS connection if the client fails to provide a certificate. + +Set the *auth.tls.sslOptionsVerify* to *verify_peer* to force a node to perform peer verification. When set to *verify_none*, peer verification will be disabled and certificate exchange won't be performed. + +Refer to the chart documentation for [more information and examples of enabling TLS and using Let's Encrypt certificates](https://docs.bitnami.com/kubernetes/infrastructure/rabbitmq/administration/enable-tls-ingress/). + +### Load custom definitions + +It is possible to [load a RabbitMQ definitions file to configure RabbitMQ](https://www.rabbitmq.com/management.html#load-definitions). + +Because definitions may contain RabbitMQ credentials, [store the JSON as a Kubernetes secret](https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets-as-files-from-a-pod). Within the secret's data, choose a key name that corresponds with the desired load definitions filename (i.e. `load_definition.json`) and use the JSON object as the value. + +Next, specify the `load_definitions` property as an `extraConfiguration` pointing to the load definition file path within the container (i.e. `/app/load_definition.json`) and set `loadDefinition.enable` to `true`. Any load definitions specified will be available within in the container at `/app`. + +> NOTE: Loading a definition will take precedence over any configuration done through [Helm values](#parameters). + +If needed, you can use `extraSecrets` to let the chart create the secret for you. This way, you don't need to manually create it before deploying a release. These secrets can also be templated to use supplied chart values. + +Refer to the chart documentation for [more information and configuration examples of loading custom definitions](https://docs.bitnami.com/kubernetes/infrastructure/rabbitmq/configuration/load-files/). + +### Configure LDAP support + +LDAP support can be enabled in the chart by specifying the `ldap.*` parameters while creating a release. Refer to the chart documentation for [more information and a configuration example](https://docs.bitnami.com/kubernetes/infrastructure/rabbitmq/configuration/configure-ldap/). + +### Configure memory high watermark + +It is possible to configure a memory high watermark on RabbitMQ to define [memory thresholds](https://www.rabbitmq.com/memory.html#threshold) using the `memoryHighWatermark.*` parameters. To do so, you have two alternatives: + +- Set an absolute limit of RAM to be used on each RabbitMQ node, as shown in the configuration example below: + +```text +memoryHighWatermark.enabled="true" +memoryHighWatermark.type="absolute" +memoryHighWatermark.value="512MB" +``` + +- Set a relative limit of RAM to be used on each RabbitMQ node. To enable this feature, define the memory limits at pod level too. An example configuration is shown below: + +```text +memoryHighWatermark.enabled="true" +memoryHighWatermark.type="relative" +memoryHighWatermark.value="0.4" +resources.limits.memory="2Gi" +``` + +### Add extra environment variables + +In case you want to add extra environment variables (useful for advanced operations like custom init scripts), you can use the `extraEnvVars` property. + +```yaml +extraEnvVars: + - name: LOG_LEVEL + value: error +``` + +Alternatively, you can use a ConfigMap or a Secret with the environment variables. To do so, use the `.extraEnvVarsCM` or the `extraEnvVarsSecret` properties. + +### Use plugins + +The Bitnami Docker RabbitMQ image ships a set of plugins by default. By default, this chart enables `rabbitmq_management` and `rabbitmq_peer_discovery_k8s` since they are required for RabbitMQ to work on K8s. + +To enable extra plugins, set the `extraPlugins` parameter with the list of plugins you want to enable. In addition to this, the `communityPlugins` parameter can be used to specify a list of URLs (separated by spaces) for custom plugins for RabbitMQ. + +Refer to the chart documentation for [more information on using RabbitMQ plugins](https://docs.bitnami.com/kubernetes/infrastructure/rabbitmq/configuration/use-plugins/). + +### Advanced logging + +In case you want to configure RabbitMQ logging set `logs` value to false and set the log config in extraConfiguration following the [official documentation](https://www.rabbitmq.com/logging.html#log-file-location). + +An example: + +```yaml +logs: false # custom logging +extraConfiguration: | + log.default.level = warning + log.file = false + log.console = true + log.console.level = warning + log.console.formatter = json +``` + +### Recover the cluster from complete shutdown + +> IMPORTANT: Some of these procedures can lead to data loss. Always make a backup beforehand. + +The RabbitMQ cluster is able to support multiple node failures but, in a situation in which all the nodes are brought down at the same time, the cluster might not be able to self-recover. + +This happens if the pod management policy of the statefulset is not `Parallel` and the last pod to be running wasn't the first pod of the statefulset. If that happens, update the pod management policy to recover a healthy state: + +```console +$ kubectl delete statefulset STATEFULSET_NAME --cascade=false +helm upgrade RELEASE_NAME oci://REGISTRY_NAME/REPOSITORY_NAME/rabbitmq \ + --set podManagementPolicy=Parallel \ + --set replicaCount=NUMBER_OF_REPLICAS \ + --set auth.password=PASSWORD \ + --set auth.erlangCookie=ERLANG_COOKIE +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +For a faster resyncronization of the nodes, you can temporarily disable the readiness probe by setting `readinessProbe.enabled=false`. Bear in mind that the pods will be exposed before they are actually ready to process requests. + +If the steps above don't bring the cluster to a healthy state, it could be possible that none of the RabbitMQ nodes think they were the last node to be up during the shutdown. In those cases, you can force the boot of the nodes by specifying the `clustering.forceBoot=true` parameter (which will execute [`rabbitmqctl force_boot`](https://www.rabbitmq.com/rabbitmqctl.8.html#force_boot) in each pod): + +```console +helm upgrade RELEASE_NAME oci://REGISTRY_NAME/REPOSITORY_NAME/rabbitmq \ + --set podManagementPolicy=Parallel \ + --set clustering.forceBoot=true \ + --set replicaCount=NUMBER_OF_REPLICAS \ + --set auth.password=PASSWORD \ + --set auth.erlangCookie=ERLANG_COOKIE +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +More information: [Clustering Guide: Restarting](https://www.rabbitmq.com/clustering.html#restarting). + +### Known issues + +- Changing the password through RabbitMQ's UI can make the pod fail due to the default liveness probes. If you do so, remember to make the chart aware of the new password. Updating the default secret with the password you set through RabbitMQ's UI will automatically recreate the pods. If you are using your own secret, you may have to manually recreate the pods. + +## Persistence + +The [Bitnami RabbitMQ](https://github.com/bitnami/containers/tree/main/bitnami/rabbitmq) image stores the RabbitMQ data and configurations at the `/opt/bitnami/rabbitmq/var/lib/rabbitmq/` path of the container. + +The chart mounts a [Persistent Volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) at this location. By default, the volume is created using dynamic volume provisioning. An existing PersistentVolumeClaim can also be defined. + +### Use existing PersistentVolumeClaims + +1. Create the PersistentVolume +2. Create the PersistentVolumeClaim +3. Install the chart + +```console +helm install my-release --set persistence.existingClaim=PVC_NAME oci://REGISTRY_NAME/REPOSITORY_NAME/rabbitmq +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +### Adjust permissions of the persistence volume mountpoint + +As the image runs as non-root by default, it is necessary to adjust the ownership of the persistent volume so that the container can write data into it. + +By default, the chart is configured to use Kubernetes Security Context to automatically change the ownership of the volume. However, this feature does not work in all Kubernetes distributions. +As an alternative, this chart supports using an `initContainer` to change the ownership of the volume before mounting it in the final destination. + +You can enable this `initContainer` by setting `volumePermissions.enabled` to `true`. + +### Configure the default user/vhost + +If you want to create default user/vhost and set the default permission. you can use `extraConfiguration`: + +```yaml +auth: + username: default-user +extraConfiguration: |- + default_vhost = default-vhost + default_permissions.configure = .* + default_permissions.read = .* + default_permissions.write = .* +``` + +## Troubleshooting + +Find more information about how to deal with common errors related to Bitnami's Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues). + +## Upgrading + +It's necessary to set the `auth.password` and `auth.erlangCookie` parameters when upgrading for readiness/liveness probes to work properly. When you install this chart for the first time, some notes will be displayed providing the credentials you must use under the 'Credentials' section. Please note down the password and the cookie, and run the command below to upgrade your chart: + +```console +helm upgrade my-release oci://REGISTRY_NAME/REPOSITORY_NAME/rabbitmq --set auth.password=[PASSWORD] --set auth.erlangCookie=[RABBITMQ_ERLANG_COOKIE] +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +| Note: you need to substitute the placeholders [PASSWORD] and [RABBITMQ_ERLANG_COOKIE] with the values obtained in the installation notes. + +### To 11.0.0 + +This major version changes the default RabbitMQ image from 3.10.x to 3.11.x. Follow the [official instructions](https://www.rabbitmq.com/upgrade.html) to upgrade from 3.10 to 3.11. + +### To 10.0.0 + +This major version changes the default RabbitMQ image from 3.9.x to 3.10.x. Follow the [official instructions](https://www.rabbitmq.com/upgrade.html) to upgrade from 3.9 to 3.10. + +### To 9.0.0 + +This major release renames several values in this chart and adds missing features, in order to be aligned with the rest of the assets in the Bitnami charts repository. + + .dist + .manager + .metrics + .epmd + +- `service.port` has been renamed as `service.ports.amqp`. +- `service.portName` has been renamed as `service.portNames.amqp`. +- `service.nodePort`has been renamed as `service.nodePorts.amqp`. +- `service.tlsPort` has been renamed as `service.ports.amqpTls`. +- `service.tlsPortName` has been renamed as `service.portNames.amqpTls`. +- `service.tlsNodePort` has been renamed as `service.nodePorts.amqpTls`. +- `service.epmdPortName` has been renamed as `service.portNames.epmd`. +- `service.epmdNodePort` has been renamed as `service.nodePorts.epmd`. +- `service.distPort` has been renamed as `service.ports.dist`. +- `service.distPortName` has been renamed as `service.portNames.dist`. +- `service.distNodePort` has been renamed as `service.nodePorts.dist`. +- `service.managerPort` has been renamed as `service.ports.manager`. +- `service.managerPortName` has been renamed as `service.portNames.manager`. +- `service.managerNodePort` has been renamed as `service.nodePorts.manager`. +- `service.metricsPort` has been renamed as `service.ports.metrics`. +- `service.metricsPortName` has been renamed as `service.portNames.metrics`. +- `service.metricsNodePort` has been renamed as `service.nodePorts.metrics`. +- `persistence.volumes` has been removed, as it duplicates the parameter `extraVolumes`. +- `ingress.certManager` has been removed. +- `metrics.serviceMonitor.relabellings` has been replaced with `metrics.serviceMonitor.relabelings`, and it sets the field `relabelings` instead of `metricRelabelings`. +- `metrics.serviceMonitor.additionalLabels` has been renamed as `metrics.serviceMonitor.labels` +- `updateStrategyType` has been removed, use the field `updateStrategy` instead, which is interpreted as a template. +- The content of `podSecurityContext` and `containerSecurityContext` have been modified. +- The behavior of VolumePermissions has been modified to not change ownership of '.snapshot' and 'lost+found' +- Introduced the values `ContainerPorts.*`, separating the service and container ports configuration. + +### To 8.21.0 + +This new version of the chart bumps the RabbitMQ version to `3.9.1`. It is considered a minor release, and no breaking changes are expected. Additionally, RabbitMQ `3.9.X` nodes can run alongside `3.8.X` nodes. + +See the [Upgrading guide](https://www.rabbitmq.com/upgrade.html) and the [RabbitMQ change log](https://www.rabbitmq.com/changelog.html) for further documentation. + +### To 8.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +[Learn more about this change and related upgrade considerations](https://docs.bitnami.com/kubernetes/infrastructure/rabbitmq/administration/upgrade-helm3/). + +### To 7.0.0 + +- Several parameters were renamed or disappeared in favor of new ones on this major version: + - `replicas` is renamed to `replicaCount`. + - `securityContext.*` is deprecated in favor of `podSecurityContext` and `containerSecurityContext`. + - Authentication parameters were reorganized under the `auth.*` parameter: + - `rabbitmq.username`, `rabbitmq.password`, and `rabbitmq.erlangCookie` are now `auth.username`, `auth.password`, and `auth.erlangCookie` respectively. + - `rabbitmq.tls.*` parameters are now under `auth.tls.*`. + - Parameters prefixed with `rabbitmq.` were renamed removing the prefix. E.g. `rabbitmq.configuration` -> renamed to `configuration`. + - `rabbitmq.rabbitmqClusterNodeName` is deprecated. + - `rabbitmq.setUlimitNofiles` is deprecated. + - `forceBoot.enabled` is renamed to `clustering.forceBoot`. + - `loadDefinition.secretName` is renamed to `loadDefinition.existingSecret`. + - `metics.port` is remamed to `service.metricsPort`. + - `service.extraContainerPorts` is renamed to `extraContainerPorts`. + - `service.nodeTlsPort` is renamed to `service.tlsNodePort`. + - `podDisruptionBudget` is deprecated in favor of `pdb.create`, `pdb.minAvailable`, and `pdb.maxUnavailable`. + - `rbacEnabled` -> deprecated in favor of `rbac.create`. + - New parameters: `serviceAccount.create`, and `serviceAccount.name`. + - New parameters: `memoryHighWatermark.enabled`, `memoryHighWatermark.type`, and `memoryHighWatermark.value`. +- Chart labels and Ingress configuration were adapted to follow the Helm charts best practices. +- Initialization logic now relies on the container. +- This version introduces `bitnami/common`, a [library chart](https://helm.sh/docs/topics/library_charts/#helm) as a dependency. More documentation about this new utility could be found [here](https://github.com/bitnami/charts/tree/main/bitnami/common#bitnami-common-library-chart). Please, make sure that you have updated the chart dependencies before executing any upgrade. +- The layout of the persistent volumes has changed (if using persistence). Action is required if preserving data through the upgrade is desired: + - The data has moved from `mnesia/` within the persistent volume to the root of the persistent volume + - The `config/` and `schema/` directories within the persistent volume are no longer used + - An init container can be used to move and clean up the peristent volumes. An example can be found [here](https://github.com/bitnami/charts/issues/10913#issuecomment-1169619513). + - Alternately the value `persistence.subPath` can be overridden to be `mnesia` so that the directory layout is consistent with what it was previously. + - Note however that this will leave the unused `config/` and `schema/` directories within the peristent volume forever. + +Consequences: + +- Backwards compatibility is not guaranteed. +- Compatibility with non Bitnami images is not guaranteed anymore. + +### To 6.0.0 + +This new version updates the RabbitMQ image to a [new version based on bash instead of node.js](https://github.com/bitnami/containers/tree/main/bitnami/rabbitmq#3715-r18-3715-ol-7-r19). However, since this Chart overwrites the container's command, the changes to the container shouldn't affect the Chart. To upgrade, it may be needed to enable the `fastBoot` option, as it is already the case from upgrading from 5.X to 5.Y. + +### To 5.0.0 + +This major release changes the clustering method from `ip` to `hostname`. +This change is needed to fix the persistence. The data dir will now depend on the hostname which is stable instead of the pod IP that might change. + +> IMPORTANT: Note that if you upgrade from a previous version you will lose your data. + +### To 3.0.0 + +Backwards compatibility is not guaranteed unless you modify the labels used on the chart's deployments. +Use the workaround below to upgrade from versions previous to 3.0.0. The following example assumes that the release name is rabbitmq: + +```console +kubectl delete statefulset rabbitmq --cascade=false +``` + +## Bitnami Kubernetes Documentation + +Bitnami Kubernetes documentation is available at [https://docs.bitnami.com/](https://docs.bitnami.com/). You can find there the following resources: + +- [Documentation for RabbitMQ Helm chart](https://docs.bitnami.com/kubernetes/infrastructure/rabbitmq/) +- [Get Started with Kubernetes guides](https://docs.bitnami.com/kubernetes/) +- [Bitnami Helm charts documentation](https://docs.bitnami.com/kubernetes/apps/) +- [Kubernetes FAQs](https://docs.bitnami.com/kubernetes/faq/) +- [Kubernetes Developer guides](https://docs.bitnami.com/tutorials/) + +## License + +Copyright © 2024 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/backing-services/rabbitmq/auction-onsite-alpha.values.yaml b/backing-services/rabbitmq/auction-onsite-alpha.values.yaml new file mode 100644 index 0000000..1cdb62e --- /dev/null +++ b/backing-services/rabbitmq/auction-onsite-alpha.values.yaml @@ -0,0 +1,17 @@ +auth: + username: admin + password: "admin" + securePassword: true + existingPasswordSecret: "" + +serviceAccount: + create: false + name: "" + namespace: "default" + awsRoleArn: "" + owner: "" + automountServiceAccountToken: true + annotations: {} + +service: + type: LoadBalancer \ No newline at end of file diff --git a/backing-services/rabbitmq/auction-stage-eks.values.yaml b/backing-services/rabbitmq/auction-stage-eks.values.yaml new file mode 100644 index 0000000..994bba5 --- /dev/null +++ b/backing-services/rabbitmq/auction-stage-eks.values.yaml @@ -0,0 +1,23 @@ +auth: + username: admin + password: "admin" + securePassword: true + existingPasswordSecret: "" + +serviceAccount: + create: false + name: "" + namespace: "default" + awsRoleArn: "" + owner: "" + automountServiceAccountToken: true + annotations: {} + +service: + nameOverride: "" + type: LoadBalancer + annotations: + service.beta.kubernetes.io/aws-load-balancer-type: "nlb" + service.beta.kubernetes.io/aws-load-balancer-type: external + service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing + service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: instance diff --git a/backing-services/rabbitmq/charts/common-2.14.1.tgz b/backing-services/rabbitmq/charts/common-2.14.1.tgz new file mode 100644 index 0000000..f443a7c Binary files /dev/null and b/backing-services/rabbitmq/charts/common-2.14.1.tgz differ diff --git a/backing-services/rabbitmq/ride-stage-tavana.values.yaml b/backing-services/rabbitmq/ride-stage-tavana.values.yaml new file mode 100644 index 0000000..e8fe18d --- /dev/null +++ b/backing-services/rabbitmq/ride-stage-tavana.values.yaml @@ -0,0 +1,11 @@ +auth: + username: admin + password: "admin" + securePassword: true + existingPasswordSecret: "" + +serviceAccount: + create: false + +service: + type: LoadBalancer diff --git a/backing-services/rabbitmq/schoobus-onsite.values.yaml b/backing-services/rabbitmq/schoobus-onsite.values.yaml new file mode 100644 index 0000000..1cdb62e --- /dev/null +++ b/backing-services/rabbitmq/schoobus-onsite.values.yaml @@ -0,0 +1,17 @@ +auth: + username: admin + password: "admin" + securePassword: true + existingPasswordSecret: "" + +serviceAccount: + create: false + name: "" + namespace: "default" + awsRoleArn: "" + owner: "" + automountServiceAccountToken: true + annotations: {} + +service: + type: LoadBalancer \ No newline at end of file diff --git a/backing-services/rabbitmq/school-stage-tavana.values.yaml b/backing-services/rabbitmq/school-stage-tavana.values.yaml new file mode 100644 index 0000000..da0dc1b --- /dev/null +++ b/backing-services/rabbitmq/school-stage-tavana.values.yaml @@ -0,0 +1,25 @@ +image: + registry: 172.16.16.1:30516 + repository: bitnami/rabbitmq + tag: 3.12.12-debian-11-r0 + +auth: + username: admin + password: "admin" + securePassword: true + existingPasswordSecret: "" + +serviceAccount: + create: false + name: "" + namespace: "default" + awsRoleArn: "" + owner: "" + automountServiceAccountToken: true + annotations: {} + +service: + type: NodePort + +nodeSelector: + node.name: node-01 \ No newline at end of file diff --git a/backing-services/rabbitmq/schoolbus-demo.values.yaml b/backing-services/rabbitmq/schoolbus-demo.values.yaml new file mode 100644 index 0000000..2bde3e0 --- /dev/null +++ b/backing-services/rabbitmq/schoolbus-demo.values.yaml @@ -0,0 +1,33 @@ +image: + registry: 172.16.16.2:30516 + repository: bitnami/rabbitmq + tag: 3.12.12-debian-11-r0 + +auth: + username: admin + password: "admin" + securePassword: true + existingPasswordSecret: "" + +serviceAccount: + create: false + name: "" + namespace: "default" + awsRoleArn: "" + owner: "" + automountServiceAccountToken: true + annotations: {} + +service: + type: NodePort + +nodeSelector: + node.name: node-1 + +resources: + requests: + cpu: 1000m + memory: 512Mi + limits: + cpu: 1000m + memory: 512Mi \ No newline at end of file diff --git a/backing-services/rabbitmq/schoolbuses.values.yaml b/backing-services/rabbitmq/schoolbuses.values.yaml new file mode 100644 index 0000000..6ce527c --- /dev/null +++ b/backing-services/rabbitmq/schoolbuses.values.yaml @@ -0,0 +1,20 @@ +global: + storageClass: "efs-sc" + +auth: + username: admin + password: "admin" + securePassword: true + existingPasswordSecret: "" + +serviceAccount: + create: true + name: "rabbitmqservcieaccount" + namespace: "default" + awsRoleArn: "arn:aws:iam::889565812003:role/schoolbuses_Cluster_IAM" + owner: "schoolbuses" + automountServiceAccountToken: true + annotations: {} + +service: + type: LoadBalancer \ No newline at end of file diff --git a/backing-services/rabbitmq/templates/NOTES.txt b/backing-services/rabbitmq/templates/NOTES.txt new file mode 100644 index 0000000..2d26bce --- /dev/null +++ b/backing-services/rabbitmq/templates/NOTES.txt @@ -0,0 +1,154 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +{{- $servicePort := or (.Values.service.portEnabled) (not .Values.auth.tls.enabled) | ternary .Values.service.ports.amqp .Values.service.ports.amqpTls -}} + +** Please be patient while the chart is being deployed ** + +{{- if .Values.diagnosticMode.enabled }} +The chart has been deployed in diagnostic mode. All probes have been disabled and the command has been overwritten with: + + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 4 }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 4 }} + +Get the list of pods by executing: + + kubectl get pods --namespace {{ .Release.Namespace }} -l app.kubernetes.io/instance={{ .Release.Name }} + +Access the pod you want to debug by executing + + kubectl exec --namespace {{ .Release.Namespace }} -ti -- bash + +In order to replicate the container startup scripts execute this command: + + /opt/bitnami/scripts/rabbitmq/entrypoint.sh /opt/bitnami/scripts/rabbitmq/run.sh + +{{- else }} + +Credentials: + +{{- if not .Values.loadDefinition.enabled }} + echo "Username : {{ .Values.auth.username }}" + echo "Password : $(kubectl get secret --namespace {{ .Release.Namespace }} {{ include "rabbitmq.secretPasswordName" . }} -o jsonpath="{.data.rabbitmq-password}" | base64 -d)" +{{- end }} + echo "ErLang Cookie : $(kubectl get secret --namespace {{ .Release.Namespace }} {{ include "rabbitmq.secretErlangName" . }} -o jsonpath="{.data.rabbitmq-erlang-cookie}" | base64 -d)" + +Note that the credentials are saved in persistent volume claims and will not be changed upon upgrade or reinstallation unless the persistent volume claim has been deleted. If this is not the first installation of this chart, the credentials may not be valid. +This is applicable when no passwords are set and therefore the random password is autogenerated. In case of using a fixed password, you should specify it when upgrading. +More information about the credentials may be found at https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues/#credential-errors-while-upgrading-chart-releases. + +RabbitMQ can be accessed within the cluster on port {{ $servicePort }} at {{ include "common.names.fullname" . }}.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }} + +To access for outside the cluster, perform the following steps: + +{{- if .Values.ingress.enabled }} +{{- if contains "NodePort" .Values.service.type }} + +To Access the RabbitMQ AMQP port: + +1. Obtain the NodePort IP and ports: + + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT_AMQP=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[?(@.name=='amqp')].nodePort}" services {{ include "common.names.fullname" . }}) + echo "URL : amqp://$NODE_IP:$NODE_PORT_AMQP/" + +{{- else if contains "LoadBalancer" .Values.service.type }} + +To Access the RabbitMQ AMQP port: + +1. Obtain the LoadBalancer IP: + +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 {{ include "common.names.fullname" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "common.names.fullname" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") + echo "URL : amqp://$SERVICE_IP:{{ $servicePort }}/" + +{{- else if contains "ClusterIP" .Values.service.type }} + +To Access the RabbitMQ AMQP port: + +1. Create a port-forward to the AMQP port: + + kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ include "common.names.fullname" . }} {{ $servicePort }}:{{ $servicePort }} & + echo "URL : amqp://127.0.0.1:{{ $servicePort }}/" + +{{- end }} + +2. Access RabbitMQ using using the obtained URL. + +To Access the RabbitMQ Management interface: + +1. Get the RabbitMQ Management URL and associate its hostname to your cluster external IP: + + export CLUSTER_IP=$(minikube ip) # On Minikube. Use: `kubectl cluster-info` on others K8s clusters + echo "RabbitMQ Management: http{{ if .Values.ingress.tls }}s{{ end }}://{{ .Values.ingress.hostname }}/" + echo "$CLUSTER_IP {{ .Values.ingress.hostname }}" | sudo tee -a /etc/hosts + +2. Open a browser and access RabbitMQ Management using the obtained URL. + +{{- else }} +{{- if contains "NodePort" .Values.service.type }} + +Obtain the NodePort IP and ports: + + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT_AMQP=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[?(@.name=='amqp')].nodePort}" services {{ include "common.names.fullname" . }}) + export NODE_PORT_STATS=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[?(@.name=='http-stats')].nodePort}" services {{ include "common.names.fullname" . }}) + +To Access the RabbitMQ AMQP port: + + echo "URL : amqp://$NODE_IP:$NODE_PORT_AMQP/" + +To Access the RabbitMQ Management interface: + + echo "URL : http://$NODE_IP:$NODE_PORT_STATS/" + +{{- else if contains "LoadBalancer" .Values.service.type }} + +Obtain the LoadBalancer IP: + +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 {{ include "common.names.fullname" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "common.names.fullname" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") + +To Access the RabbitMQ AMQP port: + + echo "URL : amqp://$SERVICE_IP:{{ $servicePort }}/" + +To Access the RabbitMQ Management interface: + + echo "URL : http://$SERVICE_IP:{{ .Values.service.ports.manager }}/" + +{{- else if contains "ClusterIP" .Values.service.type }} + +To Access the RabbitMQ AMQP port: + + echo "URL : amqp://127.0.0.1:{{ $servicePort }}/" + kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ include "common.names.fullname" . }} {{ $servicePort }}:{{ $servicePort }} + +To Access the RabbitMQ Management interface: + + echo "URL : http://127.0.0.1:{{ .Values.service.ports.manager }}/" + kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ include "common.names.fullname" . }} {{ .Values.service.ports.manager }}:{{ .Values.service.ports.manager }} + +{{- end }} +{{- end }} + +{{- if .Values.metrics.enabled }} + +To access the RabbitMQ Prometheus metrics, get the RabbitMQ Prometheus URL by running: + + kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ include "common.names.fullname" . }} {{ .Values.service.ports.metrics }}:{{ .Values.service.ports.metrics }} & + echo "Prometheus Metrics URL: http://127.0.0.1:{{ .Values.service.ports.metrics }}/metrics" + +Then, open the obtained URL in a browser. + +{{- end }} + +{{- include "common.warnings.rollingTag" .Values.image }} +{{- include "common.warnings.rollingTag" .Values.volumePermissions.image }} + +{{- end }} diff --git a/backing-services/rabbitmq/templates/_helpers.tpl b/backing-services/rabbitmq/templates/_helpers.tpl new file mode 100644 index 0000000..abf6782 --- /dev/null +++ b/backing-services/rabbitmq/templates/_helpers.tpl @@ -0,0 +1,269 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the proper RabbitMQ image name +*/}} +{{- define "rabbitmq.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper image name (for the init container volume-permissions image) +*/}} +{{- define "rabbitmq.volumePermissions.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.volumePermissions.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "rabbitmq.imagePullSecrets" -}} +{{ include "common.images.renderPullSecrets" (dict "images" (list .Values.image .Values.volumePermissions.image) "context" $) }} +{{- end -}} + +{{/* + Create the name of the service account to use + */}} +{{- define "rabbitmq.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "common.names.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Get the password secret. +*/}} +{{- define "rabbitmq.secretPasswordName" -}} + {{- if .Values.auth.existingPasswordSecret -}} + {{- printf "%s" (tpl .Values.auth.existingPasswordSecret $) -}} + {{- else -}} + {{- printf "%s" (include "common.names.fullname" .) -}} + {{- end -}} +{{- end -}} + +{{/* +Get the erlang secret. +*/}} +{{- define "rabbitmq.secretErlangName" -}} + {{- if .Values.auth.existingErlangSecret -}} + {{- printf "%s" (tpl .Values.auth.existingErlangSecret $) -}} + {{- else -}} + {{- printf "%s" (include "common.names.fullname" .) -}} + {{- end -}} +{{- end -}} + +{{/* +Get the TLS secret. +*/}} +{{- define "rabbitmq.tlsSecretName" -}} + {{- if .Values.auth.tls.existingSecret -}} + {{- printf "%s" (tpl .Values.auth.tls.existingSecret $) -}} + {{- else -}} + {{- printf "%s-certs" (include "common.names.fullname" .) -}} + {{- end -}} +{{- end -}} + +{{/* +Return true if a TLS credentials secret object should be created +*/}} +{{- define "rabbitmq.createTlsSecret" -}} +{{- if and .Values.auth.tls.enabled (not .Values.auth.tls.existingSecret) }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the proper RabbitMQ plugin list +*/}} +{{- define "rabbitmq.plugins" -}} +{{- $plugins := .Values.plugins -}} +{{- if .Values.extraPlugins -}} +{{- $plugins = printf "%s %s" $plugins .Values.extraPlugins -}} +{{- end -}} +{{- if .Values.metrics.enabled -}} +{{- $plugins = printf "%s %s" $plugins .Values.metrics.plugins -}} +{{- end -}} +{{- printf "%s" $plugins | replace " " ", " -}} +{{- end -}} + +{{/* +Return the number of bytes given a value +following a base 2 o base 10 number system. +Usage: +{{ include "rabbitmq.toBytes" .Values.path.to.the.Value }} +*/}} +{{- define "rabbitmq.toBytes" -}} +{{- $value := int (regexReplaceAll "([0-9]+).*" . "${1}") }} +{{- $unit := regexReplaceAll "[0-9]+(.*)" . "${1}" }} +{{- if eq $unit "Ki" }} + {{- mul $value 1024 }} +{{- else if eq $unit "Mi" }} + {{- mul $value 1024 1024 }} +{{- else if eq $unit "Gi" }} + {{- mul $value 1024 1024 1024 }} +{{- else if eq $unit "Ti" }} + {{- mul $value 1024 1024 1024 1024 }} +{{- else if eq $unit "Pi" }} + {{- mul $value 1024 1024 1024 1024 1024 }} +{{- else if eq $unit "Ei" }} + {{- mul $value 1024 1024 1024 1024 1024 1024 }} +{{- else if eq $unit "K" }} + {{- mul $value 1000 }} +{{- else if eq $unit "M" }} + {{- mul $value 1000 1000 }} +{{- else if eq $unit "G" }} + {{- mul $value 1000 1000 1000 }} +{{- else if eq $unit "T" }} + {{- mul $value 1000 1000 1000 1000 }} +{{- else if eq $unit "P" }} + {{- mul $value 1000 1000 1000 1000 1000 }} +{{- else if eq $unit "E" }} + {{- mul $value 1000 1000 1000 1000 1000 1000 }} +{{- end }} +{{- end -}} + +{{/* +Compile all warnings into a single message, and call fail. +*/}} +{{- define "rabbitmq.validateValues" -}} +{{- $messages := list -}} +{{- $messages := append $messages (include "rabbitmq.validateValues.ldap" .) -}} +{{- $messages := append $messages (include "rabbitmq.validateValues.memoryHighWatermark" .) -}} +{{- $messages := append $messages (include "rabbitmq.validateValues.ingress.tls" .) -}} +{{- $messages := append $messages (include "rabbitmq.validateValues.auth.tls" .) -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}} +{{- end -}} +{{- end -}} + +{{/* +Validate values of rabbitmq - LDAP support +*/}} +{{- define "rabbitmq.validateValues.ldap" -}} +{{- if .Values.ldap.enabled }} +{{- $serversListLength := len .Values.ldap.servers }} +{{- $userDnPattern := coalesce .Values.ldap.user_dn_pattern .Values.ldap.userDnPattern }} +{{- if or (and (not (gt $serversListLength 0)) (empty .Values.ldap.uri)) (and (not $userDnPattern) (not .Values.ldap.basedn)) }} +rabbitmq: LDAP + Invalid LDAP configuration. When enabling LDAP support, the parameters "ldap.servers" or "ldap.uri" are mandatory + to configure the connection and "ldap.userDnPattern" or "ldap.basedn" are necessary to lookup the users. Please provide them: + $ helm install {{ .Release.Name }} oci://registry-1.docker.io/bitnamicharts/rabbitmq \ + --set ldap.enabled=true \ + --set ldap.servers[0]=my-ldap-server" \ + --set ldap.port="389" \ + --set ldap.userDnPattern="cn=${username},dc=example,dc=org" +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Validate values of rabbitmq - Memory high watermark +*/}} +{{- define "rabbitmq.validateValues.memoryHighWatermark" -}} +{{- if and (not (eq .Values.memoryHighWatermark.type "absolute")) (not (eq .Values.memoryHighWatermark.type "relative")) }} +rabbitmq: memoryHighWatermark.type + Invalid Memory high watermark type. Valid values are "absolute" and + "relative". Please set a valid mode (--set memoryHighWatermark.type="xxxx") +{{- else if and .Values.memoryHighWatermark.enabled (not .Values.resources.limits.memory) (eq .Values.memoryHighWatermark.type "relative") }} +rabbitmq: memoryHighWatermark + You enabled configuring memory high watermark using a relative limit. However, + no memory limits were defined at POD level. Define your POD limits as shown below: + + $ helm install {{ .Release.Name }} oci://registry-1.docker.io/bitnamicharts/rabbitmq \ + --set memoryHighWatermark.enabled=true \ + --set memoryHighWatermark.type="relative" \ + --set memoryHighWatermark.value="0.4" \ + --set resources.limits.memory="2Gi" + + Altenatively, user an absolute value for the memory memory high watermark : + + $ helm install {{ .Release.Name }} oci://registry-1.docker.io/bitnamicharts/rabbitmq \ + --set memoryHighWatermark.enabled=true \ + --set memoryHighWatermark.type="absolute" \ + --set memoryHighWatermark.value="512MB" +{{- end -}} +{{- end -}} + +{{/* +Validate values of rabbitmq - TLS configuration for Ingress +*/}} +{{- define "rabbitmq.validateValues.ingress.tls" -}} +{{- if and .Values.ingress.enabled .Values.ingress.tls (not (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.ingress.annotations ))) (not .Values.ingress.selfSigned) (not .Values.ingress.existingSecret) (empty .Values.ingress.extraTls) }} +rabbitmq: ingress.tls + You enabled the TLS configuration for the default ingress hostname but + you did not enable any of the available mechanisms to create the TLS secret + to be used by the Ingress Controller. + Please use any of these alternatives: + - Use the `ingress.extraTls` and `ingress.secrets` parameters to provide your custom TLS certificates. + - Use the `ingress.existingSecret` to provide your custom TLS certificates. + - Rely on cert-manager to create it by setting the corresponding annotations + - Rely on Helm to create self-signed certificates by setting `ingress.selfSigned=true` +{{- end -}} +{{- end -}} + +{{/* +Validate values of RabbitMQ - Auth TLS enabled +*/}} +{{- define "rabbitmq.validateValues.auth.tls" -}} +{{- if and .Values.auth.tls.enabled (not .Values.auth.tls.autoGenerated) (not .Values.auth.tls.existingSecret) (not .Values.auth.tls.caCertificate) (not .Values.auth.tls.serverCertificate) (not .Values.auth.tls.serverKey) }} +rabbitmq: auth.tls + You enabled TLS for RabbitMQ but you did not enable any of the available mechanisms to create the TLS secret. + Please use any of these alternatives: + - Provide an existing secret containing the TLS certificates using `auth.tls.existingSecret` + - Provide the plain text certificates using `auth.tls.caCertificate`, `auth.tls.serverCertificate` and `auth.tls.serverKey`. + - Enable auto-generated certificates using `auth.tls.autoGenerated`. +{{- end -}} +{{- end -}} + +{{/* +Get the initialization scripts volume name. +*/}} +{{- define "rabbitmq.initScripts" -}} +{{- printf "%s-init-scripts" (include "common.names.fullname" .) -}} +{{- end -}} + +{{/* +Returns the available value for certain key in an existing secret (if it exists), +otherwise it generates a random value. +*/}} +{{- define "getValueFromSecret" }} + {{- $len := (default 16 .Length) | int -}} + {{- $obj := (lookup "v1" "Secret" .Namespace .Name).data -}} + {{- if $obj }} + {{- index $obj .Key | b64dec -}} + {{- else -}} + {{- randAlphaNum $len -}} + {{- end -}} +{{- end }} + +{{/* +Get the extraConfigurationExistingSecret secret. +*/}} +{{- define "rabbitmq.extraConfiguration" -}} +{{- if not (empty .Values.extraConfigurationExistingSecret) -}} + {{- include "getValueFromSecret" (dict "Namespace" .Release.Namespace "Name" .Values.extraConfigurationExistingSecret "Length" 10 "Key" "extraConfiguration") -}} +{{- else -}} + {{- tpl .Values.extraConfiguration . -}} +{{- end -}} +{{- end -}} + +{{/* +Get the TLS.sslOptions.Password secret. +*/}} +{{- define "rabbitmq.tlsSslOptionsPassword" -}} +{{- if not (empty .Values.auth.tls.sslOptionsPassword.password) -}} + {{- .Values.auth.tls.sslOptionsPassword.password -}} +{{- else -}} + {{- include "getValueFromSecret" (dict "Namespace" .Release.Namespace "Name" .Values.auth.tls.sslOptionsPassword.existingSecret "Length" 10 "Key" .Values.auth.tls.sslOptionsPassword.key) -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/rabbitmq/templates/config-secret.yaml b/backing-services/rabbitmq/templates/config-secret.yaml new file mode 100644 index 0000000..28fa351 --- /dev/null +++ b/backing-services/rabbitmq/templates/config-secret.yaml @@ -0,0 +1,26 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if or (empty .Values.configurationExistingSecret) .Values.advancedConfiguration }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ printf "%s-config" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + {{- if empty .Values.configurationExistingSecret }} + rabbitmq.conf: |- + {{- include "common.tplvalues.render" (dict "value" .Values.configuration "context" $) | b64enc | nindent 4 }} + {{- end }} + {{- if .Values.advancedConfiguration }} + advanced.config: |- + {{- include "common.tplvalues.render" (dict "value" .Values.advancedConfiguration "context" $) | b64enc | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/rabbitmq/templates/extra-list.yaml b/backing-services/rabbitmq/templates/extra-list.yaml new file mode 100644 index 0000000..2d35a58 --- /dev/null +++ b/backing-services/rabbitmq/templates/extra-list.yaml @@ -0,0 +1,9 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/backing-services/rabbitmq/templates/ingress-tls-secrets.yaml b/backing-services/rabbitmq/templates/ingress-tls-secrets.yaml new file mode 100644 index 0000000..f38feba --- /dev/null +++ b/backing-services/rabbitmq/templates/ingress-tls-secrets.yaml @@ -0,0 +1,44 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.ingress.enabled }} +{{- if .Values.ingress.secrets }} +{{- range .Values.ingress.secrets }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .name }} + namespace: {{ include "common.names.namespace" $ | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $.Values.commonLabels "context" $ ) | nindent 4 }} + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ .certificate | b64enc }} + tls.key: {{ .key | b64enc }} +--- +{{- end }} +{{- end }} +{{- if and .Values.ingress.tls .Values.ingress.selfSigned (not .Values.ingress.existingSecret) }} +{{- $secretName := printf "%s-tls" .Values.ingress.hostname }} +{{- $ca := genCA "rabbitmq-ca" 365 }} +{{- $cert := genSignedCert .Values.ingress.hostname nil (list .Values.ingress.hostname) 365 $ca }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.crt" "defaultValue" $cert.Cert "context" $) }} + tls.key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.key" "defaultValue" $cert.Key "context" $) }} + ca.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }} +{{- end }} +{{- end }} diff --git a/backing-services/rabbitmq/templates/ingress.yaml b/backing-services/rabbitmq/templates/ingress.yaml new file mode 100644 index 0000000..e977814 --- /dev/null +++ b/backing-services/rabbitmq/templates/ingress.yaml @@ -0,0 +1,59 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.ingress.enabled }} +apiVersion: {{ include "common.capabilities.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.ingress.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.ingress.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.ingressClassName (eq "true" (include "common.ingress.supportsIngressClassname" .)) }} + ingressClassName: {{ .Values.ingress.ingressClassName | quote }} + {{- end }} + rules: + {{- if .Values.ingress.hostname }} + - host: {{ include "common.tplvalues.render" ( dict "value" .Values.ingress.hostname "context" $ ) }} + http: + paths: + {{- if .Values.ingress.extraPaths }} + {{- toYaml .Values.ingress.extraPaths | nindent 10 }} + {{- end }} + - path: {{ .Values.ingress.path }} + {{- if eq "true" (include "common.ingress.supportsPathType" .) }} + pathType: {{ .Values.ingress.pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" .) "servicePort" .Values.service.portNames.manager "context" $) | nindent 14 }} + {{- end }} + {{- range .Values.ingress.extraHosts }} + - host: {{ include "common.tplvalues.render" ( dict "value" .name "context" $ ) }} + http: + paths: + - path: {{ default "/" .path }} + {{- if eq "true" (include "common.ingress.supportsPathType" $) }} + pathType: {{ default "ImplementationSpecific" .pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" $) "servicePort" $.Values.service.portNames.manager "context" $) | nindent 14 }} + {{- end }} + {{- if .Values.ingress.extraRules }} + {{- include "common.tplvalues.render" (dict "value" .Values.ingress.extraRules "context" $) | nindent 4 }} + {{- end }} + {{- if or (and .Values.ingress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.ingress.annotations )) .Values.ingress.selfSigned .Values.ingress.existingSecret)) .Values.ingress.extraTls }} + tls: + {{- if and .Values.ingress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.ingress.annotations )) .Values.ingress.selfSigned .Values.ingress.existingSecret) }} + - hosts: + - {{ .Values.ingress.hostname | quote }} + secretName: {{ default (printf "%s-tls" .Values.ingress.hostname | trunc 63 | trimSuffix "-") .Values.ingress.existingSecret }} + {{- end }} + {{- if .Values.ingress.extraTls }} + {{- include "common.tplvalues.render" (dict "value" .Values.ingress.extraTls "context" $) | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/rabbitmq/templates/init-configmap.yaml b/backing-services/rabbitmq/templates/init-configmap.yaml new file mode 100644 index 0000000..2e3ef38 --- /dev/null +++ b/backing-services/rabbitmq/templates/init-configmap.yaml @@ -0,0 +1,18 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.initScripts }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-init-scripts" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: +{{- include "common.tplvalues.render" ( dict "value" .Values.initScripts "context" $ ) | nindent 4 }} +{{- end }} diff --git a/backing-services/rabbitmq/templates/networkpolicy.yaml b/backing-services/rabbitmq/templates/networkpolicy.yaml new file mode 100644 index 0000000..b24cfa1 --- /dev/null +++ b/backing-services/rabbitmq/templates/networkpolicy.yaml @@ -0,0 +1,42 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ include "common.capabilities.networkPolicy.apiVersion" . }} +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + ingress: + # Allow inbound connections + - ports: + - port: {{ .Values.service.ports.epmd }} # EPMD + - port: {{ .Values.service.ports.amqp }} + - port: {{ .Values.service.ports.amqpTls }} + - port: {{ .Values.service.ports.dist }} + - port: {{ .Values.service.ports.manager }} + {{- if not .Values.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: + {{ printf "%s-client" (include "common.names.fullname" .) }}: "true" + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 14 }} + {{- if .Values.networkPolicy.additionalRules }} + {{- include "common.tplvalues.render" (dict "value" .Values.networkPolicy.additionalRules "context" $) | nindent 8 }} + {{- end }} + {{- end }} + # Allow prometheus scrapes + - ports: + - port: {{ .Values.service.ports.metrics }} +{{- end }} diff --git a/backing-services/rabbitmq/templates/pdb.yaml b/backing-services/rabbitmq/templates/pdb.yaml new file mode 100644 index 0000000..a02d402 --- /dev/null +++ b/backing-services/rabbitmq/templates/pdb.yaml @@ -0,0 +1,26 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.pdb.minAvailable }} + minAvailable: {{ .Values.pdb.minAvailable }} + {{- end }} + {{- if .Values.pdb.maxUnavailable }} + maxUnavailable: {{ .Values.pdb.maxUnavailable }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} +{{- end }} diff --git a/backing-services/rabbitmq/templates/prometheusrule.yaml b/backing-services/rabbitmq/templates/prometheusrule.yaml new file mode 100644 index 0000000..d9c32b5 --- /dev/null +++ b/backing-services/rabbitmq/templates/prometheusrule.yaml @@ -0,0 +1,25 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ default (include "common.names.namespace" .) .Values.metrics.prometheusRule.namespace | quote}} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.metrics.prometheusRule.additionalLabels }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.prometheusRule.additionalLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + groups: + {{- with .Values.metrics.prometheusRule.rules }} + - name: {{ template "common.names.name" $ }} + rules: {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 8 }} + {{- end }} +{{- end }} diff --git a/backing-services/rabbitmq/templates/role.yaml b/backing-services/rabbitmq/templates/role.yaml new file mode 100644 index 0000000..3bbfadb --- /dev/null +++ b/backing-services/rabbitmq/templates/role.yaml @@ -0,0 +1,23 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.rbac.create }} +kind: Role +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ printf "%s-endpoint-reader" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: + - apiGroups: [""] + resources: ["endpoints"] + verbs: ["get"] + - apiGroups: [""] + resources: ["events"] + verbs: ["create"] +{{- end }} diff --git a/backing-services/rabbitmq/templates/rolebinding.yaml b/backing-services/rabbitmq/templates/rolebinding.yaml new file mode 100644 index 0000000..5bcdc30 --- /dev/null +++ b/backing-services/rabbitmq/templates/rolebinding.yaml @@ -0,0 +1,23 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.rbac.create }} +kind: RoleBinding +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ printf "%s-endpoint-reader" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +subjects: + - kind: ServiceAccount + name: {{ template "rabbitmq.serviceAccountName" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ printf "%s-endpoint-reader" (include "common.names.fullname" .) }} +{{- end }} diff --git a/backing-services/rabbitmq/templates/secrets.yaml b/backing-services/rabbitmq/templates/secrets.yaml new file mode 100644 index 0000000..1aa2e6c --- /dev/null +++ b/backing-services/rabbitmq/templates/secrets.yaml @@ -0,0 +1,64 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- $host := printf "%s.%s.svc.%s" (include "common.names.fullname" .) (include "common.names.namespace" .) .Values.clusterDomain }} +{{- $port := print .Values.service.ports.amqp }} +{{- $user := print .Values.auth.username }} +{{- $password := include "common.secrets.passwords.manage" (dict "secret" (include "rabbitmq.secretPasswordName" .) "key" "rabbitmq-password" "length" 16 "providedValues" (list "auth.password") "context" $) | trimAll "\"" | b64dec }} + +{{- if or (not .Values.auth.existingErlangSecret) (not .Values.auth.existingPasswordSecret) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + {{- if (not .Values.auth.existingPasswordSecret ) }} + rabbitmq-password: {{ print $password | b64enc | quote }} + {{- end }} + {{- if (not .Values.auth.existingErlangSecret ) }} + rabbitmq-erlang-cookie: {{ include "common.secrets.passwords.manage" (dict "secret" (include "common.names.fullname" .) "key" "rabbitmq-erlang-cookie" "length" 32 "providedValues" (list "auth.erlangCookie") "context" $) }} + {{- end }} +{{- end }} +{{- range $key, $value := .Values.extraSecrets }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ ternary (printf "%s-%s" $.Release.Name $key) $key $.Values.extraSecretsPrependReleaseName }} + namespace: {{ include "common.names.namespace" $ | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $.Values.commonLabels "context" $ ) | nindent 4 }} + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +stringData: {{- include "common.tplvalues.render" (dict "value" $value "context" $) | nindent 2 }} +{{- end }} +{{- if .Values.serviceBindings.enabled }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }}-svcbind + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: servicebinding.io/rabbitmq +data: + provider: {{ print "bitnami" | b64enc | quote }} + type: {{ print "rabbitmq" | b64enc | quote }} + host: {{ print $host | b64enc | quote }} + port: {{ print $port | b64enc | quote }} + username: {{ print $user | b64enc | quote }} + password: {{ print $password | b64enc | quote }} + uri: {{ printf "amqp://%s:%s@%s:%s" $user $password $host $port | b64enc | quote }} +{{- end }} diff --git a/backing-services/rabbitmq/templates/serviceaccount.yaml b/backing-services/rabbitmq/templates/serviceaccount.yaml new file mode 100644 index 0000000..ff35f52 --- /dev/null +++ b/backing-services/rabbitmq/templates/serviceaccount.yaml @@ -0,0 +1,14 @@ +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: "{{ .Values.serviceAccount.name }}" + namespace: "{{ .Values.serviceAccount.namespace }}" + annotations: + eks.amazonaws.com/role-arn: "{{ .Values.serviceAccount.awsRoleArn }}" + labels: + owner: "{{ .Values.serviceAccount.owner }}" +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +secrets: + - name: {{ include "common.names.fullname" . }} +{{- end }} \ No newline at end of file diff --git a/backing-services/rabbitmq/templates/servicemonitor.yaml b/backing-services/rabbitmq/templates/servicemonitor.yaml new file mode 100644 index 0000000..3c2cff9 --- /dev/null +++ b/backing-services/rabbitmq/templates/servicemonitor.yaml @@ -0,0 +1,57 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ default (include "common.names.namespace" .) .Values.metrics.serviceMonitor.namespace | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.serviceMonitor.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + {{- if or .Values.metrics.serviceMonitor.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.serviceMonitor.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + jobLabel: {{ .Values.metrics.serviceMonitor.jobLabel | quote }} + endpoints: + - port: metrics + {{- if .Values.metrics.serviceMonitor.path }} + path: {{ .Values.metrics.serviceMonitor.path }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.params }} + params: {{ toYaml .Values.metrics.serviceMonitor.params | nindent 8 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.interval }} + interval: {{ .Values.metrics.serviceMonitor.interval }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.honorLabels }} + honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.relabelings }} + relabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.relabelings "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.metricRelabelings "context" $) | nindent 8 }} + {{- end }} + namespaceSelector: + matchNames: + - {{ include "common.names.namespace" . | quote }} + {{- if .Values.metrics.serviceMonitor.podTargetLabels }} + podTargetLabels: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.podTargetLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.targetLabels }} + targetLabels: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.targetLabels "context" $) | nindent 4 }} + {{- end }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + {{- if .Values.metrics.serviceMonitor.selector }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.serviceMonitor.selector "context" $) | nindent 6 }} + {{- end }} +{{- end }} diff --git a/backing-services/rabbitmq/templates/statefulset.yaml b/backing-services/rabbitmq/templates/statefulset.yaml new file mode 100644 index 0000000..7ac5140 --- /dev/null +++ b/backing-services/rabbitmq/templates/statefulset.yaml @@ -0,0 +1,461 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.statefulsetLabels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + {{- if or .Values.statefulsetAnnotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.statefulsetAnnotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + serviceName: {{ printf "%s-%s" (include "common.names.fullname" .) (default "headless" .Values.servicenameOverride) }} + podManagementPolicy: {{ .Values.podManagementPolicy }} + replicas: {{ .Values.replicaCount }} + {{- if .Values.updateStrategy }} + updateStrategy: {{- toYaml .Values.updateStrategy | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + annotations: + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 8 }} + {{- end }} + checksum/config: {{ include (print $.Template.BasePath "/config-secret.yaml") . | sha256sum }} + {{- if (include "rabbitmq.createTlsSecret" . ) }} + checksum/config: {{ include (print $.Template.BasePath "/tls-secrets.yaml") . | sha256sum }} + {{- end }} + {{- if or (not .Values.auth.existingErlangSecret) (not .Values.auth.existingPasswordSecret) .Values.extraSecrets }} + checksum/secret: {{ include (print $.Template.BasePath "/secrets.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.podAnnotations "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.podAnnotations "context" $) | nindent 8 }} + {{- end }} + spec: + {{- include "rabbitmq.imagePullSecrets" . | nindent 6 }} + {{- if .Values.schedulerName }} + schedulerName: {{ .Values.schedulerName | quote }} + {{- end }} + {{- if .Values.serviceAccount.create }} + serviceAccountName: rabbitmqservcieaccount + {{- end }} + {{- if .Values.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.affinity "context" .) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAffinityPreset "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAntiAffinityPreset "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.nodeAffinityPreset.type "key" .Values.nodeAffinityPreset.key "values" .Values.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.nodeSelector "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.tolerations "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- omit .Values.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.dnsPolicy }} + dnsPolicy: {{ .Values.dnsPolicy }} + {{- end }} + {{- if .Values.dnsConfig }} + dnsConfig: {{- include "common.tplvalues.render" (dict "value" .Values.dnsConfig "context" .) | nindent 8 }} + {{- end }} + terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} + enableServiceLinks: {{ .Values.enableServiceLinks }} + initContainers: + {{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }} + - name: volume-permissions + image: {{ include "rabbitmq.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + args: + - -ec + - | + mkdir -p "{{ .Values.persistence.mountPath }}" + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + chown `id -u`:`id -G | cut -d " " -f2` {{ .Values.persistence.mountPath }} + {{- else }} + chown "{{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }}" "{{ .Values.persistence.mountPath }}" + {{- end }} + find "{{ .Values.persistence.mountPath }}" -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | \ + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + xargs -r chown -R `id -u`:`id -G | cut -d " " -f2` + {{- else }} + xargs -r chown -R "{{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }}" + {{- end }} + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.containerSecurityContext "runAsUser" | toYaml | nindent 12 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.containerSecurityContext | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: data + mountPath: {{ .Values.persistence.mountPath }} + {{- if .Values.persistence.subPath }} + subPath: {{ .Values.persistence.subPath }} + {{- end }} + {{- end }} + {{- if .Values.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.initContainers "context" $) | nindent 8 }} + {{- end }} + containers: + - name: rabbitmq + image: {{ template "rabbitmq.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.args "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.lifecycleHooks "context" $) | nindent 12 }} + {{- else }} + lifecycle: + preStop: + exec: + command: + - /bin/bash + - -ec + - | + if [[ -f /opt/bitnami/scripts/rabbitmq/nodeshutdown.sh ]]; then + /opt/bitnami/scripts/rabbitmq/nodeshutdown.sh -t {{ .Values.terminationGracePeriodSeconds | quote }} -d {{ ternary "true" "false" .Values.image.debug | quote }} + else + rabbitmqctl stop_app + fi + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + - name: MY_POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- $svcName := printf "%s-%s" (include "common.names.fullname" .) (default "headless" .Values.servicenameOverride) }} + {{- if .Values.featureFlags }} + - name: RABBITMQ_FEATURE_FLAGS + value: {{ .Values.featureFlags }} + {{- end }} + - name: RABBITMQ_FORCE_BOOT + value: {{ ternary "yes" "no" .Values.clustering.forceBoot | quote }} + {{- if (eq "hostname" .Values.clustering.addressType) }} + - name: RABBITMQ_NODE_NAME + value: "rabbit@$(MY_POD_NAME).{{ $svcName }}.$(MY_POD_NAMESPACE).svc.{{ .Values.clusterDomain }}" + {{- else }} + - name: RABBITMQ_NODE_NAME + value: "rabbit@$(MY_POD_NAME)" + {{- end }} + - name: RABBITMQ_MNESIA_DIR + value: "{{ .Values.persistence.mountPath }}/$(RABBITMQ_NODE_NAME)" + - name: RABBITMQ_LDAP_ENABLE + value: {{ ternary "yes" "no" .Values.ldap.enabled | quote }} + {{- if .Values.ldap.enabled }} + - name: RABBITMQ_LDAP_TLS + value: {{ ternary "yes" "no" .Values.ldap.tls.enabled | quote }} + - name: RABBITMQ_LDAP_SERVERS + value: {{ .Values.ldap.servers | join "," | quote }} + - name: RABBITMQ_LDAP_SERVERS_PORT + value: {{ .Values.ldap.port | quote }} + - name: RABBITMQ_LDAP_USER_DN_PATTERN + value: {{ .Values.ldap.user_dn_pattern }} + {{- end }} + {{- if .Values.logs }} + - name: RABBITMQ_LOGS + value: {{ .Values.logs | quote }} + {{- end }} + - name: RABBITMQ_ULIMIT_NOFILES + value: {{ .Values.ulimitNofiles | quote }} + {{- if and .Values.maxAvailableSchedulers }} + - name: RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS + value: {{ printf "+S %s:%s" (toString .Values.maxAvailableSchedulers) (toString .Values.onlineSchedulers) -}} + {{- end }} + - name: RABBITMQ_USE_LONGNAME + value: "true" + - name: RABBITMQ_ERL_COOKIE + valueFrom: + secretKeyRef: + name: {{ template "rabbitmq.secretErlangName" . }} + key: rabbitmq-erlang-cookie + {{- if and .Values.clustering.rebalance (gt (.Values.replicaCount | int) 1) }} + - name: RABBITMQ_CLUSTER_REBALANCE + value: "true" + {{- end }} + - name: RABBITMQ_LOAD_DEFINITIONS + value: {{ ternary "yes" "no" .Values.loadDefinition.enabled | quote }} + - name: RABBITMQ_DEFINITIONS_FILE + value: {{ .Values.loadDefinition.file | quote }} + - name: RABBITMQ_SECURE_PASSWORD + value: {{ ternary "yes" "no" (or .Values.auth.securePassword (not .Values.auth.password)) | quote }} + - name: RABBITMQ_USERNAME + value: {{ .Values.auth.username | quote }} + - name: RABBITMQ_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "rabbitmq.secretPasswordName" . }} + key: rabbitmq-password + - name: RABBITMQ_PLUGINS + value: {{ include "rabbitmq.plugins" . | quote }} + {{- if .Values.communityPlugins }} + - name: RABBITMQ_COMMUNITY_PLUGINS + value: {{ .Values.communityPlugins | quote }} + {{- end }} + {{- if .Values.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.extraEnvVarsSecret "context" $) }} + {{- end }} + ports: + - name: amqp + containerPort: {{ .Values.containerPorts.amqp }} + - name: dist + containerPort: {{ .Values.containerPorts.dist }} + - name: stats + containerPort: {{ .Values.containerPorts.manager }} + - name: epmd + containerPort: {{ .Values.containerPorts.epmd }} + {{- if .Values.metrics.enabled }} + - name: metrics + containerPort: {{ .Values.containerPorts.metrics }} + {{- end }} + {{- if .Values.auth.tls.enabled }} + - name: amqp-tls + containerPort: {{ .Values.containerPorts.amqpTls }} + {{- end }} + {{- if .Values.extraContainerPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraContainerPorts "context" $) | nindent 12 }} + {{- end }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - sh + - -ec + {{- if or (.Values.loadDefinition.enabled) (not (contains "rabbitmq_management" .Values.plugins )) }} + - rabbitmq-diagnostics -q ping + {{- else }} + - curl -f --user {{ .Values.auth.username }}:$RABBITMQ_PASSWORD 127.0.0.1:{{ .Values.containerPorts.manager }}/api/health/checks/virtual-hosts + {{- end }} + {{- end }} + {{- if .Values.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - sh + - -ec + {{- if or (.Values.loadDefinition.enabled) (not (contains "rabbitmq_management" .Values.plugins )) }} + - rabbitmq-diagnostics -q check_running && rabbitmq-diagnostics -q check_local_alarms + {{- else }} + - curl -f --user {{ .Values.auth.username }}:$RABBITMQ_PASSWORD 127.0.0.1:{{ .Values.containerPorts.manager }}/api/health/checks/local-alarms + {{- end }} + {{- end }} + {{- if .Values.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: {{ternary "amqp-tls" "amqp" .Values.auth.tls.enabled }} + {{- end }} + {{- end }} + {{- if .Values.resources }} + resources: {{- toYaml .Values.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: configuration + mountPath: /bitnami/rabbitmq/conf + - name: data + mountPath: {{ .Values.persistence.mountPath }} + {{- if .Values.persistence.subPath }} + subPath: {{ .Values.persistence.subPath }} + {{- end }} + {{- if .Values.auth.tls.enabled }} + - name: certs + mountPath: /opt/bitnami/rabbitmq/certs + {{- end }} + {{- if and .Values.ldap.tls.enabled .Values.ldap.tls.certificatesSecret }} + - name: ldap-certs + mountPath: {{ .Values.ldap.tls.certificatesMountPath }} + {{- end }} + {{- if .Values.loadDefinition.enabled }} + - name: load-definition-volume + mountPath: /app + readOnly: true + {{- end }} + {{- if .Values.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.initScripts }} + - name: custom-init-scripts + mountPath: /docker-entrypoint-initdb.d/init-scripts + {{- end }} + {{- if .Values.initScriptsCM }} + - name: custom-init-scripts-cm + mountPath: /docker-entrypoint-initdb.d/init-scripts-cm + {{- end }} + {{- if .Values.initScriptsSecret }} + - name: custom-init-scripts-secret + mountPath: /docker-entrypoint-initdb.d/init-scripts-secret + {{- end }} + {{- if .Values.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + {{- if .Values.auth.tls.enabled }} + - name: certs + projected: + sources: + - secret: + name: {{ template "rabbitmq.tlsSecretName" . }} + items: + {{- if not .Values.auth.tls.overrideCaCertificate }} + - key: {{ ternary "tls.crt" "ca.crt" .Values.auth.tls.existingSecretFullChain }} + path: ca_certificate.pem + {{- end }} + - key: tls.crt + path: server_certificate.pem + - key: tls.key + path: server_key.pem + {{- if .Values.auth.tls.overrideCaCertificate }} + - secret: + name: {{ .Values.auth.tls.overrideCaCertificate }} + items: + - key: ca.crt + path: ca_certificate.pem + {{- end }} + {{- end }} + {{- if and .Values.ldap.tls.enabled .Values.ldap.tls.certificatesSecret }} + - name: ldap-certs + secret: + secretName: {{ .Values.ldap.tls.certificatesSecret }} + {{- end }} + - name: configuration + projected: + sources: + {{- if or (and (empty .Values.configurationExistingSecret) .Values.configuration) (and (not .Values.advancedConfigurationExistingSecret) .Values.advancedConfiguration) }} + - secret: + name: {{ printf "%s-config" (include "common.names.fullname" .) }} + {{- end }} + {{- if and .Values.advancedConfigurationExistingSecret (not .Values.advancedConfiguration) }} + - secret: + name: {{ tpl .Values.advancedConfigurationExistingSecret . | quote }} + {{- end }} + {{- if not (empty .Values.configurationExistingSecret) }} + - secret: + name: {{ tpl .Values.configurationExistingSecret . | quote }} + {{- end }} + {{- if .Values.loadDefinition.enabled }} + - name: load-definition-volume + secret: + secretName: {{ tpl .Values.loadDefinition.existingSecret . | quote }} + {{- end }} + {{- if .Values.initScripts }} + - name: custom-init-scripts + configMap: + name: {{ template "rabbitmq.initScripts" . }} + {{- end }} + {{- if .Values.initScriptsCM }} + - name: custom-init-scripts-cm + configMap: + name: {{ tpl .Values.initScriptsCM . | quote }} + {{- end }} + {{- if .Values.initScriptsSecret }} + - name: custom-init-scripts-secret + secret: + secretName: {{ tpl .Values.initScriptsSecret . | quote }} + defaultMode: 0755 + {{- end }} + {{- if .Values.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraVolumes "context" $) | nindent 8 }} + {{- end }} + {{- if not .Values.persistence.enabled }} + - name: data + emptyDir: {} + {{- else if .Values.persistence.existingClaim }} + - name: data + persistentVolumeClaim: + {{- with .Values.persistence.existingClaim }} + claimName: {{ tpl . $ }} + {{- end }} + {{- else }} + {{- if .Values.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: data + {{- $claimLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.persistence.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.matchLabels" ( dict "customLabels" $claimLabels "context" $ ) | nindent 10 }} + {{- if .Values.persistence.annotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.persistence.annotations "context" $) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{ include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) }} + {{- if .Values.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.selector "context" $) | nindent 10 }} + {{- end -}} + {{- end }} diff --git a/backing-services/rabbitmq/templates/svc-headless.yaml b/backing-services/rabbitmq/templates/svc-headless.yaml new file mode 100644 index 0000000..f99292a --- /dev/null +++ b/backing-services/rabbitmq/templates/svc-headless.yaml @@ -0,0 +1,42 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-%s" (include "common.names.fullname" .) (default "headless" .Values.servicenameOverride) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.service.annotationsHeadless .Values.commonAnnotations .Values.service.headless.annotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.service.headless.annotations .Values.service.annotationsHeadless .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + clusterIP: None + ports: + - name: {{ .Values.service.portNames.epmd }} + port: {{ .Values.service.ports.epmd }} + targetPort: epmd + {{- if or (.Values.service.portEnabled) (not .Values.auth.tls.enabled) }} + - name: {{ .Values.service.portNames.amqp }} + port: {{ .Values.service.ports.amqp }} + targetPort: amqp + {{- end }} + {{- if .Values.auth.tls.enabled }} + - name: {{ .Values.service.portNames.amqpTls }} + port: {{ .Values.service.ports.amqpTls }} + targetPort: amqp-tls + {{- end }} + - name: {{ .Values.service.portNames.dist }} + port: {{ .Values.service.ports.dist }} + targetPort: dist + {{- if .Values.service.managerPortEnabled }} + - name: {{ .Values.service.portNames.manager }} + port: {{ .Values.service.ports.manager }} + targetPort: stats + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + publishNotReadyAddresses: true diff --git a/backing-services/rabbitmq/templates/svc.yaml b/backing-services/rabbitmq/templates/svc.yaml new file mode 100644 index 0000000..8c89ea7 --- /dev/null +++ b/backing-services/rabbitmq/templates/svc.yaml @@ -0,0 +1,108 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.service.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + {{- if or .Values.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + {{- if not (empty .Values.service.clusterIP) }} + clusterIP: {{ .Values.service.clusterIP }} + {{- end }} + {{- if eq .Values.service.type "LoadBalancer" }} + {{- if not (empty .Values.service.loadBalancerIP) }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + {{- if .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{- toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + allocateLoadBalancerNodePorts: {{ .Values.service.allocateLoadBalancerNodePorts }} + {{- end }} + {{- if or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if .Values.service.sessionAffinity }} + sessionAffinity: {{ .Values.service.sessionAffinity }} + {{- end }} + {{- if .Values.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.service.externalIPs }} + externalIPs: {{- toYaml .Values.service.externalIPs | nindent 4 }} + {{- end }} + ports: + {{- if or (.Values.service.portEnabled) (not .Values.auth.tls.enabled) }} + - name: {{ .Values.service.portNames.amqp }} + port: {{ .Values.service.ports.amqp }} + targetPort: amqp + {{- if (eq .Values.service.type "ClusterIP") }} + nodePort: null + {{- else if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.amqp)) }} + nodePort: {{ .Values.service.nodePorts.amqp }} + {{- end }} + {{- end }} + {{- if .Values.auth.tls.enabled }} + - name: {{ .Values.service.portNames.amqpTls }} + port: {{ .Values.service.ports.amqpTls }} + targetPort: amqp-tls + {{- if (eq .Values.service.type "ClusterIP") }} + nodePort: null + {{- else if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.amqpTls)) }} + nodePort: {{ .Values.service.nodePorts.amqpTls }} + {{- end }} + {{- end }} + {{- if .Values.service.epmdPortEnabled }} + - name: {{ .Values.service.portNames.epmd }} + port: {{ .Values.service.ports.epmd }} + targetPort: epmd + {{- if (eq .Values.service.type "ClusterIP") }} + nodePort: null + {{- else if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.epmd)) }} + nodePort: {{ .Values.service.nodePorts.epmd }} + {{- end }} + {{- end }} + {{- if .Values.service.distPortEnabled }} + - name: {{ .Values.service.portNames.dist }} + port: {{ .Values.service.ports.dist }} + targetPort: dist + {{- if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- else if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.dist)) }} + nodePort: {{ .Values.service.nodePorts.dist }} + {{- end }} + {{- end }} + {{- if .Values.service.managerPortEnabled }} + - name: {{ .Values.service.portNames.manager }} + port: {{ .Values.service.ports.manager }} + targetPort: stats + {{- if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- else if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.manager)) }} + nodePort: {{ .Values.service.nodePorts.manager }} + {{- end }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: {{ .Values.service.portNames.metrics }} + port: {{ .Values.service.ports.metrics }} + targetPort: metrics + {{- if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- else if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.metrics)) }} + nodePort: {{ .Values.service.nodePorts.metrics }} + {{- end }} + {{- end }} + {{- if .Values.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} diff --git a/backing-services/rabbitmq/templates/tls-secrets.yaml b/backing-services/rabbitmq/templates/tls-secrets.yaml new file mode 100644 index 0000000..aafc651 --- /dev/null +++ b/backing-services/rabbitmq/templates/tls-secrets.yaml @@ -0,0 +1,36 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "rabbitmq.createTlsSecret" . ) }} +{{- $secretName := printf "%s-certs" (include "common.names.fullname" .) }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + {{- if not .Values.auth.tls.autoGenerated }} + tls.crt: {{ required "A valid .Values.auth.tls.serverCertificate entry required!" .Values.auth.tls.serverCertificate | b64enc | quote }} + tls.key: {{ required "A valid .Values.auth.tls.serverKey entry required!" .Values.auth.tls.serverKey | b64enc | quote }} + ca.crt: {{ required "A valid .Values.auth.tls.caCertificate entry required!" .Values.auth.tls.caCertificate | b64enc | quote }} + {{- else }} + {{- $ca := genCA "rabbitmq-internal-ca" 365 }} + {{- $fullname := include "common.names.fullname" . }} + {{- $releaseNamespace := .Release.Namespace }} + {{- $clusterDomain := .Values.clusterDomain }} + {{- $serviceName := include "common.names.fullname" . }} + {{- $altNames := list (printf "*.%s.%s.svc.%s" $serviceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $serviceName $releaseNamespace $clusterDomain) $fullname }} + {{- $cert := genSignedCert $fullname nil $altNames 365 $ca }} + tls.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.crt" "defaultValue" $cert.Cert "context" $) }} + tls.key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.key" "defaultValue" $cert.Key "context" $) }} + ca.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }} + {{- end }} +{{- end }} diff --git a/backing-services/rabbitmq/templates/validation.yaml b/backing-services/rabbitmq/templates/validation.yaml new file mode 100644 index 0000000..e0c1abc --- /dev/null +++ b/backing-services/rabbitmq/templates/validation.yaml @@ -0,0 +1,7 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- include "rabbitmq.validateValues" . }} + diff --git a/backing-services/rabbitmq/values.schema.json b/backing-services/rabbitmq/values.schema.json new file mode 100644 index 0000000..8ef33ef --- /dev/null +++ b/backing-services/rabbitmq/values.schema.json @@ -0,0 +1,100 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "auth": { + "type": "object", + "properties": { + "username": { + "type": "string", + "title": "RabbitMQ user", + "form": true + }, + "password": { + "type": "string", + "title": "RabbitMQ password", + "form": true, + "description": "Defaults to a random 10-character alphanumeric string if not set" + } + } + }, + "extraConfiguration": { + "type": "string", + "title": "Extra RabbitMQ Configuration", + "form": true, + "render": "textArea", + "description": "Extra configuration to be appended to RabbitMQ Configuration" + }, + "replicaCount": { + "type": "integer", + "form": true, + "title": "Number of replicas", + "description": "Number of replicas to deploy" + }, + "persistence": { + "type": "object", + "title": "Persistence configuration", + "form": true, + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable persistence", + "description": "Enable persistence using Persistent Volume Claims" + }, + "size": { + "type": "string", + "title": "Persistent Volume Size", + "form": true, + "render": "slider", + "sliderMin": 1, + "sliderMax": 100, + "sliderUnit": "Gi", + "hidden": { + "value": false, + "path": "persistence/enabled" + } + } + } + }, + "volumePermissions": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable Init Containers", + "description": "Use an init container to set required folder permissions on the data volume before mounting it in the final destination" + } + } + }, + "metrics": { + "type": "object", + "form": true, + "title": "Prometheus metrics details", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enable Prometheus metrics for RabbitMQ", + "description": "Install Prometheus plugin in the RabbitMQ container", + "form": true + }, + "serviceMonitor": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Create Prometheus Operator ServiceMonitor", + "description": "Create a ServiceMonitor to track metrics using Prometheus Operator", + "form": true, + "hidden": { + "value": false, + "path": "metrics/enabled" + } + } + } + } + } + } + } +} diff --git a/backing-services/rabbitmq/values.yaml b/backing-services/rabbitmq/values.yaml new file mode 100644 index 0000000..2e36702 --- /dev/null +++ b/backing-services/rabbitmq/values.yaml @@ -0,0 +1,1467 @@ +# Copyright VMware, Inc. +# SPDX-License-Identifier: APACHE-2.0 + +## @section Global parameters +## 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, imagePullSecrets and storageClass +## + +## @param global.imageRegistry Global Docker image registry +## @param global.imagePullSecrets Global Docker registry secret names as an array +## @param global.storageClass Global StorageClass for Persistent Volume(s) +## +global: + imageRegistry: "" + ## E.g. + ## imagePullSecrets: + ## - myRegistryKeySecretName + ## + imagePullSecrets: [] + storageClass: "" + +## @section RabbitMQ Image parameters +## Bitnami RabbitMQ image version +## ref: https://hub.docker.com/r/bitnami/rabbitmq/tags/ +## @param image.registry [default: REGISTRY_NAME] RabbitMQ image registry +## @param image.repository [default: REPOSITORY_NAME/rabbitmq] RabbitMQ image repository +## @skip image.tag RabbitMQ image tag (immutable tags are recommended) +## @param image.digest RabbitMQ image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag +## @param image.pullPolicy RabbitMQ image pull policy +## @param image.pullSecrets Specify docker-registry secret names as an array +## @param image.debug Set to true if you would like to see extra information on logs +## +image: + registry: 172.16.16.1:30516 + repository: bitnami/rabbitmq + tag: 3.12.12-debian-11-r0 + digest: "" + ## set to true if you would like to see extra information on logs + ## It turns BASH and/or NAMI debugging in the image + ## + debug: false + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://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/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + +## @section Common parameters +## + +## @param nameOverride String to partially override rabbitmq.fullname template (will maintain the release name) +## +nameOverride: "" +## @param fullnameOverride String to fully override rabbitmq.fullname template +## +fullnameOverride: "" +## @param namespaceOverride String to fully override common.names.namespace +## +namespaceOverride: "" +## @param kubeVersion Force target Kubernetes version (using Helm capabilities if not set) +## +kubeVersion: "" +## @param clusterDomain Kubernetes Cluster Domain +## +clusterDomain: cluster.local +## @param extraDeploy Array of extra objects to deploy with the release +## +extraDeploy: [] +## @param commonAnnotations Annotations to add to all deployed objects +## +commonAnnotations: {} +## @param servicenameOverride String to partially override headless service name +## +servicenameOverride: "" +## @param commonLabels Labels to add to all deployed objects +## +commonLabels: {} + +## @param serviceBindings.enabled Create secret for service binding (Experimental) +## Ref: https://servicebinding.io/service-provider/ +## +serviceBindings: + enabled: false + +## @param enableServiceLinks Whether information about services should be injected into pod's environment variable +## The environment variables injected by service links are not used, but can lead to slow boot times or slow running of the scripts when there are many services in the current namespace. +## If you experience slow pod startups or slow running of the scripts you probably want to set this to `false`. +## +enableServiceLinks: true + +## Enable diagnostic mode in the deployment +## +diagnosticMode: + ## @param diagnosticMode.enabled Enable diagnostic mode (all probes will be disabled and the command will be overridden) + ## + enabled: false + ## @param diagnosticMode.command Command to override all containers in the deployment + ## + command: + - sleep + ## @param diagnosticMode.args Args to override all containers in the deployment + ## + args: + - infinity + +## @param hostAliases Deployment pod host aliases +## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ +## +hostAliases: [] +## @param dnsPolicy DNS Policy for pod +## ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/ +## E.g. +## dnsPolicy: ClusterFirst +## +dnsPolicy: "" +## @param dnsConfig DNS Configuration pod +## ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/ +## E.g. +## dnsConfig: +## options: +## - name: ndots +## value: "4" +## +dnsConfig: {} +## RabbitMQ Authentication parameters +## +auth: + ## @param auth.username RabbitMQ application username + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/rabbitmq#environment-variables + ## + username: admin + ## @param auth.password RabbitMQ application password + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/rabbitmq#environment-variables + ## + password: "admin" + ## @param auth.securePassword Whether to set the RabbitMQ password securely. This is incompatible with loading external RabbitMQ definitions and 'true' when not setting the auth.password parameter. + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/rabbitmq#environment-variables + ## + securePassword: true + ## @param auth.existingPasswordSecret Existing secret with RabbitMQ credentials (must contain a value for `rabbitmq-password` key) + ## e.g: + ## existingPasswordSecret: name-of-existing-secret + ## + existingPasswordSecret: "" + ## @param auth.enableLoopbackUser If enabled, the user `auth.username` can only connect from localhost + ## + enableLoopbackUser: false + ## @param auth.erlangCookie Erlang cookie to determine whether different nodes are allowed to communicate with each other + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/rabbitmq#environment-variables + ## + erlangCookie: "" + ## @param auth.existingErlangSecret Existing secret with RabbitMQ Erlang cookie (must contain a value for `rabbitmq-erlang-cookie` key) + ## e.g: + ## existingErlangSecret: name-of-existing-secret + ## + existingErlangSecret: "" + + ## Enable encryption to rabbitmq + ## ref: https://www.rabbitmq.com/ssl.html + ## @param auth.tls.enabled Enable TLS support on RabbitMQ + ## @param auth.tls.autoGenerated Generate automatically self-signed TLS certificates + ## @param auth.tls.failIfNoPeerCert When set to true, TLS connection will be rejected if client fails to provide a certificate + ## @param auth.tls.sslOptionsVerify Should [peer verification](https://www.rabbitmq.com/ssl.html#peer-verification) be enabled? + ## @param auth.tls.sslOptionsPassword.enabled Enable usage of password for private Key + ## @param auth.tls.sslOptionsPassword.existingSecret Name of existing Secret containing the sslOptionsPassword + ## @param auth.tls.sslOptionsPassword.key Enable Key referring to sslOptionsPassword in Secret specified in auth.tls.sslOptionsPassword.existingSecret + ## @param auth.tls.sslOptionsPassword.password Use this string as Password. If set, auth.tls.sslOptionsPassword.existingSecret and auth.tls.sslOptionsPassword.key are ignored + ## @param auth.tls.caCertificate Certificate Authority (CA) bundle content + ## @param auth.tls.serverCertificate Server certificate content + ## @param auth.tls.serverKey Server private key content + ## @param auth.tls.existingSecret Existing secret with certificate content to RabbitMQ credentials + ## @param auth.tls.existingSecretFullChain Whether or not the existing secret contains the full chain in the certificate (`tls.crt`). Will be used in place of `ca.cert` if `true`. + ## @param auth.tls.overrideCaCertificate Existing secret with certificate content be mounted instead of the `ca.crt` coming from caCertificate or existingSecret/existingSecretFullChain. + ## + tls: + enabled: false + autoGenerated: false + failIfNoPeerCert: true + sslOptionsVerify: verify_peer + sslOptionsPassword: + enabled: false + existingSecret: "" + key: "" + password: "" + caCertificate: "" + serverCertificate: "" + serverKey: "" + existingSecret: "" + existingSecretFullChain: false + overrideCaCertificate: "" + +## @param logs Path of the RabbitMQ server's Erlang log file. Value for the `RABBITMQ_LOGS` environment variable +## ref: https://www.rabbitmq.com/logging.html#log-file-location +## +logs: "-" +## @param ulimitNofiles RabbitMQ Max File Descriptors +## ref: https://github.com/bitnami/containers/tree/main/bitnami/rabbitmq#environment-variables +## ref: https://www.rabbitmq.com/install-debian.html#kernel-resource-limits +## +ulimitNofiles: "65536" +## RabbitMQ maximum available scheduler threads and online scheduler threads. By default it will create a thread per CPU detected, with the following parameters you can tune it manually. +## ref: https://hamidreza-s.github.io/erlang/scheduling/real-time/preemptive/migration/2016/02/09/erlang-scheduler-details.html#scheduler-threads +## ref: https://github.com/bitnami/charts/issues/2189 +## @param maxAvailableSchedulers RabbitMQ maximum available scheduler threads +## @param onlineSchedulers RabbitMQ online scheduler threads +## +maxAvailableSchedulers: "" +onlineSchedulers: "" + +## The memory threshold under which RabbitMQ will stop reading from client network sockets, in order to avoid being killed by the OS +## ref: https://www.rabbitmq.com/alarms.html +## ref: https://www.rabbitmq.com/memory.html#threshold +## +memoryHighWatermark: + ## @param memoryHighWatermark.enabled Enable configuring Memory high watermark on RabbitMQ + ## + enabled: false + ## @param memoryHighWatermark.type Memory high watermark type. Either `absolute` or `relative` + ## + type: "relative" + ## Memory high watermark value. + ## @param memoryHighWatermark.value Memory high watermark value + ## The default value of 0.4 stands for 40% of available RAM + ## Note: the memory relative limit is applied to the resource.limits.memory to calculate the memory threshold + ## You can also use an absolute value, e.g.: 256MB + ## + value: 0.4 + +## @param plugins List of default plugins to enable (should only be altered to remove defaults; for additional plugins use `extraPlugins`) +## +plugins: "rabbitmq_management rabbitmq_peer_discovery_k8s" +## @param communityPlugins List of Community plugins (URLs) to be downloaded during container initialization +## Combine it with extraPlugins to also enable them. +## +communityPlugins: "" +## @param extraPlugins Extra plugins to enable (single string containing a space-separated list) +## Use this instead of `plugins` to add new plugins +## +extraPlugins: "rabbitmq_auth_backend_ldap" + +## Clustering settings +## +clustering: + ## @param clustering.enabled Enable RabbitMQ clustering + ## + enabled: true + ## @param clustering.name RabbitMQ cluster name + ## If not set, a name is generated using the common.names.fullname template + ## + name: "" + ## @param clustering.addressType Switch clustering mode. Either `ip` or `hostname` + ## + addressType: hostname + ## @param clustering.rebalance Rebalance master for queues in cluster when new replica is created + ## ref: https://www.rabbitmq.com/rabbitmq-queues.8.html#rebalance + ## + rebalance: false + ## @param clustering.forceBoot Force boot of an unexpectedly shut down cluster (in an unexpected order). + ## forceBoot executes 'rabbitmqctl force_boot' to force boot cluster shut down unexpectedly in an unknown order + ## ref: https://www.rabbitmq.com/rabbitmqctl.8.html#force_boot + ## + forceBoot: false + ## @param clustering.partitionHandling Switch Partition Handling Strategy. Either `autoheal` or `pause_minority` or `pause_if_all_down` or `ignore` + ## ref: https://www.rabbitmq.com/partitions.html#automatic-handling + ## + partitionHandling: autoheal + +## Loading a RabbitMQ definitions file to configure RabbitMQ +## +loadDefinition: + ## @param loadDefinition.enabled Enable loading a RabbitMQ definitions file to configure RabbitMQ + ## + enabled: false + ## @param loadDefinition.file Name of the definitions file + ## + file: "/app/load_definition.json" + ## @param loadDefinition.existingSecret Existing secret with the load definitions file + ## Can be templated if needed, e.g: + ## existingSecret: "{{ .Release.Name }}-load-definition" + ## + existingSecret: "" + +## @param command Override default container command (useful when using custom images) +## +command: [] +## @param args Override default container args (useful when using custom images) +## +args: [] +## @param lifecycleHooks Overwrite livecycle for the RabbitMQ container(s) to automate configuration before or after startup +## +lifecycleHooks: {} +## @param terminationGracePeriodSeconds Default duration in seconds k8s waits for container to exit before sending kill signal. +## Any time in excess of 10 seconds will be spent waiting for any synchronization necessary for cluster not to lose data. +## +terminationGracePeriodSeconds: 120 +## @param extraEnvVars Extra environment variables to add to RabbitMQ pods +## E.g: +## extraEnvVars: +## - name: FOO +## value: BAR +## +extraEnvVars: [] +## @param extraEnvVarsCM Name of existing ConfigMap containing extra environment variables +## +extraEnvVarsCM: "" +## @param extraEnvVarsSecret Name of existing Secret containing extra environment variables (in case of sensitive data) +## +extraEnvVarsSecret: "" + +## Container Ports +## @param containerPorts.amqp +## @param containerPorts.amqpTls +## @param containerPorts.dist +## @param containerPorts.manager +## @param containerPorts.epmd +## @param containerPorts.metrics +## +containerPorts: + amqp: 5672 + amqpTls: 5671 + dist: 25672 + manager: 15672 + epmd: 4369 + metrics: 9419 + +## @param initScripts Dictionary of init scripts. Evaluated as a template. +## Specify dictionary of scripts to be run at first boot +## Alternatively, you can put your scripts under the files/docker-entrypoint-initdb.d directory +## For example: +## initScripts: +## my_init_script.sh: | +## #!/bin/sh +## echo "Do something." +## +initScripts: {} +## @param initScriptsCM ConfigMap with the init scripts. Evaluated as a template. +## Note: This will override initScripts +## +initScriptsCM: "" +## @param initScriptsSecret Secret containing `/docker-entrypoint-initdb.d` scripts to be executed at initialization time that contain sensitive data. Evaluated as a template. +## +initScriptsSecret: "" +## @param extraContainerPorts Extra ports to be included in container spec, primarily informational +## E.g: +## extraContainerPorts: +## - name: new_port_name +## containerPort: 1234 +## +extraContainerPorts: [] +## @param configuration [string] RabbitMQ Configuration file content: required cluster configuration +## Do not override unless you know what you are doing. +## To add more configuration, use `extraConfiguration` of `advancedConfiguration` instead +## + +## RabbitMQ tcp_listen_options parameters +## See : https://www.rabbitmq.com/networking.html for additional information +## +tcpListenOptions: + ## @param tcpListenOptions.backlog Maximum size of the unaccepted TCP connections queue + ## + backlog: 128 + ## @param tcpListenOptions.nodelay When set to true, deactivates Nagle's algorithm. Default is true. Highly recommended for most users. + ## + nodelay: true + ## tcpListenOptions.linger + ## + linger: + ## @param tcpListenOptions.linger.lingerOn Enable Server socket lingering + ## + lingerOn: true + ## @param tcpListenOptions.linger.timeout Server Socket lingering timeout + ## + timeout: 0 + ## @param tcpListenOptions.keepalive When set to true, enables TCP keepalives + ## + keepalive: false + +configuration: |- + ## Username and password + ## + default_user = {{ .Values.auth.username }} + {{- if and (not .Values.auth.securePassword) .Values.auth.password }} + default_pass = {{ .Values.auth.password }} + {{- end }} + {{- if .Values.clustering.enabled }} + ## Clustering + ## + cluster_name = {{ default (include "common.names.fullname" .) .Values.clustering.name }} + cluster_formation.peer_discovery_backend = rabbit_peer_discovery_k8s + cluster_formation.k8s.host = kubernetes.default + cluster_formation.k8s.address_type = {{ .Values.clustering.addressType }} + {{- $svcName := printf "%s-%s" (include "common.names.fullname" .) (default "headless" .Values.servicenameOverride) }} + cluster_formation.k8s.service_name = {{ $svcName }} + cluster_formation.k8s.hostname_suffix = .{{ $svcName }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }} + cluster_formation.node_cleanup.interval = 10 + cluster_formation.node_cleanup.only_log_warning = true + cluster_partition_handling = {{ .Values.clustering.partitionHandling }} + {{- end }} + {{ if and .Values.clustering.enabled .Values.loadDefinition.enabled }} + cluster_formation.target_cluster_size_hint = {{ .Values.replicaCount }} + {{ end }} + {{- if .Values.loadDefinition.enabled }} + load_definitions = {{ .Values.loadDefinition.file }} + {{- end }} + # queue master locator + queue_master_locator = min-masters + # enable loopback user + {{- if not (empty .Values.auth.username) }} + loopback_users.{{ .Values.auth.username }} = {{ .Values.auth.enableLoopbackUser }} + {{- else}} + loopback_users.guest = {{ .Values.auth.enableLoopbackUser }} + {{- end }} + {{ template "rabbitmq.extraConfiguration" . }} + {{- if .Values.auth.tls.enabled }} + ssl_options.verify = {{ .Values.auth.tls.sslOptionsVerify }} + listeners.ssl.default = {{ .Values.service.ports.amqpTls }} + ssl_options.fail_if_no_peer_cert = {{ .Values.auth.tls.failIfNoPeerCert }} + ssl_options.cacertfile = /opt/bitnami/rabbitmq/certs/ca_certificate.pem + ssl_options.certfile = /opt/bitnami/rabbitmq/certs/server_certificate.pem + ssl_options.keyfile = /opt/bitnami/rabbitmq/certs/server_key.pem + {{- if .Values.auth.tls.sslOptionsPassword.enabled }} + ssl_options.password = {{ template "rabbitmq.tlsSslOptionsPassword" . }} + {{- end }} + {{- end }} + {{- if .Values.ldap.enabled }} + auth_backends.1.authn = ldap + auth_backends.1.authz = {{ ternary "ldap" "internal" .Values.ldap.authorisationEnabled }} + auth_backends.2 = internal + {{- $host := list }} + {{- $port := ternary 636 389 .Values.ldap.tls.enabled }} + {{- if .Values.ldap.uri }} + {{- $hostPort := get (urlParse .Values.ldap.uri) "host" }} + {{- $host = list (index (splitList ":" $hostPort) 0) -}} + {{- if (contains ":" $hostPort) }} + {{- $port = index (splitList ":" $hostPort) 1 -}} + {{- end }} + {{- end }} + {{- range $index, $server := concat $host .Values.ldap.servers }} + auth_ldap.servers.{{ add $index 1 }} = {{ $server }} + {{- end }} + auth_ldap.port = {{ coalesce .Values.ldap.port $port }} + {{- if or .Values.ldap.user_dn_pattern .Values.ldap.userDnPattern }} + auth_ldap.user_dn_pattern = {{ coalesce .Values.ldap.user_dn_pattern .Values.ldap.userDnPattern }} + {{- end }} + {{- if .Values.ldap.basedn }} + auth_ldap.dn_lookup_base = {{ .Values.ldap.basedn }} + {{- end }} + {{- if .Values.ldap.uidField }} + auth_ldap.dn_lookup_attribute = {{ .Values.ldap.uidField }} + {{- end }} + {{- if .Values.ldap.binddn }} + auth_ldap.dn_lookup_bind.user_dn = {{ .Values.ldap.binddn }} + auth_ldap.dn_lookup_bind.password = {{ required "'ldap.bindpw' is required when 'ldap.binddn' is defined" .Values.ldap.bindpw }} + {{- end }} + {{- if .Values.ldap.tls.enabled }} + auth_ldap.use_ssl = {{ not .Values.ldap.tls.startTls }} + auth_ldap.use_starttls = {{ .Values.ldap.tls.startTls }} + {{- if .Values.ldap.tls.CAFilename }} + auth_ldap.ssl_options.cacertfile = {{ .Values.ldap.tls.certificatesMountPath }}/{{ .Values.ldap.tls.CAFilename }} + {{- end }} + {{- if .Values.ldap.tls.certFilename }} + auth_ldap.ssl_options.certfile = {{ .Values.ldap.tls.certificatesMountPath }}/{{ .Values.ldap.tls.certFilename }} + auth_ldap.ssl_options.keyfile = {{ .Values.ldap.tls.certificatesMountPath }}/{{ required "'ldap.tls.certKeyFilename' is required when 'ldap.tls.certFilename' is defined" .Values.ldap.tls.certKeyFilename }} + {{- end }} + {{- if .Values.ldap.tls.skipVerify }} + auth_ldap.ssl_options.verify = verify_none + auth_ldap.ssl_options.fail_if_no_peer_cert = false + {{- else if .Values.ldap.tls.verify }} + auth_ldap.ssl_options.verify = {{ .Values.ldap.tls.verify }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.metrics.enabled }} + ## Prometheus metrics + ## + prometheus.tcp.port = {{ .Values.containerPorts.metrics }} + {{- end }} + {{- if .Values.memoryHighWatermark.enabled }} + ## Memory Threshold + ## + total_memory_available_override_value = {{ include "rabbitmq.toBytes" .Values.resources.limits.memory }} + vm_memory_high_watermark.{{ .Values.memoryHighWatermark.type }} = {{ .Values.memoryHighWatermark.value }} + ## TCP Listen Options + ## + tcp_listen_options.backlog = {{ .Values.tcpListenOptions.backlog }} + tcp_listen_options.nodelay = {{ .Values.tcpListenOptions.nodelay }} + tcp_listen_options.linger.on = {{ .Values.tcpListenOptions.linger.lingerOn }} + tcp_listen_options.linger.timeout = {{ .Values.tcpListenOptions.linger.timeout }} + tcp_listen_options.keepalive = {{ .Values.tcpListenOptions.keepalive }} + {{- end }} + +## @param configurationExistingSecret Existing secret with the configuration to use as rabbitmq.conf. +## Must contain the key "rabbitmq.conf" +## Takes precedence over `configuration`, so do not use both simultaneously +## With providing an existingSecret, extraConfiguration and extraConfigurationExistingSecret do not take any effect +## +configurationExistingSecret: "" + +## @param extraConfiguration [string] Configuration file content: extra configuration to be appended to RabbitMQ configuration +## Use this instead of `configuration` to add more configuration +## Do not use simultaneously with `extraConfigurationExistingSecret` +## +extraConfiguration: |- + #default_vhost = {{ .Release.Namespace }}-vhost + #disk_free_limit.absolute = 50MB + +## @param extraConfigurationExistingSecret Existing secret with the extra configuration to append to `configuration`. +## Must contain the key "extraConfiguration" +## Takes precedence over `extraConfiguration`, so do not use both simultaneously +## +extraConfigurationExistingSecret: "" + +## @param advancedConfiguration Configuration file content: advanced configuration +## Use this as additional configuration in classic config format (Erlang term configuration format) +## +## LDAP authorisation example: +## advancedConfiguration: |- +## [{rabbitmq_auth_backend_ldap,[ +## {tag_queries, [{administrator, {constant, true}}, +## {management, {constant, true}}]} +## ]}]. +## +## If both, advancedConfiguration and advancedConfigurationExistingSecret are set, then advancedConfiguration +## will be used instead of the secret. +# +advancedConfiguration: |- + +## @param advancedConfigurationExistingSecret Existing secret with the advanced configuration file (must contain a key `advanced.config`). +## Use this as additional configuration in classic config format (Erlang term configuration format) as in advancedConfiguration +## Do not use in combination with advancedConfiguration, will be ignored +## +advancedConfigurationExistingSecret: "" + +## This subsystem was introduced in RabbitMQ 3.8.0 to allow rolling upgrades of cluster members without shutting down the entire cluster. +## Feature flags are a mechanism that controls what features are considered to be enabled or available on all cluster nodes. If a feature flag is enabled, so is its associated feature (or behavior). If not then all nodes in the cluster will disable the feature (behavior). +## e.g, drop_unroutable_metric,empty_basic_get_metric,implicit_default_bindings,maintenance_mode_status,quorum_queue,virtual_host_metadata +## @param featureFlags that controls what features are considered to be enabled or available on all cluster nodes. +## +featureFlags: "" + +## LDAP configuration +## +ldap: + ## @param ldap.enabled Enable LDAP support + ## + enabled: false + ## @param ldap.uri LDAP connection string. + ## + uri: "" + ## @param ldap.servers List of LDAP servers hostnames. This is valid only if ldap.uri is not set + ## + servers: [] + ## @param ldap.port LDAP servers port. This is valid only if ldap.uri is not set + ## + port: "" + + ## DEPRECATED ldap.user_dn_pattern it will removed in a future, please use userDnPattern instead + ## Pattern used to translate the provided username into a value to be used for the LDAP bind + ## @param ldap.userDnPattern Pattern used to translate the provided username into a value to be used for the LDAP bind. + ## ref: https://www.rabbitmq.com/ldap.html#usernames-and-dns + ## + userDnPattern: "" + ## @param ldap.binddn DN of the account used to search in the LDAP server. + ## + binddn: "" + ## @param ldap.bindpw Password for binddn account. + ## + bindpw: "" + ## @param ldap.basedn Base DN path where binddn account will search for the users. + ## + basedn: "" + ## @param ldap.uidField Field used to match with the user name (uid, samAccountName, cn, etc). It matches with 'dn_lookup_attribute' in RabbitMQ configuration + ##��ref: https://www.rabbitmq.com/ldap.html#usernames-and-dns + ## + ## @param ldap.uidField Field used to match with the user name (uid, samAccountName, cn, etc). It matches with 'dn_lookup_attribute' in RabbitMQ configuration + ## + uidField: "" + ## @param ldap.authorisationEnabled Enable LDAP authorisation. Please set 'advancedConfiguration' with tag, topic, resources and vhost mappings + ## ref: https://www.rabbitmq.com/ldap.html#authorisation + ## + authorisationEnabled: false + ## @param ldap.tls.enabled Enabled TLS configuration. + ## @param ldap.tls.startTls Use STARTTLS instead of LDAPS. + ## @param ldap.tls.skipVerify Skip any SSL verification (hostanames or certificates) + ## @param ldap.tls.verify Verify connection. Valid values are 'verify_peer' or 'verify_none' + ## @param ldap.tls.certificatesMountPath Where LDAP certifcates are mounted. + ## @param ldap.tls.certificatesSecret Secret with LDAP certificates. + ## @param ldap.tls.CAFilename CA certificate filename. Should match with the CA entry key in the ldap.tls.certificatesSecret. + ## @param ldap.tls.certFilename Client certificate filename to authenticate against the LDAP server. Should match with certificate the entry key in the ldap.tls.certificatesSecret. + ## @param ldap.tls.certKeyFilename Client Key filename to authenticate against the LDAP server. Should match with certificate the entry key in the ldap.tls.certificatesSecret. + ## + tls: + enabled: false + startTls: false + skipVerify: false + verify: "verify_peer" + certificatesMountPath: /opt/bitnami/rabbitmq/ldap/certs + certificatesSecret: "" + CAFilename: "" + certFilename: "" + certKeyFilename: "" + +## @param extraVolumeMounts Optionally specify extra list of additional volumeMounts +## Examples: +## extraVolumeMounts: +## - name: extras +## mountPath: /usr/share/extras +## readOnly: true +## +extraVolumeMounts: [] +## @param extraVolumes Optionally specify extra list of additional volumes . +## Example: +## extraVolumes: +## - name: extras +## emptyDir: {} +## +extraVolumes: [] +## @param extraSecrets Optionally specify extra secrets to be created by the chart. +## This can be useful when combined with load_definitions to automatically create the secret containing the definitions to be loaded. +## Example: +## extraSecrets: +## load-definition: +## load_definition.json: | +## { +## ... +## } +## +extraSecrets: {} +## @param extraSecretsPrependReleaseName Set this flag to true if extraSecrets should be created with prepended. +## +extraSecretsPrependReleaseName: false + +## @section Statefulset parameters +## + +## @param replicaCount Number of RabbitMQ replicas to deploy +## +replicaCount: 1 +## @param schedulerName Use an alternate scheduler, e.g. "stork". +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +schedulerName: "" +## RabbitMQ should be initialized one by one when building cluster for the first time. +## Therefore, the default value of podManagementPolicy is 'OrderedReady' +## Once the RabbitMQ participates in the cluster, it waits for a response from another +## RabbitMQ in the same cluster at reboot, except the last RabbitMQ of the same cluster. +## If the cluster exits gracefully, you do not need to change the podManagementPolicy +## because the first RabbitMQ of the statefulset always will be last of the cluster. +## However if the last RabbitMQ of the cluster is not the first RabbitMQ due to a failure, +## you must change podManagementPolicy to 'Parallel'. +## ref : https://www.rabbitmq.com/clustering.html#restarting +## @param podManagementPolicy Pod management policy +## +podManagementPolicy: OrderedReady +## @param podLabels RabbitMQ Pod labels. Evaluated as a template +## Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +## +podLabels: {} +## @param podAnnotations RabbitMQ Pod annotations. Evaluated as a template +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +## +podAnnotations: {} +## @param updateStrategy.type Update strategy type for RabbitMQ statefulset +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies +## +updateStrategy: + ## StrategyType + ## Can be set to RollingUpdate or OnDelete + ## + type: RollingUpdate +## @param statefulsetLabels RabbitMQ statefulset labels. Evaluated as a template +## Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +## +statefulsetLabels: {} +## @param statefulsetAnnotations RabbitMQ statefulset annotations. Evaluated as a template +## Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +## +statefulsetAnnotations: {} +## @param priorityClassName Name of the priority class to be used by RabbitMQ pods, priority class needs to be created beforehand +## Ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ +## +priorityClassName: "" +## @param podAffinityPreset Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## +podAffinityPreset: "" +## @param podAntiAffinityPreset Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` +## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## +podAntiAffinityPreset: soft + +## Node affinity preset +## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity +## +nodeAffinityPreset: + ## @param nodeAffinityPreset.type Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param nodeAffinityPreset.key Node label key to match Ignored if `affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param nodeAffinityPreset.values Node label values to match. Ignored if `affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + +## @param affinity Affinity for pod assignment. Evaluated as a template +## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +## Note: podAffinityPreset, podAntiAffinityPreset, and nodeAffinityPreset will be ignored when it's set +## +affinity: {} +## @param nodeSelector Node labels for pod assignment. Evaluated as a template +## ref: https://kubernetes.io/docs/user-guide/node-selection/ +## +nodeSelector: {} +## @param tolerations Tolerations for pod assignment. Evaluated as a template +## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +## +tolerations: [] +## @param topologySpreadConstraints Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template +## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#spread-constraints-for-pods +## +topologySpreadConstraints: [] + +## RabbitMQ pods' Security Context +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod +## @param podSecurityContext.enabled Enable RabbitMQ pods' Security Context +## @param podSecurityContext.fsGroup Set RabbitMQ pod's Security Context fsGroup +## +podSecurityContext: + enabled: true + fsGroup: 1001 + +## @param containerSecurityContext.enabled Enabled RabbitMQ containers' Security Context +## @param containerSecurityContext.runAsUser Set RabbitMQ containers' Security Context runAsUser +## @param containerSecurityContext.runAsNonRoot Set RabbitMQ container's Security Context runAsNonRoot +## @param containerSecurityContext.allowPrivilegeEscalation Set container's privilege escalation +## @param containerSecurityContext.capabilities.drop Set container's Security Context runAsNonRoot +## @param containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container +## Example: +## containerSecurityContext: +## capabilities: +## drop: ["NET_RAW"] +## readOnlyRootFilesystem: true +## +containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + +## RabbitMQ containers' resource requests and limits +## ref: https://kubernetes.io/docs/user-guide/compute-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:'. +## @param resources.limits The resources limits for RabbitMQ containers +## @param resources.requests The requested resources for RabbitMQ containers +## +resources: + ## Example: + ## limits: + ## cpu: 1000m + ## memory: 2Gi + ## + limits: {} + ## Examples: + ## requests: + ## cpu: 1000m + ## memory: 2Gi + ## + requests: {} + +## Configure RabbitMQ containers' extra options for liveness probe +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes +## @param livenessProbe.enabled Enable livenessProbe +## @param livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe +## @param livenessProbe.periodSeconds Period seconds for livenessProbe +## @param livenessProbe.timeoutSeconds Timeout seconds for livenessProbe +## @param livenessProbe.failureThreshold Failure threshold for livenessProbe +## @param livenessProbe.successThreshold Success threshold for livenessProbe +## +livenessProbe: + enabled: false + initialDelaySeconds: 120 + timeoutSeconds: 20 + periodSeconds: 30 + failureThreshold: 6 + successThreshold: 1 +## Configure RabbitMQ containers' extra options for readiness probe +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes +## @param readinessProbe.enabled Enable readinessProbe +## @param readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe +## @param readinessProbe.periodSeconds Period seconds for readinessProbe +## @param readinessProbe.timeoutSeconds Timeout seconds for readinessProbe +## @param readinessProbe.failureThreshold Failure threshold for readinessProbe +## @param readinessProbe.successThreshold Success threshold for readinessProbe +## +readinessProbe: + enabled: false + initialDelaySeconds: 10 + timeoutSeconds: 20 + periodSeconds: 30 + failureThreshold: 3 + successThreshold: 1 + +## Configure RabbitMQ containers' extra options for startup probe +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes +## @param startupProbe.enabled Enable startupProbe +## @param startupProbe.initialDelaySeconds Initial delay seconds for startupProbe +## @param startupProbe.periodSeconds Period seconds for startupProbe +## @param startupProbe.timeoutSeconds Timeout seconds for startupProbe +## @param startupProbe.failureThreshold Failure threshold for startupProbe +## @param startupProbe.successThreshold Success threshold for startupProbe +## +startupProbe: + enabled: false + initialDelaySeconds: 10 + timeoutSeconds: 20 + periodSeconds: 30 + failureThreshold: 3 + successThreshold: 1 + +## @param customLivenessProbe Override default liveness probe +## +customLivenessProbe: {} +## @param customReadinessProbe Override default readiness probe +## +customReadinessProbe: {} +## @param customStartupProbe Define a custom startup probe +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-startup-probes +## +customStartupProbe: {} +## @param initContainers Add init containers to the RabbitMQ pod +## Example: +## initContainers: +## - name: your-image-name +## image: your-image +## imagePullPolicy: Always +## ports: +## - name: portname +## containerPort: 1234 +## +initContainers: [] +## @param sidecars Add sidecar containers to the RabbitMQ pod +## Example: +## sidecars: +## - name: your-image-name +## image: your-image +## imagePullPolicy: Always +## ports: +## - name: portname +## containerPort: 1234 +## +sidecars: [] + +## Pod Disruption Budget configuration +## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ +## +pdb: + ## @param pdb.create Enable/disable a Pod Disruption Budget creation + ## + create: false + ## @param pdb.minAvailable Minimum number/percentage of pods that should remain scheduled + ## + minAvailable: 1 + ## @param pdb.maxUnavailable Maximum number/percentage of pods that may be made unavailable + ## + maxUnavailable: "" + +## @section RBAC parameters +## + +## RabbitMQ pods ServiceAccount +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ +## +serviceAccount: + create: false + name: "" + namespace: "default" + awsRoleArn: "" + owner: "" + automountServiceAccountToken: true + annotations: {} + +## Role Based Access +## ref: https://kubernetes.io/docs/admin/authorization/rbac/ +## +rbac: + ## @param rbac.create Whether RBAC rules should be created + ## binding RabbitMQ ServiceAccount to a role + ## that allows RabbitMQ pods querying the K8s API + ## + create: true + +## @section Persistence parameters +## + +persistence: + ## @param persistence.enabled Enable RabbitMQ data persistence using PVC + ## + enabled: true + ## @param persistence.storageClass PVC Storage Class for RabbitMQ data volume + ## 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: "" + ## @param persistence.selector Selector to match an existing Persistent Volume + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## @param persistence.accessModes PVC Access Modes for RabbitMQ data volume + ## + accessModes: + - ReadWriteOnce + ## @param persistence.existingClaim Provide an existing PersistentVolumeClaims + ## The value is evaluated as a template + ## So, for example, the name can depend on .Release or .Chart + ## + existingClaim: "" + ## @param persistence.mountPath The path the volume will be mounted at + ## Note: useful when using custom RabbitMQ images + ## + mountPath: /bitnami/rabbitmq/mnesia + ## @param persistence.subPath The subdirectory of the volume to mount to + ## Useful in dev environments and one PV for multiple services + ## + subPath: "" + ## @param persistence.size PVC Storage Request for RabbitMQ data volume + ## If you change this value, you might have to adjust `rabbitmq.diskFreeLimit` as well + ## + size: 8Gi + ## @param persistence.annotations Persistence annotations. Evaluated as a template + ## Example: + ## annotations: + ## example.io/disk-volume-type: SSD + ## + annotations: {} + ## @param persistence.labels Persistence labels. Evaluated as a template + ## Example: + ## labels: + ## app: my-app + labels: {} + +## Persistent Volume Claim Retention Policy +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention +## +persistentVolumeClaimRetentionPolicy: + ## @param persistentVolumeClaimRetentionPolicy.enabled Enable Persistent volume retention policy for rabbitmq Statefulset + ## + enabled: false + ## @param persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced + ## + whenScaled: Retain + ## @param persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted + ## + whenDeleted: Retain + +## @section Exposure parameters +## + +## Kubernetes service type +## +service: + ## @param service.type Kubernetes Service type + ## + type: ClusterIP + + ## @param service.portEnabled Amqp port. Cannot be disabled when `auth.tls.enabled` is `false`. Listener can be disabled with `listeners.tcp = none`. + ## + portEnabled: true + ## @param service.distPortEnabled Erlang distribution server port + ## + distPortEnabled: true + ## @param service.managerPortEnabled RabbitMQ Manager port + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/rabbitmq#environment-variables + ## + managerPortEnabled: true + ## @param service.epmdPortEnabled RabbitMQ EPMD Discovery service port + ## + epmdPortEnabled: true + ## Service ports + ## @param service.ports.amqp Amqp service port + ## @param service.ports.amqpTls Amqp TLS service port + ## @param service.ports.dist Erlang distribution service port + ## @param service.ports.manager RabbitMQ Manager service port + ## @param service.ports.metrics RabbitMQ Prometheues metrics service port + ## @param service.ports.epmd EPMD Discovery service port + ## + ports: + amqp: 5672 + amqpTls: 5671 + dist: 25672 + manager: 15672 + metrics: 9419 + epmd: 4369 + ## Service ports name + ## @param service.portNames.amqp Amqp service port name + ## @param service.portNames.amqpTls Amqp TLS service port name + ## @param service.portNames.dist Erlang distribution service port name + ## @param service.portNames.manager RabbitMQ Manager service port name + ## @param service.portNames.metrics RabbitMQ Prometheues metrics service port name + ## @param service.portNames.epmd EPMD Discovery service port name + ## + portNames: + amqp: "amqp" + amqpTls: "amqp-tls" + dist: "dist" + manager: "http-stats" + metrics: "metrics" + epmd: "epmd" + + ## Node ports to expose + ## @param service.nodePorts.amqp Node port for Ampq + ## @param service.nodePorts.amqpTls Node port for Ampq TLS + ## @param service.nodePorts.dist Node port for Erlang distribution + ## @param service.nodePorts.manager Node port for RabbitMQ Manager + ## @param service.nodePorts.epmd Node port for EPMD Discovery + ## @param service.nodePorts.metrics Node port for RabbitMQ Prometheues metrics + ## + nodePorts: + amqp: "" + amqpTls: "" + dist: "" + manager: "" + epmd: "" + metrics: "" + ## @param service.extraPorts Extra ports to expose in the service + ## E.g.: + ## extraPorts: + ## - name: new_svc_name + ## port: 1234 + ## targetPort: 1234 + ## + extraPorts: [] + ## @param service.loadBalancerSourceRanges Address(es) that are allowed when service is `LoadBalancer` + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param service.allocateLoadBalancerNodePorts Whether to allocate node ports when service type is LoadBalancer + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-nodeport-allocation + ## + allocateLoadBalancerNodePorts: true + ## @param service.externalIPs Set the ExternalIPs + ## + externalIPs: [] + ## @param service.externalTrafficPolicy Enable client source IP preservation + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param service.loadBalancerIP Set the LoadBalancerIP + ## + loadBalancerIP: "" + ## @param service.clusterIP Kubernetes service Cluster IP + ## e.g.: + ## clusterIP: None + ## + clusterIP: "" + ## @param service.labels Service labels. Evaluated as a template + ## + labels: {} + ## @param service.annotations Service annotations. Evaluated as a template + ## Example: + ## annotations: + ## service.beta.kubernetes.io/aws-load-balancer-internal: 0.0.0.0/0 + ## + annotations: {} + ## DEPRECATED service.annotationsHeadless it will removed in a future release, please use service.headless.annotations instead + ## @param service.annotationsHeadless Headless Service annotations. Evaluated as a template + ## Example: + ## annotations: + ## external-dns.alpha.kubernetes.io/internal-hostname: rabbitmq.example.com + ## + annotationsHeadless: {} + ## Headless service properties + ## + headless: + ## @param service.headless.annotations Annotations for the headless service. + ## + annotations: {} + ## @param service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + +## Configure the ingress resource that allows you to access the +## RabbitMQ installation. Set up the URL +## ref: https://kubernetes.io/docs/user-guide/ingress/ +## +ingress: + ## @param ingress.enabled Enable ingress resource for Management console + ## + enabled: false + + ## @param ingress.path Path for the default host. You may need to set this to '/*' in order to use this with ALB ingress controllers. + ## + path: / + + ## @param ingress.pathType Ingress path type + ## + pathType: ImplementationSpecific + ## @param ingress.hostname Default host for the ingress resource + ## + hostname: rabbitmq.local + ## @param ingress.annotations Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. + ## For a full list of possible ingress annotations, please see + ## ref: https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md + ## Use this parameter to set the required annotations for cert-manager, see + ## ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations + ## + ## e.g: + ## annotations: + ## kubernetes.io/ingress.class: nginx + ## cert-manager.io/cluster-issuer: cluster-issuer-name + ## + annotations: {} + ## @param ingress.tls Enable TLS configuration for the hostname defined at `ingress.hostname` parameter + ## TLS certificates will be retrieved from a TLS secret with name: {{- printf "%s-tls" .Values.ingress.hostname }} + ## You can: + ## - Use the `ingress.secrets` parameter to create this TLS secret + ## - Rely on cert-manager to create it by setting the corresponding annotations + ## - Rely on Helm to create self-signed certificates by setting `ingress.selfSigned=true` + ## + tls: false + ## @param ingress.selfSigned Set this to true in order to create a TLS secret for this ingress record + ## using self-signed certificates generated by Helm + ## + selfSigned: false + ## @param ingress.extraHosts The list of additional hostnames to be covered with this ingress record. + ## Most likely the hostname above will be enough, but in the event more hosts are needed, this is an array + ## e.g: + ## extraHosts: + ## - name: rabbitmq.local + ## path: / + ## + extraHosts: [] + ## @param ingress.extraPaths An array with additional arbitrary paths that may need to be added to the ingress under the main host + ## e.g: + ## extraPaths: + ## - path: /* + ## backend: + ## serviceName: ssl-redirect + ## servicePort: use-annotation + ## + extraPaths: [] + ## @param ingress.extraRules The list of additional rules to be added to this ingress record. Evaluated as a template + ## Useful when looking for additional customization, such as using different backend + ## + extraRules: [] + ## @param ingress.extraTls The tls configuration for additional hostnames to be covered with this ingress record. + ## see: https://kubernetes.io/docs/concepts/services-networking/ingress/#tls + ## e.g: + ## extraTls: + ## - hosts: + ## - rabbitmq.local + ## secretName: rabbitmq.local-tls + ## + extraTls: [] + ## @param ingress.secrets Custom TLS certificates as secrets + ## NOTE: 'key' and 'certificate' are expected in PEM format + ## NOTE: 'name' should line up with a 'secretName' set further up + ## If it is not set and you're using cert-manager, this is unneeded, as it will create a secret for you with valid certificates + ## If it is not set and you're NOT using cert-manager either, self-signed certificates will be created valid for 365 days + ## It is also possible to create and manage the certificates outside of this helm chart + ## Please see README.md for more information + ## e.g: + ## secrets: + ## - name: rabbitmq.local-tls + ## key: |- + ## -----BEGIN RSA PRIVATE KEY----- + ## ... + ## -----END RSA PRIVATE KEY----- + ## certificate: |- + ## -----BEGIN CERTIFICATE----- + ## ... + ## -----END CERTIFICATE----- + ## + secrets: [] + ## @param ingress.ingressClassName IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+) + ## This is supported in Kubernetes 1.18+ and required if you have more than one IngressClass marked as the default for your cluster . + ## ref: https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/ + ## + ingressClassName: "" + ## @param ingress.existingSecret It is you own the certificate as secret. + ## + existingSecret: "" + +## Network Policy configuration +## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ +## +networkPolicy: + ## @param networkPolicy.enabled Enable creation of NetworkPolicy resources + ## + enabled: false + ## @param networkPolicy.allowExternal Don't require client label for connections + ## The Policy model to apply. When set to false, only pods with the correct + ## client label will have network access to the ports RabbitMQ is listening + ## on. When true, RabbitMQ will accept connections from any source + ## (with the correct destination port). + ## + allowExternal: true + ## @param networkPolicy.additionalRules Additional NetworkPolicy Ingress "from" rules to set. Note that all rules are OR-ed. + ## e.g: + ## additionalRules: + ## - matchLabels: + ## - role: frontend + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + additionalRules: [] + +## @section Metrics Parameters +## + +## Prometheus Metrics +## +metrics: + ## @param metrics.enabled Enable exposing RabbitMQ metrics to be gathered by Prometheus + ## + enabled: false + ## @param metrics.plugins Plugins to enable Prometheus metrics in RabbitMQ + ## + plugins: "rabbitmq_prometheus" + ## Prometheus pod annotations + ## @param metrics.podAnnotations [object] Annotations for enabling prometheus to access the metrics endpoint + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: + prometheus.io/scrape: "true" + prometheus.io/port: "{{ .Values.service.ports.metrics }}" + ## Prometheus Service Monitor + ## ref: https://github.com/coreos/prometheus-operator + ## + serviceMonitor: + ## @param metrics.serviceMonitor.enabled Create ServiceMonitor Resource for scraping metrics using PrometheusOperator + ## + enabled: false + ## @param metrics.serviceMonitor.namespace Specify the namespace in which the serviceMonitor resource will be created + ## + namespace: "" + ## @param metrics.serviceMonitor.interval Specify the interval at which metrics should be scraped + ## + interval: 30s + ## @param metrics.serviceMonitor.scrapeTimeout Specify the timeout after which the scrape is ended + ## e.g: + ## scrapeTimeout: 30s + ## + scrapeTimeout: "" + ## @param metrics.serviceMonitor.jobLabel The name of the label on the target service to use as the job name in prometheus. + ## + jobLabel: "" + ## @param metrics.serviceMonitor.relabelings RelabelConfigs to apply to samples before scraping. + ## + relabelings: [] + ## @param metrics.serviceMonitor.metricRelabelings MetricsRelabelConfigs to apply to samples before ingestion. + ## + metricRelabelings: [] + ## @param metrics.serviceMonitor.honorLabels honorLabels chooses the metric's labels on collisions with target labels + ## + honorLabels: false + ## @param metrics.serviceMonitor.targetLabels Used to keep given service's labels in target + ## e.g: + ## - app.kubernetes.io/name + ## + targetLabels: {} + ## @param metrics.serviceMonitor.podTargetLabels Used to keep given pod's labels in target + ## e.g: + ## - app.kubernetes.io/name + ## + podTargetLabels: {} + ## @param metrics.serviceMonitor.path Define the path used by ServiceMonitor to scrap metrics + ## Could be /metrics for aggregated metrics or /metrics/per-object for more details + ## + path: "" + ## @param metrics.serviceMonitor.params Define the HTTP URL parameters used by ServiceMonitor + ## + params: {} + ## @param metrics.serviceMonitor.selector ServiceMonitor selector labels + ## ref: https://github.com/bitnami/charts/tree/main/bitnami/prometheus-operator#prometheus-configuration + ## + ## selector: + ## prometheus: my-prometheus + ## + selector: {} + ## @param metrics.serviceMonitor.labels Extra labels for the ServiceMonitor + ## + labels: {} + ## @param metrics.serviceMonitor.annotations Extra annotations for the ServiceMonitor + ## + annotations: {} + + ## 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: + ## @param metrics.prometheusRule.enabled Set this to true to create prometheusRules for Prometheus operator + ## + enabled: false + ## @param metrics.prometheusRule.additionalLabels Additional labels that can be used so prometheusRules will be discovered by Prometheus + ## + additionalLabels: {} + ## @param metrics.prometheusRule.namespace namespace where prometheusRules resource should be created + ## + namespace: "" + ## List of rules, used as template by Helm. + ## @param metrics.prometheusRule.rules List of rules, used as template by Helm. + ## These are just examples rules inspired from https://awesome-prometheus-alerts.grep.to/rules.html + ## rules: + ## - alert: RabbitmqDown + ## expr: rabbitmq_up{service="{{ template "common.names.fullname" . }}"} == 0 + ## for: 5m + ## labels: + ## severity: error + ## annotations: + ## summary: Rabbitmq down (instance {{ "{{ $labels.instance }}" }}) + ## description: RabbitMQ node down + ## - alert: ClusterDown + ## expr: | + ## sum(rabbitmq_running{service="{{ template "common.names.fullname" . }}"}) + ## < {{ .Values.replicaCount }} + ## for: 5m + ## labels: + ## severity: error + ## annotations: + ## summary: Cluster down (instance {{ "{{ $labels.instance }}" }}) + ## description: | + ## Less than {{ .Values.replicaCount }} nodes running in RabbitMQ cluster + ## VALUE = {{ "{{ $value }}" }} + ## - alert: ClusterPartition + ## expr: rabbitmq_partitions{service="{{ template "common.names.fullname" . }}"} > 0 + ## for: 5m + ## labels: + ## severity: error + ## annotations: + ## summary: Cluster partition (instance {{ "{{ $labels.instance }}" }}) + ## description: | + ## Cluster partition + ## VALUE = {{ "{{ $value }}" }} + ## - alert: OutOfMemory + ## expr: | + ## rabbitmq_node_mem_used{service="{{ template "common.names.fullname" . }}"} + ## / rabbitmq_node_mem_limit{service="{{ template "common.names.fullname" . }}"} + ## * 100 > 90 + ## for: 5m + ## labels: + ## severity: warning + ## annotations: + ## summary: Out of memory (instance {{ "{{ $labels.instance }}" }}) + ## description: | + ## Memory available for RabbmitMQ is low (< 10%)\n VALUE = {{ "{{ $value }}" }} + ## LABELS: {{ "{{ $labels }}" }} + ## - alert: TooManyConnections + ## expr: rabbitmq_connectionsTotal{service="{{ template "common.names.fullname" . }}"} > 1000 + ## for: 5m + ## labels: + ## severity: warning + ## annotations: + ## summary: Too many connections (instance {{ "{{ $labels.instance }}" }}) + ## description: | + ## RabbitMQ instance has too many connections (> 1000) + ## VALUE = {{ "{{ $value }}" }}\n LABELS: {{ "{{ $labels }}" }} + ## + rules: [] + +## @section Init Container Parameters +## + +## Init Container parameters +## Change the owner and group of the persistent volume(s) mountpoint(s) to 'runAsUser:fsGroup' on each component +## values from the securityContext section of the component +## +volumePermissions: + ## @param volumePermissions.enabled Enable init container that changes the owner and group of the persistent volume(s) mountpoint to `runAsUser:fsGroup` + ## + enabled: false + ## @param volumePermissions.image.registry [default: REGISTRY_NAME] Init container volume-permissions image registry + ## @param volumePermissions.image.repository [default: REPOSITORY_NAME/os-shell] Init container volume-permissions image repository + ## @skip volumePermissions.image.tag Init container volume-permissions image tag + ## @param volumePermissions.image.digest Init container volume-permissions image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param volumePermissions.image.pullPolicy Init container volume-permissions image pull policy + ## @param volumePermissions.image.pullSecrets Specify docker-registry secret names as an array + ## + image: + registry: docker.io + repository: bitnami/os-shell + tag: 11-debian-11-r93 + digest: "" + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://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/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Init Container resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-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:'. + ## @param volumePermissions.resources.limits Init container volume-permissions resource limits + ## @param volumePermissions.resources.requests Init container volume-permissions resource requests + ## + resources: + ## Example: + ## limits: + ## cpu: 100m + ## memory: 128Mi + ## + limits: {} + ## Examples: + ## requests: + ## cpu: 100m + ## memory: 128Mi + ## + requests: {} + ## Init container' Security Context + ## Note: the chown of the data folder is done to containerSecurityContext.runAsUser + ## and not the below volumePermissions.containerSecurityContext.runAsUser + ## @param volumePermissions.containerSecurityContext.runAsUser User ID for the init container + ## + containerSecurityContext: + runAsUser: 0 diff --git a/backing-services/redis/.helmignore b/backing-services/redis/.helmignore new file mode 100644 index 0000000..f0c1319 --- /dev/null +++ b/backing-services/redis/.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/backing-services/redis/Chart.lock b/backing-services/redis/Chart.lock new file mode 100644 index 0000000..01190b8 --- /dev/null +++ b/backing-services/redis/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + version: 2.14.1 +digest: sha256:5ccbe5f1fe4459864a8c9d7329c400b678666b6cfb1450818a830bda81995bc3 +generated: "2023-12-19T19:11:00.40217662Z" diff --git a/backing-services/redis/Chart.yaml b/backing-services/redis/Chart.yaml new file mode 100644 index 0000000..c3e11ec --- /dev/null +++ b/backing-services/redis/Chart.yaml @@ -0,0 +1,37 @@ +# Copyright VMware, Inc. +# SPDX-License-Identifier: APACHE-2.0 + +annotations: + category: Database + licenses: Apache-2.0 + images: | + - name: os-shell + image: docker.io/bitnami/os-shell:11-debian-11-r93 + - name: redis-exporter + image: docker.io/bitnami/redis-exporter:1.56.0-debian-11-r0 + - name: redis-sentinel + image: docker.io/bitnami/redis-sentinel:7.2.4-debian-11-r0 + - name: redis + image: docker.io/bitnami/redis:7.2.4-debian-11-r0 +apiVersion: v2 +appVersion: 7.2.4 +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + tags: + - bitnami-common + version: 2.x.x +description: Redis(R) is an open source, advanced key-value store. It is often referred to as a data structure server since keys can contain strings, hashes, lists, sets and sorted sets. +home: https://bitnami.com +icon: https://bitnami.com/assets/stacks/redis/img/redis-stack-220x234.png +keywords: +- redis +- keyvalue +- database +maintainers: +- name: VMware, Inc. + url: https://github.com/bitnami/charts +name: redis +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/redis +version: 18.6.3 diff --git a/backing-services/redis/README.md b/backing-services/redis/README.md new file mode 100644 index 0000000..cc5c08f --- /dev/null +++ b/backing-services/redis/README.md @@ -0,0 +1,1022 @@ + + +# Bitnami package for Redis(R) + +Redis(R) is an open source, advanced key-value store. It is often referred to as a data structure server since keys can contain strings, hashes, lists, sets and sorted sets. + +[Overview of Redis®](http://redis.io) + +Disclaimer: Redis is a registered trademark of Redis Ltd. Any rights therein are reserved to Redis Ltd. Any use by Bitnami is for referential purposes only and does not indicate any sponsorship, endorsement, or affiliation between Redis Ltd. + +## TL;DR + +```console +helm install my-release oci://registry-1.docker.io/bitnamicharts/redis +``` + +Looking to use Redisreg; in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the enterprise edition of Bitnami Application Catalog. + +## Introduction + +This chart bootstraps a [Redis®](https://github.com/bitnami/containers/tree/main/bitnami/redis) deployment on a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters. + +### Choose between Redis® Helm Chart and Redis® Cluster Helm Chart + +You can choose any of the two Redis® Helm charts for deploying a Redis® cluster. + +1. [Redis® Helm Chart](https://github.com/bitnami/charts/tree/main/bitnami/redis) will deploy a master-replica cluster, with the [option](https://github.com/bitnami/charts/tree/main/bitnami/redis#redis-sentinel-configuration-parameters) of enabling using Redis® Sentinel. +2. [Redis® Cluster Helm Chart](https://github.com/bitnami/charts/tree/main/bitnami/redis-cluster) will deploy a Redis® Cluster topology with sharding. + +The main features of each chart are the following: + +| Redis® | Redis® Cluster | +|--------------------------------------------------------|------------------------------------------------------------------------| +| Supports multiple databases | Supports only one database. Better if you have a big dataset | +| Single write point (single master) | Multiple write points (multiple masters) | +| ![Redis® Topology](img/redis-topology.png) | ![Redis® Cluster Topology](img/redis-cluster-topology.png) | + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ +- 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 oci://REGISTRY_NAME/REPOSITORY_NAME/redis +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The command deploys Redis® 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 + +### Global parameters + +| Name | Description | Value | +| ------------------------- | ------------------------------------------------------ | ----- | +| `global.imageRegistry` | Global Docker image registry | `""` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | +| `global.storageClass` | Global StorageClass for Persistent Volume(s) | `""` | +| `global.redis.password` | Global Redis® password (overrides `auth.password`) | `""` | + +### Common parameters + +| Name | Description | Value | +| ------------------------- | -------------------------------------------------------------------------------------------------------------- | --------------- | +| `kubeVersion` | Override Kubernetes version | `""` | +| `nameOverride` | String to partially override common.names.fullname | `""` | +| `fullnameOverride` | String to fully override common.names.fullname | `""` | +| `namespaceOverride` | String to fully override common.names.namespace | `""` | +| `commonLabels` | Labels to add to all deployed objects | `{}` | +| `commonAnnotations` | Annotations to add to all deployed objects | `{}` | +| `secretAnnotations` | Annotations to add to secret | `{}` | +| `clusterDomain` | Kubernetes cluster domain name | `cluster.local` | +| `extraDeploy` | Array of extra objects to deploy with the release | `[]` | +| `useHostnames` | Use hostnames internally when announcing replication. If false, the hostname will be resolved to an IP address | `true` | +| `nameResolutionThreshold` | Failure threshold for internal hostnames resolution | `5` | +| `nameResolutionTimeout` | Timeout seconds between probes for internal hostnames resolution | `5` | +| `diagnosticMode.enabled` | Enable diagnostic mode (all probes will be disabled and the command will be overridden) | `false` | +| `diagnosticMode.command` | Command to override all containers in the deployment | `["sleep"]` | +| `diagnosticMode.args` | Args to override all containers in the deployment | `["infinity"]` | + +### Redis® Image parameters + +| Name | Description | Value | +| ------------------- | ---------------------------------------------------------------------------------------------------------- | ----------------------- | +| `image.registry` | Redis® image registry | `REGISTRY_NAME` | +| `image.repository` | Redis® image repository | `REPOSITORY_NAME/redis` | +| `image.digest` | Redis® image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `image.pullPolicy` | Redis® image pull policy | `IfNotPresent` | +| `image.pullSecrets` | Redis® image pull secrets | `[]` | +| `image.debug` | Enable image debug mode | `false` | + +### Redis® common configuration parameters + +| Name | Description | Value | +| -------------------------------- | ------------------------------------------------------------------------------------- | ------------- | +| `architecture` | Redis® architecture. Allowed values: `standalone` or `replication` | `replication` | +| `auth.enabled` | Enable password authentication | `true` | +| `auth.sentinel` | Enable password authentication on sentinels too | `true` | +| `auth.password` | Redis® password | `""` | +| `auth.existingSecret` | The name of an existing secret with Redis® credentials | `""` | +| `auth.existingSecretPasswordKey` | Password key to be retrieved from existing secret | `""` | +| `auth.usePasswordFiles` | Mount credentials as files instead of using an environment variable | `false` | +| `commonConfiguration` | Common configuration to be added into the ConfigMap | `""` | +| `existingConfigmap` | The name of an existing ConfigMap with your custom configuration for Redis® nodes | `""` | + +### Redis® master configuration parameters + +| Name | Description | Value | +| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ------------------------ | +| `master.count` | Number of Redis® master instances to deploy (experimental, requires additional configuration) | `1` | +| `master.configuration` | Configuration for Redis® master nodes | `""` | +| `master.disableCommands` | Array with Redis® commands to disable on master nodes | `["FLUSHDB","FLUSHALL"]` | +| `master.command` | Override default container command (useful when using custom images) | `[]` | +| `master.args` | Override default container args (useful when using custom images) | `[]` | +| `master.enableServiceLinks` | Whether information about services should be injected into pod's environment variable | `true` | +| `master.preExecCmds` | Additional commands to run prior to starting Redis® master | `[]` | +| `master.extraFlags` | Array with additional command line flags for Redis® master | `[]` | +| `master.extraEnvVars` | Array with extra environment variables to add to Redis® master nodes | `[]` | +| `master.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for Redis® master nodes | `""` | +| `master.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for Redis® master nodes | `""` | +| `master.containerPorts.redis` | Container port to open on Redis® master nodes | `6379` | +| `master.startupProbe.enabled` | Enable startupProbe on Redis® master nodes | `false` | +| `master.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `20` | +| `master.startupProbe.periodSeconds` | Period seconds for startupProbe | `5` | +| `master.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `master.startupProbe.failureThreshold` | Failure threshold for startupProbe | `5` | +| `master.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `master.livenessProbe.enabled` | Enable livenessProbe on Redis® master nodes | `true` | +| `master.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `20` | +| `master.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `5` | +| `master.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `master.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `5` | +| `master.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `master.readinessProbe.enabled` | Enable readinessProbe on Redis® master nodes | `true` | +| `master.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `20` | +| `master.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `5` | +| `master.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `1` | +| `master.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `5` | +| `master.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `master.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `master.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `master.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `master.resources.limits` | The resources limits for the Redis® master containers | `{}` | +| `master.resources.requests` | The requested resources for the Redis® master containers | `{}` | +| `master.podSecurityContext.enabled` | Enabled Redis® master pods' Security Context | `true` | +| `master.podSecurityContext.fsGroup` | Set Redis® master pod's Security Context fsGroup | `1001` | +| `master.containerSecurityContext.enabled` | Enabled Redis® master containers' Security Context | `true` | +| `master.containerSecurityContext.runAsUser` | Set Redis® master containers' Security Context runAsUser | `1001` | +| `master.containerSecurityContext.runAsGroup` | Set Redis® master containers' Security Context runAsGroup | `0` | +| `master.containerSecurityContext.runAsNonRoot` | Set Redis® master containers' Security Context runAsNonRoot | `true` | +| `master.containerSecurityContext.allowPrivilegeEscalation` | Is it possible to escalate Redis® pod(s) privileges | `false` | +| `master.containerSecurityContext.seccompProfile.type` | Set Redis® master containers' Security Context seccompProfile | `RuntimeDefault` | +| `master.containerSecurityContext.capabilities.drop` | Set Redis® master containers' Security Context capabilities to drop | `["ALL"]` | +| `master.kind` | Use either Deployment, StatefulSet (default) or DaemonSet | `StatefulSet` | +| `master.schedulerName` | Alternate scheduler for Redis® master pods | `""` | +| `master.updateStrategy.type` | Redis® master statefulset strategy type | `RollingUpdate` | +| `master.minReadySeconds` | How many seconds a pod needs to be ready before killing the next, during update | `0` | +| `master.priorityClassName` | Redis® master pods' priorityClassName | `""` | +| `master.hostAliases` | Redis® master pods host aliases | `[]` | +| `master.podLabels` | Extra labels for Redis® master pods | `{}` | +| `master.podAnnotations` | Annotations for Redis® master pods | `{}` | +| `master.shareProcessNamespace` | Share a single process namespace between all of the containers in Redis® master pods | `false` | +| `master.podAffinityPreset` | Pod affinity preset. Ignored if `master.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `master.podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `master.affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `master.nodeAffinityPreset.type` | Node affinity preset type. Ignored if `master.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `master.nodeAffinityPreset.key` | Node label key to match. Ignored if `master.affinity` is set | `""` | +| `master.nodeAffinityPreset.values` | Node label values to match. Ignored if `master.affinity` is set | `[]` | +| `master.affinity` | Affinity for Redis® master pods assignment | `{}` | +| `master.nodeSelector` | Node labels for Redis® master pods assignment | `{}` | +| `master.tolerations` | Tolerations for Redis® master pods assignment | `[]` | +| `master.topologySpreadConstraints` | Spread Constraints for Redis® master pod assignment | `[]` | +| `master.dnsPolicy` | DNS Policy for Redis® master pod | `""` | +| `master.dnsConfig` | DNS Configuration for Redis® master pod | `{}` | +| `master.lifecycleHooks` | for the Redis® master container(s) to automate configuration before or after startup | `{}` | +| `master.extraVolumes` | Optionally specify extra list of additional volumes for the Redis® master pod(s) | `[]` | +| `master.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the Redis® master container(s) | `[]` | +| `master.sidecars` | Add additional sidecar containers to the Redis® master pod(s) | `[]` | +| `master.initContainers` | Add additional init containers to the Redis® master pod(s) | `[]` | +| `master.persistence.enabled` | Enable persistence on Redis® master nodes using Persistent Volume Claims | `true` | +| `master.persistence.medium` | Provide a medium for `emptyDir` volumes. | `""` | +| `master.persistence.sizeLimit` | Set this to enable a size limit for `emptyDir` volumes. | `""` | +| `master.persistence.path` | The path the volume will be mounted at on Redis® master containers | `/data` | +| `master.persistence.subPath` | The subdirectory of the volume to mount on Redis® master containers | `""` | +| `master.persistence.subPathExpr` | Used to construct the subPath subdirectory of the volume to mount on Redis® master containers | `""` | +| `master.persistence.storageClass` | Persistent Volume storage class | `""` | +| `master.persistence.accessModes` | Persistent Volume access modes | `["ReadWriteOnce"]` | +| `master.persistence.size` | Persistent Volume size | `8Gi` | +| `master.persistence.annotations` | Additional custom annotations for the PVC | `{}` | +| `master.persistence.labels` | Additional custom labels for the PVC | `{}` | +| `master.persistence.selector` | Additional labels to match for the PVC | `{}` | +| `master.persistence.dataSource` | Custom PVC data source | `{}` | +| `master.persistence.existingClaim` | Use a existing PVC which must be created manually before bound | `""` | +| `master.persistentVolumeClaimRetentionPolicy.enabled` | Controls if and how PVCs are deleted during the lifecycle of a StatefulSet | `false` | +| `master.persistentVolumeClaimRetentionPolicy.whenScaled` | Volume retention behavior when the replica count of the StatefulSet is reduced | `Retain` | +| `master.persistentVolumeClaimRetentionPolicy.whenDeleted` | Volume retention behavior that applies when the StatefulSet is deleted | `Retain` | +| `master.service.type` | Redis® master service type | `ClusterIP` | +| `master.service.ports.redis` | Redis® master service port | `6379` | +| `master.service.nodePorts.redis` | Node port for Redis® master | `""` | +| `master.service.externalTrafficPolicy` | Redis® master service external traffic policy | `Cluster` | +| `master.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `master.service.internalTrafficPolicy` | Redis® master service internal traffic policy (requires Kubernetes v1.22 or greater to be usable) | `Cluster` | +| `master.service.clusterIP` | Redis® master service Cluster IP | `""` | +| `master.service.loadBalancerIP` | Redis® master service Load Balancer IP | `""` | +| `master.service.loadBalancerClass` | master service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) | `""` | +| `master.service.loadBalancerSourceRanges` | Redis® master service Load Balancer sources | `[]` | +| `master.service.externalIPs` | Redis® master service External IPs | `[]` | +| `master.service.annotations` | Additional custom annotations for Redis® master service | `{}` | +| `master.service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` | +| `master.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `master.terminationGracePeriodSeconds` | Integer setting the termination grace period for the redis-master pods | `30` | +| `master.serviceAccount.create` | Specifies whether a ServiceAccount should be created | `false` | +| `master.serviceAccount.name` | The name of the ServiceAccount to use. | `""` | +| `master.serviceAccount.automountServiceAccountToken` | Whether to auto mount the service account token | `true` | +| `master.serviceAccount.annotations` | Additional custom annotations for the ServiceAccount | `{}` | + +### Redis® replicas configuration parameters + +| Name | Description | Value | +| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------ | +| `replica.kind` | Use either DaemonSet or StatefulSet (default) | `StatefulSet` | +| `replica.replicaCount` | Number of Redis® replicas to deploy | `3` | +| `replica.configuration` | Configuration for Redis® replicas nodes | `""` | +| `replica.disableCommands` | Array with Redis® commands to disable on replicas nodes | `["FLUSHDB","FLUSHALL"]` | +| `replica.command` | Override default container command (useful when using custom images) | `[]` | +| `replica.args` | Override default container args (useful when using custom images) | `[]` | +| `replica.enableServiceLinks` | Whether information about services should be injected into pod's environment variable | `true` | +| `replica.preExecCmds` | Additional commands to run prior to starting Redis® replicas | `[]` | +| `replica.extraFlags` | Array with additional command line flags for Redis® replicas | `[]` | +| `replica.extraEnvVars` | Array with extra environment variables to add to Redis® replicas nodes | `[]` | +| `replica.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for Redis® replicas nodes | `""` | +| `replica.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for Redis® replicas nodes | `""` | +| `replica.externalMaster.enabled` | Use external master for bootstrapping | `false` | +| `replica.externalMaster.host` | External master host to bootstrap from | `""` | +| `replica.externalMaster.port` | Port for Redis service external master host | `6379` | +| `replica.containerPorts.redis` | Container port to open on Redis® replicas nodes | `6379` | +| `replica.startupProbe.enabled` | Enable startupProbe on Redis® replicas nodes | `true` | +| `replica.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `10` | +| `replica.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `replica.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `replica.startupProbe.failureThreshold` | Failure threshold for startupProbe | `22` | +| `replica.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `replica.livenessProbe.enabled` | Enable livenessProbe on Redis® replicas nodes | `true` | +| `replica.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `20` | +| `replica.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `5` | +| `replica.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `replica.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `5` | +| `replica.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `replica.readinessProbe.enabled` | Enable readinessProbe on Redis® replicas nodes | `true` | +| `replica.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `20` | +| `replica.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `5` | +| `replica.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `1` | +| `replica.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `5` | +| `replica.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `replica.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `replica.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `replica.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `replica.resources.limits` | The resources limits for the Redis® replicas containers | `{}` | +| `replica.resources.requests` | The requested resources for the Redis® replicas containers | `{}` | +| `replica.podSecurityContext.enabled` | Enabled Redis® replicas pods' Security Context | `true` | +| `replica.podSecurityContext.fsGroup` | Set Redis® replicas pod's Security Context fsGroup | `1001` | +| `replica.containerSecurityContext.enabled` | Enabled Redis® replicas containers' Security Context | `true` | +| `replica.containerSecurityContext.runAsUser` | Set Redis® replicas containers' Security Context runAsUser | `1001` | +| `replica.containerSecurityContext.runAsGroup` | Set Redis® replicas containers' Security Context runAsGroup | `0` | +| `replica.containerSecurityContext.runAsNonRoot` | Set Redis® replicas containers' Security Context runAsNonRoot | `true` | +| `replica.containerSecurityContext.allowPrivilegeEscalation` | Set Redis® replicas pod's Security Context allowPrivilegeEscalation | `false` | +| `replica.containerSecurityContext.seccompProfile.type` | Set Redis® replicas containers' Security Context seccompProfile | `RuntimeDefault` | +| `replica.containerSecurityContext.capabilities.drop` | Set Redis® replicas containers' Security Context capabilities to drop | `["ALL"]` | +| `replica.schedulerName` | Alternate scheduler for Redis® replicas pods | `""` | +| `replica.updateStrategy.type` | Redis® replicas statefulset strategy type | `RollingUpdate` | +| `replica.minReadySeconds` | How many seconds a pod needs to be ready before killing the next, during update | `0` | +| `replica.priorityClassName` | Redis® replicas pods' priorityClassName | `""` | +| `replica.podManagementPolicy` | podManagementPolicy to manage scaling operation of %%MAIN_CONTAINER_NAME%% pods | `""` | +| `replica.hostAliases` | Redis® replicas pods host aliases | `[]` | +| `replica.podLabels` | Extra labels for Redis® replicas pods | `{}` | +| `replica.podAnnotations` | Annotations for Redis® replicas pods | `{}` | +| `replica.shareProcessNamespace` | Share a single process namespace between all of the containers in Redis® replicas pods | `false` | +| `replica.podAffinityPreset` | Pod affinity preset. Ignored if `replica.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `replica.podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `replica.affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `replica.nodeAffinityPreset.type` | Node affinity preset type. Ignored if `replica.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `replica.nodeAffinityPreset.key` | Node label key to match. Ignored if `replica.affinity` is set | `""` | +| `replica.nodeAffinityPreset.values` | Node label values to match. Ignored if `replica.affinity` is set | `[]` | +| `replica.affinity` | Affinity for Redis® replicas pods assignment | `{}` | +| `replica.nodeSelector` | Node labels for Redis® replicas pods assignment | `{}` | +| `replica.tolerations` | Tolerations for Redis® replicas pods assignment | `[]` | +| `replica.topologySpreadConstraints` | Spread Constraints for Redis® replicas pod assignment | `[]` | +| `replica.dnsPolicy` | DNS Policy for Redis® replica pods | `""` | +| `replica.dnsConfig` | DNS Configuration for Redis® replica pods | `{}` | +| `replica.lifecycleHooks` | for the Redis® replica container(s) to automate configuration before or after startup | `{}` | +| `replica.extraVolumes` | Optionally specify extra list of additional volumes for the Redis® replicas pod(s) | `[]` | +| `replica.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the Redis® replicas container(s) | `[]` | +| `replica.sidecars` | Add additional sidecar containers to the Redis® replicas pod(s) | `[]` | +| `replica.initContainers` | Add additional init containers to the Redis® replicas pod(s) | `[]` | +| `replica.persistence.enabled` | Enable persistence on Redis® replicas nodes using Persistent Volume Claims | `true` | +| `replica.persistence.medium` | Provide a medium for `emptyDir` volumes. | `""` | +| `replica.persistence.sizeLimit` | Set this to enable a size limit for `emptyDir` volumes. | `""` | +| `replica.persistence.path` | The path the volume will be mounted at on Redis® replicas containers | `/data` | +| `replica.persistence.subPath` | The subdirectory of the volume to mount on Redis® replicas containers | `""` | +| `replica.persistence.subPathExpr` | Used to construct the subPath subdirectory of the volume to mount on Redis® replicas containers | `""` | +| `replica.persistence.storageClass` | Persistent Volume storage class | `""` | +| `replica.persistence.accessModes` | Persistent Volume access modes | `["ReadWriteOnce"]` | +| `replica.persistence.size` | Persistent Volume size | `8Gi` | +| `replica.persistence.annotations` | Additional custom annotations for the PVC | `{}` | +| `replica.persistence.labels` | Additional custom labels for the PVC | `{}` | +| `replica.persistence.selector` | Additional labels to match for the PVC | `{}` | +| `replica.persistence.dataSource` | Custom PVC data source | `{}` | +| `replica.persistence.existingClaim` | Use a existing PVC which must be created manually before bound | `""` | +| `replica.persistentVolumeClaimRetentionPolicy.enabled` | Controls if and how PVCs are deleted during the lifecycle of a StatefulSet | `false` | +| `replica.persistentVolumeClaimRetentionPolicy.whenScaled` | Volume retention behavior when the replica count of the StatefulSet is reduced | `Retain` | +| `replica.persistentVolumeClaimRetentionPolicy.whenDeleted` | Volume retention behavior that applies when the StatefulSet is deleted | `Retain` | +| `replica.service.type` | Redis® replicas service type | `ClusterIP` | +| `replica.service.ports.redis` | Redis® replicas service port | `6379` | +| `replica.service.nodePorts.redis` | Node port for Redis® replicas | `""` | +| `replica.service.externalTrafficPolicy` | Redis® replicas service external traffic policy | `Cluster` | +| `replica.service.internalTrafficPolicy` | Redis® replicas service internal traffic policy (requires Kubernetes v1.22 or greater to be usable) | `Cluster` | +| `replica.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `replica.service.clusterIP` | Redis® replicas service Cluster IP | `""` | +| `replica.service.loadBalancerIP` | Redis® replicas service Load Balancer IP | `""` | +| `replica.service.loadBalancerClass` | replicas service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) | `""` | +| `replica.service.loadBalancerSourceRanges` | Redis® replicas service Load Balancer sources | `[]` | +| `replica.service.annotations` | Additional custom annotations for Redis® replicas service | `{}` | +| `replica.service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` | +| `replica.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `replica.terminationGracePeriodSeconds` | Integer setting the termination grace period for the redis-replicas pods | `30` | +| `replica.autoscaling.enabled` | Enable replica autoscaling settings | `false` | +| `replica.autoscaling.minReplicas` | Minimum replicas for the pod autoscaling | `1` | +| `replica.autoscaling.maxReplicas` | Maximum replicas for the pod autoscaling | `11` | +| `replica.autoscaling.targetCPU` | Percentage of CPU to consider when autoscaling | `""` | +| `replica.autoscaling.targetMemory` | Percentage of Memory to consider when autoscaling | `""` | +| `replica.serviceAccount.create` | Specifies whether a ServiceAccount should be created | `false` | +| `replica.serviceAccount.name` | The name of the ServiceAccount to use. | `""` | +| `replica.serviceAccount.automountServiceAccountToken` | Whether to auto mount the service account token | `true` | +| `replica.serviceAccount.annotations` | Additional custom annotations for the ServiceAccount | `{}` | + +### Redis® Sentinel configuration parameters + +| Name | Description | Value | +| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | +| `sentinel.enabled` | Use Redis® Sentinel on Redis® pods. | `false` | +| `sentinel.image.registry` | Redis® Sentinel image registry | `REGISTRY_NAME` | +| `sentinel.image.repository` | Redis® Sentinel image repository | `REPOSITORY_NAME/redis-sentinel` | +| `sentinel.image.digest` | Redis® Sentinel image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `sentinel.image.pullPolicy` | Redis® Sentinel image pull policy | `IfNotPresent` | +| `sentinel.image.pullSecrets` | Redis® Sentinel image pull secrets | `[]` | +| `sentinel.image.debug` | Enable image debug mode | `false` | +| `sentinel.annotations` | Additional custom annotations for Redis® Sentinel resource | `{}` | +| `sentinel.masterSet` | Master set name | `mymaster` | +| `sentinel.quorum` | Sentinel Quorum | `2` | +| `sentinel.getMasterTimeout` | Amount of time to allow before get_sentinel_master_info() times out. | `90` | +| `sentinel.automateClusterRecovery` | Automate cluster recovery in cases where the last replica is not considered a good replica and Sentinel won't automatically failover to it. | `false` | +| `sentinel.redisShutdownWaitFailover` | Whether the Redis® master container waits for the failover at shutdown (in addition to the Redis® Sentinel container). | `true` | +| `sentinel.downAfterMilliseconds` | Timeout for detecting a Redis® node is down | `60000` | +| `sentinel.failoverTimeout` | Timeout for performing a election failover | `180000` | +| `sentinel.parallelSyncs` | Number of replicas that can be reconfigured in parallel to use the new master after a failover | `1` | +| `sentinel.configuration` | Configuration for Redis® Sentinel nodes | `""` | +| `sentinel.command` | Override default container command (useful when using custom images) | `[]` | +| `sentinel.args` | Override default container args (useful when using custom images) | `[]` | +| `sentinel.enableServiceLinks` | Whether information about services should be injected into pod's environment variable | `true` | +| `sentinel.preExecCmds` | Additional commands to run prior to starting Redis® Sentinel | `[]` | +| `sentinel.extraEnvVars` | Array with extra environment variables to add to Redis® Sentinel nodes | `[]` | +| `sentinel.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for Redis® Sentinel nodes | `""` | +| `sentinel.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for Redis® Sentinel nodes | `""` | +| `sentinel.externalMaster.enabled` | Use external master for bootstrapping | `false` | +| `sentinel.externalMaster.host` | External master host to bootstrap from | `""` | +| `sentinel.externalMaster.port` | Port for Redis service external master host | `6379` | +| `sentinel.containerPorts.sentinel` | Container port to open on Redis® Sentinel nodes | `26379` | +| `sentinel.startupProbe.enabled` | Enable startupProbe on Redis® Sentinel nodes | `true` | +| `sentinel.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `10` | +| `sentinel.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `sentinel.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `sentinel.startupProbe.failureThreshold` | Failure threshold for startupProbe | `22` | +| `sentinel.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `sentinel.livenessProbe.enabled` | Enable livenessProbe on Redis® Sentinel nodes | `true` | +| `sentinel.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `20` | +| `sentinel.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `sentinel.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `sentinel.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `sentinel.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `sentinel.readinessProbe.enabled` | Enable readinessProbe on Redis® Sentinel nodes | `true` | +| `sentinel.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `20` | +| `sentinel.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `5` | +| `sentinel.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `1` | +| `sentinel.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `sentinel.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `sentinel.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `sentinel.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `sentinel.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `sentinel.persistence.enabled` | Enable persistence on Redis® sentinel nodes using Persistent Volume Claims (Experimental) | `false` | +| `sentinel.persistence.storageClass` | Persistent Volume storage class | `""` | +| `sentinel.persistence.accessModes` | Persistent Volume access modes | `["ReadWriteOnce"]` | +| `sentinel.persistence.size` | Persistent Volume size | `100Mi` | +| `sentinel.persistence.annotations` | Additional custom annotations for the PVC | `{}` | +| `sentinel.persistence.labels` | Additional custom labels for the PVC | `{}` | +| `sentinel.persistence.selector` | Additional labels to match for the PVC | `{}` | +| `sentinel.persistence.dataSource` | Custom PVC data source | `{}` | +| `sentinel.persistence.medium` | Provide a medium for `emptyDir` volumes. | `""` | +| `sentinel.persistence.sizeLimit` | Set this to enable a size limit for `emptyDir` volumes. | `""` | +| `sentinel.persistentVolumeClaimRetentionPolicy.enabled` | Controls if and how PVCs are deleted during the lifecycle of a StatefulSet | `false` | +| `sentinel.persistentVolumeClaimRetentionPolicy.whenScaled` | Volume retention behavior when the replica count of the StatefulSet is reduced | `Retain` | +| `sentinel.persistentVolumeClaimRetentionPolicy.whenDeleted` | Volume retention behavior that applies when the StatefulSet is deleted | `Retain` | +| `sentinel.resources.limits` | The resources limits for the Redis® Sentinel containers | `{}` | +| `sentinel.resources.requests` | The requested resources for the Redis® Sentinel containers | `{}` | +| `sentinel.containerSecurityContext.enabled` | Enabled Redis® Sentinel containers' Security Context | `true` | +| `sentinel.containerSecurityContext.runAsUser` | Set Redis® Sentinel containers' Security Context runAsUser | `1001` | +| `sentinel.containerSecurityContext.runAsGroup` | Set Redis® Sentinel containers' Security Context runAsGroup | `0` | +| `sentinel.containerSecurityContext.runAsNonRoot` | Set Redis® Sentinel containers' Security Context runAsNonRoot | `true` | +| `sentinel.containerSecurityContext.allowPrivilegeEscalation` | Set Redis® Sentinel containers' Security Context allowPrivilegeEscalation | `false` | +| `sentinel.containerSecurityContext.seccompProfile.type` | Set Redis® Sentinel containers' Security Context seccompProfile | `RuntimeDefault` | +| `sentinel.containerSecurityContext.capabilities.drop` | Set Redis® Sentinel containers' Security Context capabilities to drop | `["ALL"]` | +| `sentinel.lifecycleHooks` | for the Redis® sentinel container(s) to automate configuration before or after startup | `{}` | +| `sentinel.extraVolumes` | Optionally specify extra list of additional volumes for the Redis® Sentinel | `[]` | +| `sentinel.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the Redis® Sentinel container(s) | `[]` | +| `sentinel.service.type` | Redis® Sentinel service type | `ClusterIP` | +| `sentinel.service.ports.redis` | Redis® service port for Redis® | `6379` | +| `sentinel.service.ports.sentinel` | Redis® service port for Redis® Sentinel | `26379` | +| `sentinel.service.nodePorts.redis` | Node port for Redis® | `""` | +| `sentinel.service.nodePorts.sentinel` | Node port for Sentinel | `""` | +| `sentinel.service.externalTrafficPolicy` | Redis® Sentinel service external traffic policy | `Cluster` | +| `sentinel.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `sentinel.service.clusterIP` | Redis® Sentinel service Cluster IP | `""` | +| `sentinel.service.loadBalancerIP` | Redis® Sentinel service Load Balancer IP | `""` | +| `sentinel.service.loadBalancerClass` | sentinel service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) | `""` | +| `sentinel.service.loadBalancerSourceRanges` | Redis® Sentinel service Load Balancer sources | `[]` | +| `sentinel.service.annotations` | Additional custom annotations for Redis® Sentinel service | `{}` | +| `sentinel.service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` | +| `sentinel.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `sentinel.service.headless.annotations` | Annotations for the headless service. | `{}` | +| `sentinel.terminationGracePeriodSeconds` | Integer setting the termination grace period for the redis-node pods | `30` | + +### Other Parameters + +| Name | Description | Value | +| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `serviceBindings.enabled` | Create secret for service binding (Experimental) | `false` | +| `networkPolicy.enabled` | Enable creation of NetworkPolicy resources | `false` | +| `networkPolicy.allowExternal` | Don't require client label for connections | `true` | +| `networkPolicy.extraIngress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `networkPolicy.extraEgress` | Add extra egress rules to the NetworkPolicy | `[]` | +| `networkPolicy.ingressNSMatchLabels` | Labels to match to allow traffic from other namespaces | `{}` | +| `networkPolicy.ingressNSPodMatchLabels` | Pod labels to match to allow traffic from other namespaces | `{}` | +| `networkPolicy.metrics.allowExternal` | Don't require client label for connections for metrics endpoint | `true` | +| `networkPolicy.metrics.ingressNSMatchLabels` | Labels to match to allow traffic from other namespaces to metrics endpoint | `{}` | +| `networkPolicy.metrics.ingressNSPodMatchLabels` | Pod labels to match to allow traffic from other namespaces to metrics endpoint | `{}` | +| `podSecurityPolicy.create` | Whether to create a PodSecurityPolicy. WARNING: PodSecurityPolicy is deprecated in Kubernetes v1.21 or later, unavailable in v1.25 or later | `false` | +| `podSecurityPolicy.enabled` | Enable PodSecurityPolicy's RBAC rules | `false` | +| `rbac.create` | Specifies whether RBAC resources should be created | `false` | +| `rbac.rules` | Custom RBAC rules to set | `[]` | +| `serviceAccount.create` | Specifies whether a ServiceAccount should be created | `true` | +| `serviceAccount.name` | The name of the ServiceAccount to use. | `""` | +| `serviceAccount.automountServiceAccountToken` | Whether to auto mount the service account token | `true` | +| `serviceAccount.annotations` | Additional custom annotations for the ServiceAccount | `{}` | +| `pdb.create` | Specifies whether a PodDisruptionBudget should be created | `false` | +| `pdb.minAvailable` | Min number of pods that must still be available after the eviction | `1` | +| `pdb.maxUnavailable` | Max number of pods that can be unavailable after the eviction | `""` | +| `tls.enabled` | Enable TLS traffic | `false` | +| `tls.authClients` | Require clients to authenticate | `true` | +| `tls.autoGenerated` | Enable autogenerated certificates | `false` | +| `tls.existingSecret` | The name of the existing secret that contains the TLS certificates | `""` | +| `tls.certificatesSecret` | DEPRECATED. Use existingSecret instead. | `""` | +| `tls.certFilename` | Certificate filename | `""` | +| `tls.certKeyFilename` | Certificate Key filename | `""` | +| `tls.certCAFilename` | CA Certificate filename | `""` | +| `tls.dhParamsFilename` | File containing DH params (in order to support DH based ciphers) | `""` | + +### Metrics Parameters + +| Name | Description | Value | +| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | -------------------------------- | +| `metrics.enabled` | Start a sidecar prometheus exporter to expose Redis® metrics | `false` | +| `metrics.image.registry` | Redis® Exporter image registry | `REGISTRY_NAME` | +| `metrics.image.repository` | Redis® Exporter image repository | `REPOSITORY_NAME/redis-exporter` | +| `metrics.image.digest` | Redis® Exporter image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `metrics.image.pullPolicy` | Redis® Exporter image pull policy | `IfNotPresent` | +| `metrics.image.pullSecrets` | Redis® Exporter image pull secrets | `[]` | +| `metrics.startupProbe.enabled` | Enable startupProbe on Redis® replicas nodes | `false` | +| `metrics.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `10` | +| `metrics.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `metrics.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `metrics.startupProbe.failureThreshold` | Failure threshold for startupProbe | `5` | +| `metrics.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `metrics.livenessProbe.enabled` | Enable livenessProbe on Redis® replicas nodes | `true` | +| `metrics.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `10` | +| `metrics.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `metrics.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `metrics.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `5` | +| `metrics.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `metrics.readinessProbe.enabled` | Enable readinessProbe on Redis® replicas nodes | `true` | +| `metrics.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `metrics.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `metrics.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `1` | +| `metrics.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `3` | +| `metrics.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `metrics.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `metrics.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `metrics.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `metrics.command` | Override default metrics container init command (useful when using custom images) | `[]` | +| `metrics.redisTargetHost` | A way to specify an alternative Redis® hostname | `localhost` | +| `metrics.extraArgs` | Extra arguments for Redis® exporter, for example: | `{}` | +| `metrics.extraEnvVars` | Array with extra environment variables to add to Redis® exporter | `[]` | +| `metrics.containerSecurityContext.enabled` | Enabled Redis® exporter containers' Security Context | `true` | +| `metrics.containerSecurityContext.runAsUser` | Set Redis® exporter containers' Security Context runAsUser | `1001` | +| `metrics.containerSecurityContext.runAsGroup` | Set Redis® exporter containers' Security Context runAsGroup | `0` | +| `metrics.containerSecurityContext.runAsNonRoot` | Set Redis® exporter containers' Security Context runAsNonRoot | `true` | +| `metrics.containerSecurityContext.allowPrivilegeEscalation` | Set Redis® exporter containers' Security Context allowPrivilegeEscalation | `false` | +| `metrics.containerSecurityContext.seccompProfile.type` | Set Redis® exporter containers' Security Context seccompProfile | `RuntimeDefault` | +| `metrics.containerSecurityContext.capabilities.drop` | Set Redis® exporter containers' Security Context capabilities to drop | `["ALL"]` | +| `metrics.extraVolumes` | Optionally specify extra list of additional volumes for the Redis® metrics sidecar | `[]` | +| `metrics.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the Redis® metrics sidecar | `[]` | +| `metrics.resources.limits` | The resources limits for the Redis® exporter container | `{}` | +| `metrics.resources.requests` | The requested resources for the Redis® exporter container | `{}` | +| `metrics.podLabels` | Extra labels for Redis® exporter pods | `{}` | +| `metrics.podAnnotations` | Annotations for Redis® exporter pods | `{}` | +| `metrics.service.type` | Redis® exporter service type | `ClusterIP` | +| `metrics.service.port` | Redis® exporter service port | `9121` | +| `metrics.service.externalTrafficPolicy` | Redis® exporter service external traffic policy | `Cluster` | +| `metrics.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `metrics.service.loadBalancerIP` | Redis® exporter service Load Balancer IP | `""` | +| `metrics.service.loadBalancerClass` | exporter service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) | `""` | +| `metrics.service.loadBalancerSourceRanges` | Redis® exporter service Load Balancer sources | `[]` | +| `metrics.service.annotations` | Additional custom annotations for Redis® exporter service | `{}` | +| `metrics.service.clusterIP` | Redis® exporter service Cluster IP | `""` | +| `metrics.serviceMonitor.enabled` | Create ServiceMonitor resource(s) for scraping metrics using PrometheusOperator | `false` | +| `metrics.serviceMonitor.namespace` | The namespace in which the ServiceMonitor will be created | `""` | +| `metrics.serviceMonitor.interval` | The interval at which metrics should be scraped | `30s` | +| `metrics.serviceMonitor.scrapeTimeout` | The timeout after which the scrape is ended | `""` | +| `metrics.serviceMonitor.relabellings` | Metrics RelabelConfigs to apply to samples before scraping. | `[]` | +| `metrics.serviceMonitor.metricRelabelings` | Metrics RelabelConfigs to apply to samples before ingestion. | `[]` | +| `metrics.serviceMonitor.honorLabels` | Specify honorLabels parameter to add the scrape endpoint | `false` | +| `metrics.serviceMonitor.additionalLabels` | Additional labels that can be used so ServiceMonitor resource(s) can be discovered by Prometheus | `{}` | +| `metrics.serviceMonitor.podTargetLabels` | Labels from the Kubernetes pod to be transferred to the created metrics | `[]` | +| `metrics.serviceMonitor.sampleLimit` | Limit of how many samples should be scraped from every Pod | `false` | +| `metrics.serviceMonitor.targetLimit` | Limit of how many targets should be scraped | `false` | +| `metrics.podMonitor.enabled` | Create PodMonitor resource(s) for scraping metrics using PrometheusOperator | `false` | +| `metrics.podMonitor.namespace` | The namespace in which the PodMonitor will be created | `""` | +| `metrics.podMonitor.interval` | The interval at which metrics should be scraped | `30s` | +| `metrics.podMonitor.scrapeTimeout` | The timeout after which the scrape is ended | `""` | +| `metrics.podMonitor.relabellings` | Metrics RelabelConfigs to apply to samples before scraping. | `[]` | +| `metrics.podMonitor.metricRelabelings` | Metrics RelabelConfigs to apply to samples before ingestion. | `[]` | +| `metrics.podMonitor.honorLabels` | Specify honorLabels parameter to add the scrape endpoint | `false` | +| `metrics.podMonitor.additionalLabels` | Additional labels that can be used so PodMonitor resource(s) can be discovered by Prometheus | `{}` | +| `metrics.podMonitor.podTargetLabels` | Labels from the Kubernetes pod to be transferred to the created metrics | `[]` | +| `metrics.podMonitor.sampleLimit` | Limit of how many samples should be scraped from every Pod | `false` | +| `metrics.podMonitor.targetLimit` | Limit of how many targets should be scraped | `false` | +| `metrics.prometheusRule.enabled` | Create a custom prometheusRule Resource for scraping metrics using PrometheusOperator | `false` | +| `metrics.prometheusRule.namespace` | The namespace in which the prometheusRule will be created | `""` | +| `metrics.prometheusRule.additionalLabels` | Additional labels for the prometheusRule | `{}` | +| `metrics.prometheusRule.rules` | Custom Prometheus rules | `[]` | + +### Init Container Parameters + +| Name | Description | Value | +| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------ | -------------------------- | +| `volumePermissions.enabled` | Enable init container that changes the owner/group of the PV mount point to `runAsUser:fsGroup` | `false` | +| `volumePermissions.image.registry` | OS Shell + Utility image registry | `REGISTRY_NAME` | +| `volumePermissions.image.repository` | OS Shell + Utility image repository | `REPOSITORY_NAME/os-shell` | +| `volumePermissions.image.digest` | OS Shell + Utility image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `volumePermissions.image.pullPolicy` | OS Shell + Utility image pull policy | `IfNotPresent` | +| `volumePermissions.image.pullSecrets` | OS Shell + Utility image pull secrets | `[]` | +| `volumePermissions.resources.limits` | The resources limits for the init container | `{}` | +| `volumePermissions.resources.requests` | The requested resources for the init container | `{}` | +| `volumePermissions.containerSecurityContext.runAsUser` | Set init container's Security Context runAsUser | `0` | +| `sysctl.enabled` | Enable init container to modify Kernel settings | `false` | +| `sysctl.image.registry` | OS Shell + Utility image registry | `REGISTRY_NAME` | +| `sysctl.image.repository` | OS Shell + Utility image repository | `REPOSITORY_NAME/os-shell` | +| `sysctl.image.digest` | OS Shell + Utility image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `sysctl.image.pullPolicy` | OS Shell + Utility image pull policy | `IfNotPresent` | +| `sysctl.image.pullSecrets` | OS Shell + Utility image pull secrets | `[]` | +| `sysctl.command` | Override default init-sysctl container command (useful when using custom images) | `[]` | +| `sysctl.mountHostSys` | Mount the host `/sys` folder to `/host-sys` | `false` | +| `sysctl.resources.limits` | The resources limits for the init container | `{}` | +| `sysctl.resources.requests` | The requested resources for the init container | `{}` | + +### useExternalDNS Parameters + +| Name | Description | Value | +| -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | +| `useExternalDNS.enabled` | Enable various syntax that would enable external-dns to work. Note this requires a working installation of `external-dns` to be usable. | `false` | +| `useExternalDNS.additionalAnnotations` | Extra annotations to be utilized when `external-dns` is enabled. | `{}` | +| `useExternalDNS.annotationKey` | The annotation key utilized when `external-dns` is enabled. Setting this to `false` will disable annotations. | `external-dns.alpha.kubernetes.io/` | +| `useExternalDNS.suffix` | The DNS suffix utilized when `external-dns` is enabled. Note that we prepend the suffix with the full name of the release. | `""` | + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +helm install my-release \ + --set auth.password=secretpassword \ + oci://REGISTRY_NAME/REPOSITORY_NAME/redis +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The above command sets the Redis® server password to `secretpassword`. + +> NOTE: Once this chart is deployed, it is not possible to change the application's access credentials, such as usernames or passwords, using Helm. To change these application credentials after deployment, delete any persistent volumes (PVs) used by the chart and re-deploy it, or use the application's built-in administrative tools if available. + +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 oci://REGISTRY_NAME/REPOSITORY_NAME/redis +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> **Tip**: You can use the default [values.yaml](https://github.com/bitnami/charts/tree/main/bitnami/redis/values.yaml) + +## Configuration and installation details + +### [Rolling VS Immutable tags](https://docs.bitnami.com/tutorials/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. + +### Use a different Redis® version + +To modify the application version used in this chart, specify a different version of the image using the `image.tag` parameter and/or a different repository using the `image.repository` parameter. Refer to the [chart documentation for more information on these parameters and how to use them with images from a private registry](https://docs.bitnami.com/kubernetes/infrastructure/redis/configuration/change-image-version/). + +### Bootstrapping with an External Cluster + +This chart is equipped with the ability to bring online a set of Pods that connect to an existing Redis deployment that lies outside of Kubernetes. This effectively creates a hybrid Redis Deployment where both Pods in Kubernetes and Instances such as Virtual Machines can partake in a single Redis Deployment. This is helpful in situations where one may be migrating Redis from Virtual Machines into Kubernetes, for example. To take advantage of this, use the following as an example configuration: + +```yaml +replica: + externalMaster: + enabled: true + host: external-redis-0.internal +sentinel: + externalMaster: + enabled: true + host: external-redis-0.internal +``` + +:warning: This is currently limited to clusters in which Sentinel and Redis run on the same node! :warning: + +Please also note that the external sentinel must be listening on port `26379`, and this is currently not configurable. + +Once the Kubernetes Redis Deployment is online and confirmed to be working with the existing cluster, the configuration can then be removed and the cluster will remain connected. + +### External DNS + +This chart is equipped to allow leveraging the ExternalDNS project. Doing so will enable ExternalDNS to publish the FQDN for each instance, in the format of `..`. +Example, when using the following configuration: + +```yaml +useExternalDNS: + enabled: true + suffix: prod.example.org + additionalAnnotations: + ttl: 10 +``` + +On a cluster where the name of the Helm release is `a`, the hostname of a Pod is generated as: `a-redis-node-0.a-redis.prod.example.org`. The IP of that FQDN will match that of the associated Pod. This modifies the following parameters of the Redis/Sentinel configuration using this new FQDN: + +- `replica-announce-ip` +- `known-sentinel` +- `known-replica` +- `announce-ip` + +:warning: This requires a working installation of `external-dns` to be fully functional. :warning: + +See the [official ExternalDNS documentation](https://github.com/kubernetes-sigs/external-dns) for additional configuration options. + +### Cluster topologies + +#### Default: Master-Replicas + +When installing the chart with `architecture=replication`, it will deploy a Redis® master StatefulSet and a Redis® replicas StatefulSet. The replicas will be read-replicas of the master. Two services will be exposed: + +- Redis® Master service: Points to the master, where read-write operations can be performed +- Redis® Replicas service: Points to the replicas, where only read operations are allowed by default. + +In case the master crashes, the replicas will wait until the master node is respawned again by the Kubernetes Controller Manager. + +#### Standalone + +When installing the chart with `architecture=standalone`, it will deploy a standalone Redis® StatefulSet. A single service will be exposed: + +- Redis® Master service: Points to the master, where read-write operations can be performed + +#### Master-Replicas with Sentinel + +When installing the chart with `architecture=replication` and `sentinel.enabled=true`, it will deploy a Redis® master StatefulSet (only one master allowed) and a Redis® replicas StatefulSet. In this case, the pods will contain an extra container with Redis® Sentinel. This container will form a cluster of Redis® Sentinel nodes, which will promote a new master in case the actual one fails. + +On graceful termination of the Redis® master pod, a failover of the master is initiated to promote a new master. The Redis® Sentinel container in this pod will wait for the failover to occur before terminating. If `sentinel.redisShutdownWaitFailover=true` is set (the default), the Redis® container will wait for the failover as well before terminating. This increases availability for reads during failover, but may cause stale reads until all clients have switched to the new master. + +In addition to this, only one service is exposed: + +- Redis® service: Exposes port 6379 for Redis® read-only operations and port 26379 for accessing Redis® Sentinel. + +For read-only operations, access the service using port 6379. For write operations, it's necessary to access the Redis® Sentinel cluster and query the current master using the command below (using redis-cli or similar): + +```console +SENTINEL get-master-addr-by-name +``` + +This command will return the address of the current master, which can be accessed from inside the cluster. + +In case the current master crashes, the Sentinel containers will elect a new master node. + +`master.count` greater than `1` is not designed for use when `sentinel.enabled=true`. + +### Multiple masters (experimental) + +When `master.count` is greater than `1`, special care must be taken to create a consistent setup. + +An example of use case is the creation of a redundant set of standalone masters or master-replicas per Kubernetes node where you must ensure: + +- No more than `1` master can be deployed per Kubernetes node +- Replicas and writers can only see the single master of their own Kubernetes node + +One way of achieving this is by setting `master.service.internalTrafficPolicy=Local` in combination with a `master.affinity.podAntiAffinity` spec to never schedule more than one master per Kubernetes node. + +It's recommended to only change `master.count` if you know what you are doing. +`master.count` greater than `1` is not designed for use when `sentinel.enabled=true`. + +### Using a password file + +To use a password file for Redis® you need to create a secret containing the password and then deploy the chart using that secret. + +Refer to the chart documentation for more information on [using a password file for Redis®](https://docs.bitnami.com/kubernetes/infrastructure/redis/administration/use-password-file/). + +### Securing traffic using TLS + +TLS support can be enabled in the chart by specifying the `tls.` parameters while creating a release. The following parameters should be configured to properly enable the TLS support in the chart: + +- `tls.enabled`: Enable TLS support. Defaults to `false` +- `tls.existingSecret`: Name of the secret that contains the certificates. No defaults. +- `tls.certFilename`: Certificate filename. No defaults. +- `tls.certKeyFilename`: Certificate key filename. No defaults. +- `tls.certCAFilename`: CA Certificate filename. No defaults. + +Refer to the chart documentation for more information on [creating the secret and a TLS deployment example](https://docs.bitnami.com/kubernetes/infrastructure/redis/administration/enable-tls/). + +### Metrics + +The chart optionally can start a metrics exporter for [prometheus](https://prometheus.io). The metrics endpoint (port 9121) is exposed in the service. Metrics can be scraped from within the 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). If metrics are to be scraped from outside the cluster, the Kubernetes API proxy can be utilized to access the endpoint. + +If you have enabled TLS by specifying `tls.enabled=true` you also need to specify TLS option to the metrics exporter. You can do that via `metrics.extraArgs`. You can find the metrics exporter CLI flags for TLS [here](https://github.com/oliver006/redis_exporter#command-line-flags). For example: + +You can either specify `metrics.extraArgs.skip-tls-verification=true` to skip TLS verification or providing the following values under `metrics.extraArgs` for TLS client authentication: + +```console +tls-client-key-file +tls-client-cert-file +tls-ca-cert-file +``` + +### Host Kernel Settings + +Redis® may require some changes in the kernel of the host machine to work as expected, in particular increasing the `somaxconn` value and disabling transparent huge pages. + +Refer to the chart documentation for more information on [configuring host kernel settings with an example](https://docs.bitnami.com/kubernetes/infrastructure/redis/administration/configure-kernel-settings/). + +## Persistence + +By default, the chart mounts a [Persistent Volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) at the `/data` path. The volume is created using dynamic volume provisioning. If a Persistent Volume Claim already exists, specify it during installation. + +### Existing PersistentVolumeClaim + +1. Create the PersistentVolume +2. Create the PersistentVolumeClaim +3. Install the chart + +```console +helm install my-release --set master.persistence.existingClaim=PVC_NAME oci://REGISTRY_NAME/REPOSITORY_NAME/redis +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +## Backup and restore + +Refer to the chart documentation for more information on [backing up and restoring Redis® deployments](https://docs.bitnami.com/kubernetes/infrastructure/redis/administration/backup-restore/). + +## NetworkPolicy + +To enable network policy for Redis®, 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`. + +Refer to the chart documenation for more information on [enabling the network policy in Redis® deployments](https://docs.bitnami.com/kubernetes/infrastructure/redis/administration/enable-network-policy/). + +### Setting Pod's affinity + +This chart allows you to set your custom affinity using the `XXX.affinity` parameter(s). Find more information about Pod's affinity in the [Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). + +As an alternative, you can use of the preset configurations for pod affinity, pod anti-affinity, and node affinity available at the [bitnami/common](https://github.com/bitnami/charts/tree/main/bitnami/common#affinities) chart. To do so, set the `XXX.podAffinityPreset`, `XXX.podAntiAffinityPreset`, or `XXX.nodeAffinityPreset` parameters. + +## Troubleshooting + +Find more information about how to deal with common errors related to Bitnami's Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues). + +## Upgrading + +A major chart version change (like v1.2.3 -> v2.0.0) indicates that there is an incompatible breaking change needing manual actions. + +### RDB compatibility + +It's common to have RDB format changes across Redis® releases where we see backward compatibility but no forward compatibility. For example, v7.0 can load an RDB created by v6.2 , but the opposite is not true. +When that's the case, the rolling update can cause replicas to temporarily stop synchronizing while they are running a lower version than master. +For example, on a rolling update `master-0` and `replica-2` are updated first from version v6.2 to v7.0; `replica-0` and `replica-1` won't be able to start a full sync with `master-0` because they are still running v6.2 and can't support the RDB format from version 7.0 that master is now using. +This issue can be mitigated by splitting the upgrade into two stages: one for all replicas and another for any master. + +- Stage 1 (replicas only, as there's no master with an ordinal higher than 99): +`helm upgrade oci://REGISTRY_NAME/REPOSITORY_NAME/redis --set master.updateStrategy.rollingUpdate.partition=99` +- Stage 2 (anything else that is not up to date, in this case only master): +`helm upgrade oci://REGISTRY_NAME/REPOSITORY_NAME/redis` + +### To 18.0.0 + +This major version updates the Redis® docker image version used from `7.0` to `7.2`, the new stable version. There are no major changes in the chart, but we recommend checking the [Redis® 7.2 release notes](https://raw.githubusercontent.com/redis/redis/7.2/00-RELEASENOTES) before upgrading. + +NOTE: Due to an error in our release process, versions higher or equal than 17.15.4 already use 7.2 by default. + +### To 17.0.0 + +This major version updates the Redis® docker image version used from `6.2` to `7.0`, the new stable version. There are no major changes in the chart, but we recommend checking the [Redis® 7.0 release notes](https://raw.githubusercontent.com/redis/redis/7.0/00-RELEASENOTES) before upgrading. + +### To 16.0.0 + +This major release renames several values in this chart and adds missing features, in order to be inline with the rest of assets in the Bitnami charts repository. + +Affected values: + +- `master.service.port` renamed as `master.service.ports.redis`. +- `master.service.nodePort` renamed as `master.service.nodePorts.redis`. +- `replica.service.port` renamed as `replica.service.ports.redis`. +- `replica.service.nodePort` renamed as `replica.service.nodePorts.redis`. +- `sentinel.service.port` renamed as `sentinel.service.ports.redis`. +- `sentinel.service.sentinelPort` renamed as `sentinel.service.ports.sentinel`. +- `master.containerPort` renamed as `master.containerPorts.redis`. +- `replica.containerPort` renamed as `replica.containerPorts.redis`. +- `sentinel.containerPort` renamed as `sentinel.containerPorts.sentinel`. +- `master.spreadConstraints` renamed as `master.topologySpreadConstraints` +- `replica.spreadConstraints` renamed as `replica.topologySpreadConstraints` + +### To 15.0.0 + +The parameter to enable the usage of StaticIDs was removed. The behavior is to [always use StaticIDs](https://github.com/bitnami/charts/pull/7278). + +### To 14.8.0 + +The Redis® sentinel exporter was removed in this version because the upstream project was deprecated. The regular Redis® exporter is included in the sentinel scenario as usual. + +### To 14.0.0 + +- Several parameters were renamed or disappeared in favor of new ones on this major version: + - The term *slave* has been replaced by the term *replica*. Therefore, parameters prefixed with `slave` are now prefixed with `replicas`. + - Credentials parameter are reorganized under the `auth` parameter. + - `cluster.enabled` parameter is deprecated in favor of `architecture` parameter that accepts two values: `standalone` and `replication`. + - `securityContext.*` is deprecated in favor of `XXX.podSecurityContext` and `XXX.containerSecurityContext`. + - `sentinel.metrics.*` parameters are deprecated in favor of `metrics.sentinel.*` ones. +- New parameters to add custom command, environment variables, sidecars, init containers, etc. were added. +- Chart labels were adapted to follow the [Helm charts standard labels](https://helm.sh/docs/chart_best_practices/labels/#standard-labels). +- values.yaml metadata was adapted to follow the format supported by [Readme Generator for Helm](https://github.com/bitnami/readme-generator-for-helm). + +Consequences: + +Backwards compatibility is not guaranteed. To upgrade to `14.0.0`, install a new release of the Redis® chart, and migrate the data from your previous release. You have 2 alternatives to do so: + +- Create a backup of the database, and restore it on the new release as explained in the [Backup and restore](#backup-and-restore) section. +- Reuse the PVC used to hold the master data on your previous release. To do so, use the `master.persistence.existingClaim` parameter. The following example assumes that the release name is `redis`: + +```console +helm install redis oci://REGISTRY_NAME/REPOSITORY_NAME/redis --set auth.password=[PASSWORD] --set master.persistence.existingClaim=[EXISTING_PVC] +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +| Note: you need to substitute the placeholder *[EXISTING_PVC]* with the name of the PVC used on your previous release, and *[PASSWORD]* with the password used in your previous release. + +### To 13.0.0 + +This major version updates the Redis® docker image version used from `6.0` to `6.2`, the new stable version. There are no major changes in the chart and there shouldn't be any breaking changes in it as `6.2` is basically a stricter superset of `6.0`. For more information, please refer to [Redis® 6.2 release notes](https://raw.githubusercontent.com/redis/redis/6.2/00-RELEASENOTES). + +### To 12.3.0 + +This version also introduces `bitnami/common`, a [library chart](https://helm.sh/docs/topics/library_charts/#helm) as a dependency. More documentation about this new utility could be found [here](https://github.com/bitnami/charts/tree/main/bitnami/common#bitnami-common-library-chart). Please, make sure that you have updated the chart dependencies before executing any upgrade. + +### To 12.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +#### What changes were introduced in this major version? + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts + +#### Considerations when upgrading to this version + +- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues +- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore +- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 + +#### Useful links + +- +- +- + +### To 11.0.0 + +When using sentinel, a new statefulset called `-node` was introduced. This will break upgrading from a previous version where the statefulsets are called master and slave. Hence the PVC will not match the new naming and won't be reused. If you want to keep your data, you will need to perform a backup and then a restore the data in this new version. + +When deployed with sentinel enabled, only a group of nodes is deployed and the master/slave role is handled in the group. To avoid breaking the compatibility, the settings for this nodes are given through the `slave.xxxx` parameters in `values.yaml` + +### To 10.0.0 + +For releases with `usePassword: true`, the value `sentinel.usePassword` controls whether the password authentication also applies to the sentinel port. This defaults to `true` for a secure configuration, however it is possible to disable to account for the following cases: + +- Using a version of redis-sentinel prior to `5.0.1` where the authentication feature was introduced. +- Where redis clients need to be updated to support sentinel authentication. + +If using a master/slave topology, or with `usePassword: false`, no action is required. + +### To 9.0.0 + +The metrics exporter has been changed from a separate deployment to a sidecar container, due to the latest changes in the Redis® exporter code. Check the [official page](https://github.com/oliver006/redis_exporter/) for more information. The metrics container image was changed from oliver006/redis_exporter to bitnami/redis-exporter (Bitnami's maintained package of oliver006/redis_exporter). + +### To 8.0.18 + +For releases with `metrics.enabled: true` the default tag for the exporter image is now `v1.x.x`. This introduces many changes including metrics names. You'll want to use [this dashboard](https://github.com/oliver006/redis_exporter/blob/master/contrib/grafana_prometheus_redis_dashboard.json) now. Please see the [redis_exporter github page](https://github.com/oliver006/redis_exporter#upgrading-from-0x-to-1x) for more details. + +### To 7.0.0 + +This version causes a change in the Redis® Master StatefulSet definition, so the command helm upgrade would not work out of the box. As an alternative, one of the following could be done: + +- Recommended: Create a clone of the Redis® Master PVC (for example, using projects like [this one](https://github.com/edseymour/pvc-transfer)). Then launch a fresh release reusing this cloned PVC. + +```console +helm install my-release oci://REGISTRY_NAME/REPOSITORY_NAME/redis --set persistence.existingClaim= +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +- Alternative (not recommended, do at your own risk): `helm delete --purge` does not remove the PVC assigned to the Redis® Master StatefulSet. As a consequence, the following commands can be done to upgrade the release + +```console +helm delete --purge +helm install oci://REGISTRY_NAME/REPOSITORY_NAME/redis +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +Previous versions of the chart were not using persistence in the slaves, so this upgrade would add it to them. Another important change is that no values are inherited from master to slaves. For example, in 6.0.0 `slaves.readinessProbe.periodSeconds`, if empty, would be set to `master.readinessProbe.periodSeconds`. This approach lacked transparency and was difficult to maintain. From now on, all the slave parameters must be configured just as it is done with the masters. + +Some values have changed as well: + +- `master.port` and `slave.port` have been changed to `redisPort` (same value for both master and slaves) +- `master.securityContext` and `slave.securityContext` have been changed to `securityContext`(same values for both master and slaves) + +By default, the upgrade will not change the cluster topology. In case you want to use Redis® Sentinel, you must explicitly set `sentinel.enabled` to `true`. + +### To 6.0.0 + +Previous versions of the chart were using an init-container to change the permissions of the volumes. This was done in case the `securityContext` directive in the template was not enough for that (for example, with cephFS). In this new version of the chart, this container is disabled by default (which should not affect most of the deployments). If your installation still requires that init container, execute `helm upgrade` with the `--set volumePermissions.enabled=true`. + +### To 5.0.0 + +The default image in this release may be switched out for any image containing the `redis-server` +and `redis-cli` binaries. If `redis-server` is not the default image ENTRYPOINT, `master.command` +must be specified. + +#### Breaking changes + +- `master.args` and `slave.args` are removed. Use `master.command` or `slave.command` instead in order to override the image entrypoint, or `master.extraFlags` to pass additional flags to `redis-server`. +- `disableCommands` is now interpreted as an array of strings instead of a string of comma separated values. +- `master.persistence.path` now defaults to `/data`. + +### To 4.0.0 + +This version removes the `chart` label from the `spec.selector.matchLabels` +which is immutable since `StatefulSet apps/v1beta2`. It has been inadvertently +added, causing any subsequent upgrade to fail. See . + +It also fixes where a deployment `extensions/v1beta1` can not be upgraded if `spec.selector` is not explicitly set. + +Finally, it fixes by removing mutable labels in `spec.VolumeClaimTemplate.metadata.labels` so that it is upgradable. + +In order to upgrade, delete the Redis® StatefulSet before upgrading: + +```console +kubectl delete statefulsets.apps --cascade=false my-release-redis-master +``` + +And edit the Redis® slave (and metrics if enabled) deployment: + +```console +kubectl patch deployments my-release-redis-slave --type=json -p='[{"op": "remove", "path": "/spec/selector/matchLabels/chart"}]' +kubectl patch deployments my-release-redis-metrics --type=json -p='[{"op": "remove", "path": "/spec/selector/matchLabels/chart"}]' +``` + +## License + +Copyright © 2024 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/backing-services/redis/auction-onsite-alpha.values.yaml b/backing-services/redis/auction-onsite-alpha.values.yaml new file mode 100644 index 0000000..041136e --- /dev/null +++ b/backing-services/redis/auction-onsite-alpha.values.yaml @@ -0,0 +1,26 @@ +global: + redis: + password: "Auction12" + +auth: + service: + type: ClusterIP + + enabled: true + sentinel: true + password: "Auction12" + +architecture: standalone + +# replica: +# serviceAccount: +# create: true +# name: "redisservcieaccount" +# automountServiceAccountToken: true +# annotations: {} + +# persistence: +# enabled: true +# path: /data +# storageClass: "efs-sc" +# size: 2Gi \ No newline at end of file diff --git a/backing-services/redis/auction-stage-eks.values.yaml b/backing-services/redis/auction-stage-eks.values.yaml new file mode 100644 index 0000000..323becb --- /dev/null +++ b/backing-services/redis/auction-stage-eks.values.yaml @@ -0,0 +1,34 @@ +global: + redis: + password: "Auction12" + +auth: + service: + type: ClusterIP + + enabled: true + sentinel: true + password: "Auction12" + +architecture: standalone + +master: + serviceAccount: + create: true + name: "redisserviceaccount" + automountServiceAccountToken: true + annotations: + eks.amazonaws.com/role-arn: "arn:aws:iam::667294666490:role/auction-cluster-20241126163757775000000001" + +# replica: +# serviceAccount: +# create: true +# name: "redisservcieaccount" +# automountServiceAccountToken: true +# annotations: {} + +# persistence: +# enabled: true +# path: /data +# storageClass: "efs-sc" +# size: 2Gi \ No newline at end of file diff --git a/backing-services/redis/charts/common-2.14.1.tgz b/backing-services/redis/charts/common-2.14.1.tgz new file mode 100644 index 0000000..f443a7c Binary files /dev/null and b/backing-services/redis/charts/common-2.14.1.tgz differ diff --git a/backing-services/redis/img/redis-cluster-topology.png b/backing-services/redis/img/redis-cluster-topology.png new file mode 100644 index 0000000..f0a02a9 Binary files /dev/null and b/backing-services/redis/img/redis-cluster-topology.png differ diff --git a/backing-services/redis/img/redis-topology.png b/backing-services/redis/img/redis-topology.png new file mode 100644 index 0000000..3f5280f Binary files /dev/null and b/backing-services/redis/img/redis-topology.png differ diff --git a/backing-services/redis/schoobus-onsite.values.yaml b/backing-services/redis/schoobus-onsite.values.yaml new file mode 100644 index 0000000..49711b7 --- /dev/null +++ b/backing-services/redis/schoobus-onsite.values.yaml @@ -0,0 +1,25 @@ +global: + redis: + password: "secret123" + +auth: + service: + type: ClusterIP + enabled: true + sentinel: true + password: "secret123" + +architecture: standalone + +# replica: +# serviceAccount: +# create: true +# name: "redisservcieaccount" +# automountServiceAccountToken: true +# annotations: {} + +# persistence: +# enabled: true +# path: /data +# storageClass: "efs-sc" +# size: 2Gi \ No newline at end of file diff --git a/backing-services/redis/school-stage-tavana.values.yaml b/backing-services/redis/school-stage-tavana.values.yaml new file mode 100644 index 0000000..e667135 --- /dev/null +++ b/backing-services/redis/school-stage-tavana.values.yaml @@ -0,0 +1,33 @@ +global: + redis: + password: "secret123" + +image: + registry: 172.16.16.1:30516 + repository: bitnami/redis + tag: 7.2.4-debian-11-r0 + +auth: + service: + type: ClusterIP + enabled: true + sentinel: true + password: "secret123" + +architecture: standalone + +# replica: +# serviceAccount: +# create: true +# name: "redisservcieaccount" +# automountServiceAccountToken: true +# annotations: {} + +# persistence: +# enabled: true +# path: /data +# storageClass: "efs-sc" +# size: 2Gi + +nodeSelector: + node.name: node-01 \ No newline at end of file diff --git a/backing-services/redis/schoolbus-demo.values.yaml b/backing-services/redis/schoolbus-demo.values.yaml new file mode 100644 index 0000000..c3b6144 --- /dev/null +++ b/backing-services/redis/schoolbus-demo.values.yaml @@ -0,0 +1,41 @@ +global: + redis: + password: "secret123" + +image: + registry: 172.16.16.2:30516 + repository: bitnami/redis + tag: 7.2.4-debian-11-r0 + +auth: + service: + type: ClusterIP + enabled: true + sentinel: true + password: "secret123" + +architecture: standalone + +# replica: +# serviceAccount: +# create: true +# name: "redisservcieaccount" +# automountServiceAccountToken: true +# annotations: {} + +# persistence: +# enabled: true +# path: /data +# storageClass: "efs-sc" +# size: 2Gi + +master: + resources: + requests: + cpu: 500m + memory: 500Mi + limits: + cpu: 500m + memory: 500Mi + nodeSelector: + node.name: node-1 diff --git a/backing-services/redis/schoolbuses.values.yaml b/backing-services/redis/schoolbuses.values.yaml new file mode 100644 index 0000000..b45f19a --- /dev/null +++ b/backing-services/redis/schoolbuses.values.yaml @@ -0,0 +1,24 @@ +global: + storageClass: "efs-sc" + redis: + password: "" + +auth: + persistence: + storageClass: "efs-sc" + + service: + type: ClusterIP + +# replica: +# serviceAccount: +# create: true +# name: "redisservcieaccount" +# automountServiceAccountToken: true +# annotations: {} + +# persistence: +# enabled: true +# path: /data +# storageClass: "efs-sc" +# size: 2Gi \ No newline at end of file diff --git a/backing-services/redis/templates/NOTES.txt b/backing-services/redis/templates/NOTES.txt new file mode 100644 index 0000000..cc191de --- /dev/null +++ b/backing-services/redis/templates/NOTES.txt @@ -0,0 +1,191 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +** Please be patient while the chart is being deployed ** + +{{- if .Values.diagnosticMode.enabled }} +The chart has been deployed in diagnostic mode. All probes have been disabled and the command has been overwritten with: + + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 4 }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 4 }} + +Get the list of pods by executing: + + kubectl get pods --namespace {{ include "common.names.namespace" . }} -l app.kubernetes.io/instance={{ .Release.Name }} + +Access the pod you want to debug by executing + + kubectl exec --namespace {{ include "common.names.namespace" . }} -ti -- bash + +In order to replicate the container startup scripts execute this command: + +For Redis: + + /opt/bitnami/scripts/redis/entrypoint.sh /opt/bitnami/scripts/redis/run.sh + +{{- if .Values.sentinel.enabled }} + +For Redis Sentinel: + + /opt/bitnami/scripts/redis-sentinel/entrypoint.sh /opt/bitnami/scripts/redis-sentinel/run.sh + +{{- end }} +{{- else }} + +{{- if contains .Values.master.service.type "LoadBalancer" }} +{{- if not .Values.auth.enabled }} +{{ if and (not .Values.networkPolicy.enabled) (.Values.networkPolicy.allowExternal) }} + +------------------------------------------------------------------------------- + WARNING + + By specifying "master.service.type=LoadBalancer" and "auth.enabled=false" you have + most likely exposed the Redis® service externally without any authentication + mechanism. + + For security reasons, we strongly suggest that you switch to "ClusterIP" or + "NodePort". As alternative, you can also switch to "auth.enabled=true" + providing a valid password on "password" parameter. + +------------------------------------------------------------------------------- +{{- end }} +{{- end }} +{{- end }} + +{{- if eq .Values.architecture "replication" }} +{{- if .Values.sentinel.enabled }} + +Redis® can be accessed via port {{ .Values.sentinel.service.ports.redis }} on the following DNS name from within your cluster: + + {{ template "common.names.fullname" . }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }} for read only operations + +For read/write operations, first access the Redis® Sentinel cluster, which is available in port {{ .Values.sentinel.service.ports.sentinel }} using the same domain name above. + +{{- else }} + +Redis® can be accessed on the following DNS names from within your cluster: + + {{ printf "%s-master.%s.svc.%s" (include "common.names.fullname" .) (include "common.names.namespace" . ) .Values.clusterDomain }} for read/write operations (port {{ .Values.master.service.ports.redis }}) + {{ printf "%s-replicas.%s.svc.%s" (include "common.names.fullname" .) (include "common.names.namespace" . ) .Values.clusterDomain }} for read-only operations (port {{ .Values.replica.service.ports.redis }}) + +{{- end }} +{{- else }} + +Redis® can be accessed via port {{ .Values.master.service.ports.redis }} on the following DNS name from within your cluster: + + {{ template "common.names.fullname" . }}-master.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }} + +{{- end }} + +{{ if .Values.auth.enabled }} + +To get your password run: + + export REDIS_PASSWORD=$(kubectl get secret --namespace {{ include "common.names.namespace" . }} {{ template "redis.secretName" . }} -o jsonpath="{.data.redis-password}" | base64 -d) + +{{- end }} + +To connect to your Redis® server: + +1. Run a Redis® pod that you can use as a client: + + kubectl run --namespace {{ include "common.names.namespace" . }} redis-client --restart='Never' {{ if .Values.auth.enabled }} --env REDIS_PASSWORD=$REDIS_PASSWORD {{ end }} --image {{ template "redis.image" . }} --command -- sleep infinity + +{{- if .Values.tls.enabled }} + + Copy your TLS certificates to the pod: + + kubectl cp --namespace {{ include "common.names.namespace" . }} /path/to/client.cert redis-client:/tmp/client.cert + kubectl cp --namespace {{ include "common.names.namespace" . }} /path/to/client.key redis-client:/tmp/client.key + kubectl cp --namespace {{ include "common.names.namespace" . }} /path/to/CA.cert redis-client:/tmp/CA.cert + +{{- end }} + + Use the following command to attach to the pod: + + kubectl exec --tty -i redis-client \ + {{- if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }}--labels="{{ template "common.names.fullname" . }}-client=true" \{{- end }} + --namespace {{ include "common.names.namespace" . }} -- bash + +2. Connect using the Redis® CLI: + +{{- if eq .Values.architecture "replication" }} + {{- if .Values.sentinel.enabled }} + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$REDIS_PASSWORD" {{ end }}redis-cli -h {{ template "common.names.fullname" . }} -p {{ .Values.sentinel.service.ports.redis }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} # Read only operations + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$REDIS_PASSWORD" {{ end }}redis-cli -h {{ template "common.names.fullname" . }} -p {{ .Values.sentinel.service.ports.sentinel }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} # Sentinel access + {{- else }} + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$REDIS_PASSWORD" {{ end }}redis-cli -h {{ printf "%s-master" (include "common.names.fullname" .) }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$REDIS_PASSWORD" {{ end }}redis-cli -h {{ printf "%s-replicas" (include "common.names.fullname" .) }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + {{- end }} +{{- else }} + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$REDIS_PASSWORD" {{ end }}redis-cli -h {{ template "common.names.fullname" . }}-master{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} +{{- end }} + +{{- if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }} + +Note: Since NetworkPolicy is enabled, only pods with label {{ template "common.names.fullname" . }}-client=true" will be able to connect to redis. + +{{- else }} + +To connect to your database from outside the cluster execute the following commands: + +{{- if and (eq .Values.architecture "replication") .Values.sentinel.enabled }} +{{- if contains "NodePort" .Values.sentinel.service.type }} + + export NODE_IP=$(kubectl get nodes --namespace {{ include "common.names.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get --namespace {{ include "common.names.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "common.names.fullname" . }}) + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$REDIS_PASSWORD" {{ end }}redis-cli -h $NODE_IP -p $NODE_PORT {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- else if contains "LoadBalancer" .Values.sentinel.service.type }} + + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + Watch the status with: 'kubectl get svc --namespace {{ include "common.names.namespace" . }} -w {{ template "common.names.fullname" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ include "common.names.namespace" . }} {{ template "common.names.fullname" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$REDIS_PASSWORD" {{ end }}redis-cli -h $SERVICE_IP -p {{ .Values.sentinel.service.ports.redis }} {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- else if contains "ClusterIP" .Values.sentinel.service.type }} + + kubectl port-forward --namespace {{ include "common.names.namespace" . }} svc/{{ template "common.names.fullname" . }} {{ .Values.sentinel.service.ports.redis }}:{{ .Values.sentinel.service.ports.redis }} & + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$REDIS_PASSWORD" {{ end }}redis-cli -h 127.0.0.1 -p {{ .Values.sentinel.service.ports.redis }} {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- end }} +{{- else }} +{{- if contains "NodePort" .Values.master.service.type }} + + export NODE_IP=$(kubectl get nodes --namespace {{ include "common.names.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get --namespace {{ include "common.names.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ printf "%s-master" (include "common.names.fullname" .) }}) + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$REDIS_PASSWORD" {{ end }}redis-cli -h $NODE_IP -p $NODE_PORT {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- else if contains "LoadBalancer" .Values.master.service.type }} + + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + Watch the status with: 'kubectl get svc --namespace {{ include "common.names.namespace" . }} -w {{ template "common.names.fullname" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ include "common.names.namespace" . }} {{ printf "%s-master" (include "common.names.fullname" .) }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$REDIS_PASSWORD" {{ end }}redis-cli -h $SERVICE_IP -p {{ .Values.master.service.ports.redis }} {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- else if contains "ClusterIP" .Values.master.service.type }} + + kubectl port-forward --namespace {{ include "common.names.namespace" . }} svc/{{ printf "%s-master" (include "common.names.fullname" .) }} {{ .Values.master.service.ports.redis }}:{{ .Values.master.service.ports.redis }} & + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$REDIS_PASSWORD" {{ end }}redis-cli -h 127.0.0.1 -p {{ .Values.master.service.ports.redis }} {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- end }} +{{- end }} + +{{- end }} +{{- end }} +{{- include "redis.checkRollingTags" . }} +{{- include "common.warnings.rollingTag" .Values.volumePermissions.image }} +{{- include "common.warnings.rollingTag" .Values.sysctl.image }} +{{- include "redis.validateValues" . }} + +{{- if and (eq .Values.architecture "replication") .Values.sentinel.enabled (eq .Values.sentinel.service.type "NodePort") (not .Release.IsUpgrade ) }} +{{- if $.Values.sentinel.service.nodePorts.sentinel }} +No need to upgrade, ports and nodeports have been set from values +{{- else }} +#!#!#!#!#!#!#!# IMPORTANT #!#!#!#!#!#!#!# +YOU NEED TO PERFORM AN UPGRADE FOR THE SERVICES AND WORKLOAD TO BE CREATED +{{- end }} +{{- end }} diff --git a/backing-services/redis/templates/_helpers.tpl b/backing-services/redis/templates/_helpers.tpl new file mode 100644 index 0000000..9eb017f --- /dev/null +++ b/backing-services/redis/templates/_helpers.tpl @@ -0,0 +1,328 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the proper Redis image name +*/}} +{{- define "redis.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper Redis Sentinel image name +*/}} +{{- define "redis.sentinel.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.sentinel.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper image name (for the metrics image) +*/}} +{{- define "redis.metrics.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.metrics.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper image name (for the init container volume-permissions image) +*/}} +{{- define "redis.volumePermissions.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.volumePermissions.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return sysctl image +*/}} +{{- define "redis.sysctl.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.sysctl.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "redis.imagePullSecrets" -}} +{{- include "common.images.renderPullSecrets" (dict "images" (list .Values.image .Values.sentinel.image .Values.metrics.image .Values.volumePermissions.image .Values.sysctl.image) "context" $) -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "networkPolicy.apiVersion" -}} +{{- if semverCompare ">=1.4-0, <1.7-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiGroup for PodSecurityPolicy. +*/}} +{{- define "podSecurityPolicy.apiGroup" -}} +{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "policy" -}} +{{- else -}} +{{- print "extensions" -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a TLS secret object should be created +*/}} +{{- define "redis.createTlsSecret" -}} +{{- if and .Values.tls.enabled .Values.tls.autoGenerated (and (not .Values.tls.existingSecret) (not .Values.tls.certificatesSecret)) }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the secret containing Redis TLS certificates +*/}} +{{- define "redis.tlsSecretName" -}} +{{- $secretName := coalesce .Values.tls.existingSecret .Values.tls.certificatesSecret -}} +{{- if $secretName -}} + {{- printf "%s" (tpl $secretName $) -}} +{{- else -}} + {{- printf "%s-crt" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the cert file. +*/}} +{{- define "redis.tlsCert" -}} +{{- if (include "redis.createTlsSecret" . ) -}} + {{- printf "/opt/bitnami/redis/certs/%s" "tls.crt" -}} +{{- else -}} + {{- required "Certificate filename is required when TLS in enabled" .Values.tls.certFilename | printf "/opt/bitnami/redis/certs/%s" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the cert key file. +*/}} +{{- define "redis.tlsCertKey" -}} +{{- if (include "redis.createTlsSecret" . ) -}} + {{- printf "/opt/bitnami/redis/certs/%s" "tls.key" -}} +{{- else -}} + {{- required "Certificate Key filename is required when TLS in enabled" .Values.tls.certKeyFilename | printf "/opt/bitnami/redis/certs/%s" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the CA cert file. +*/}} +{{- define "redis.tlsCACert" -}} +{{- if (include "redis.createTlsSecret" . ) -}} + {{- printf "/opt/bitnami/redis/certs/%s" "ca.crt" -}} +{{- else -}} + {{- required "Certificate CA filename is required when TLS in enabled" .Values.tls.certCAFilename | printf "/opt/bitnami/redis/certs/%s" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the DH params file. +*/}} +{{- define "redis.tlsDHParams" -}} +{{- if .Values.tls.dhParamsFilename -}} +{{- printf "/opt/bitnami/redis/certs/%s" .Values.tls.dhParamsFilename -}} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the shared service account to use +*/}} +{{- define "redis.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "common.names.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the master service account to use +*/}} +{{- define "redis.masterServiceAccountName" -}} +{{- if .Values.master.serviceAccount.create -}} + {{ default (printf "%s-master" (include "common.names.fullname" .)) .Values.master.serviceAccount.name }} +{{- else -}} + {{- if .Values.serviceAccount.create -}} + {{ template "redis.serviceAccountName" . }} + {{- else -}} + {{ default "default" .Values.master.serviceAccount.name }} + {{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the replicas service account to use +*/}} +{{- define "redis.replicaServiceAccountName" -}} +{{- if .Values.replica.serviceAccount.create -}} + {{ default (printf "%s-replica" (include "common.names.fullname" .)) .Values.replica.serviceAccount.name }} +{{- else -}} + {{- if .Values.serviceAccount.create -}} + {{ template "redis.serviceAccountName" . }} + {{- else -}} + {{ default "default" .Values.replica.serviceAccount.name }} + {{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Return the configuration configmap name +*/}} +{{- define "redis.configmapName" -}} +{{- if .Values.existingConfigmap -}} + {{- printf "%s" (tpl .Values.existingConfigmap $) -}} +{{- else -}} + {{- printf "%s-configuration" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a configmap object should be created +*/}} +{{- define "redis.createConfigmap" -}} +{{- if empty .Values.existingConfigmap }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Get the password secret. +*/}} +{{- define "redis.secretName" -}} +{{- if .Values.auth.existingSecret -}} +{{- printf "%s" (tpl .Values.auth.existingSecret $) -}} +{{- else -}} +{{- printf "%s" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Get the password key to be retrieved from Redis® secret. +*/}} +{{- define "redis.secretPasswordKey" -}} +{{- if and .Values.auth.existingSecret .Values.auth.existingSecretPasswordKey -}} +{{- printf "%s" (tpl .Values.auth.existingSecretPasswordKey $) -}} +{{- else -}} +{{- printf "redis-password" -}} +{{- end -}} +{{- end -}} + + +{{/* +Returns the available value for certain key in an existing secret (if it exists), +otherwise it generates a random value. +*/}} +{{- define "getValueFromSecret" }} + {{- $len := (default 16 .Length) | int -}} + {{- $obj := (lookup "v1" "Secret" .Namespace .Name).data -}} + {{- if $obj }} + {{- index $obj .Key | b64dec -}} + {{- else -}} + {{- randAlphaNum $len -}} + {{- end -}} +{{- end }} + +{{/* +Return Redis® password +*/}} +{{- define "redis.password" -}} +{{- if or .Values.auth.enabled .Values.global.redis.password }} + {{- if not (empty .Values.global.redis.password) }} + {{- .Values.global.redis.password -}} + {{- else if not (empty .Values.auth.password) -}} + {{- .Values.auth.password -}} + {{- else -}} + {{- include "getValueFromSecret" (dict "Namespace" (include "common.names.namespace" .) "Name" (include "redis.secretName" .) "Length" 10 "Key" (include "redis.secretPasswordKey" .)) -}} + {{- end -}} +{{- end -}} +{{- end }} + +{{/* Check if there are rolling tags in the images */}} +{{- define "redis.checkRollingTags" -}} +{{- include "common.warnings.rollingTag" .Values.image }} +{{- include "common.warnings.rollingTag" .Values.sentinel.image }} +{{- include "common.warnings.rollingTag" .Values.metrics.image }} +{{- end -}} + +{{/* +Compile all warnings into a single message, and call fail. +*/}} +{{- define "redis.validateValues" -}} +{{- $messages := list -}} +{{- $messages := append $messages (include "redis.validateValues.topologySpreadConstraints" .) -}} +{{- $messages := append $messages (include "redis.validateValues.architecture" .) -}} +{{- $messages := append $messages (include "redis.validateValues.podSecurityPolicy.create" .) -}} +{{- $messages := append $messages (include "redis.validateValues.tls" .) -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}} +{{- end -}} +{{- end -}} + +{{/* Validate values of Redis® - spreadConstrainsts K8s version */}} +{{- define "redis.validateValues.topologySpreadConstraints" -}} +{{- if and (semverCompare "<1.16-0" .Capabilities.KubeVersion.GitVersion) .Values.replica.topologySpreadConstraints -}} +redis: topologySpreadConstraints + Pod Topology Spread Constraints are only available on K8s >= 1.16 + Find more information at https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ +{{- end -}} +{{- end -}} + +{{/* Validate values of Redis® - must provide a valid architecture */}} +{{- define "redis.validateValues.architecture" -}} +{{- if and (ne .Values.architecture "standalone") (ne .Values.architecture "replication") -}} +redis: architecture + Invalid architecture selected. Valid values are "standalone" and + "replication". Please set a valid architecture (--set architecture="xxxx") +{{- end -}} +{{- if and .Values.sentinel.enabled (not (eq .Values.architecture "replication")) }} +redis: architecture + Using redis sentinel on standalone mode is not supported. + To deploy redis sentinel, please select the "replication" mode + (--set "architecture=replication,sentinel.enabled=true") +{{- end -}} +{{- end -}} + +{{/* Validate values of Redis® - PodSecurityPolicy create */}} +{{- define "redis.validateValues.podSecurityPolicy.create" -}} +{{- if and .Values.podSecurityPolicy.create (not .Values.podSecurityPolicy.enabled) }} +redis: podSecurityPolicy.create + In order to create PodSecurityPolicy, you also need to enable + podSecurityPolicy.enabled field +{{- end -}} +{{- end -}} + +{{/* Validate values of Redis® - TLS enabled */}} +{{- define "redis.validateValues.tls" -}} +{{- if and .Values.tls.enabled (not .Values.tls.autoGenerated) (not .Values.tls.existingSecret) (not .Values.tls.certificatesSecret) }} +redis: tls.enabled + In order to enable TLS, you also need to provide + an existing secret containing the TLS certificates or + enable auto-generated certificates. +{{- end -}} +{{- end -}} + +{{/* Define the suffix utilized for external-dns */}} +{{- define "redis.externalDNS.suffix" -}} +{{ printf "%s.%s" (include "common.names.fullname" .) .Values.useExternalDNS.suffix }} +{{- end -}} + +{{/* Compile all annotations utilized for external-dns */}} +{{- define "redis.externalDNS.annotations" -}} +{{- if and .Values.useExternalDNS.enabled .Values.useExternalDNS.annotationKey }} +{{ .Values.useExternalDNS.annotationKey }}hostname: {{ include "redis.externalDNS.suffix" . }} +{{- range $key, $val := .Values.useExternalDNS.additionalAnnotations }} +{{ $.Values.useExternalDNS.annotationKey }}{{ $key }}: {{ $val | quote }} +{{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/redis/templates/configmap.yaml b/backing-services/redis/templates/configmap.yaml new file mode 100644 index 0000000..6c370a2 --- /dev/null +++ b/backing-services/redis/templates/configmap.yaml @@ -0,0 +1,61 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "redis.createConfigmap" .) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-configuration" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + redis.conf: |- + # User-supplied common configuration: + {{- if .Values.commonConfiguration }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonConfiguration "context" $ ) | nindent 4 }} + {{- end }} + # End of common configuration + master.conf: |- + dir {{ .Values.master.persistence.path }} + # User-supplied master configuration: + {{- if .Values.master.configuration }} + {{- include "common.tplvalues.render" ( dict "value" .Values.master.configuration "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.master.disableCommands }} + {{- range .Values.master.disableCommands }} + rename-command {{ . }} "" + {{- end }} + {{- end }} + # End of master configuration + replica.conf: |- + dir {{ .Values.replica.persistence.path }} + # User-supplied replica configuration: + {{- if .Values.replica.configuration }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.configuration "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.replica.disableCommands }} + {{- range .Values.replica.disableCommands }} + rename-command {{ . }} "" + {{- end }} + {{- end }} + # End of replica configuration + {{- if .Values.sentinel.enabled }} + sentinel.conf: |- + dir "/tmp" + port {{ .Values.sentinel.containerPorts.sentinel }} + sentinel monitor {{ .Values.sentinel.masterSet }} {{ template "common.names.fullname" . }}-node-0.{{ template "common.names.fullname" . }}-headless.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }} {{ .Values.sentinel.service.ports.redis }} {{ .Values.sentinel.quorum }} + sentinel down-after-milliseconds {{ .Values.sentinel.masterSet }} {{ .Values.sentinel.downAfterMilliseconds }} + sentinel failover-timeout {{ .Values.sentinel.masterSet }} {{ .Values.sentinel.failoverTimeout }} + sentinel parallel-syncs {{ .Values.sentinel.masterSet }} {{ .Values.sentinel.parallelSyncs }} + # User-supplied sentinel configuration: + {{- if .Values.sentinel.configuration }} + {{- include "common.tplvalues.render" ( dict "value" .Values.sentinel.configuration "context" $ ) | nindent 4 }} + {{- end }} + # End of sentinel configuration + {{- end }} +{{- end }} diff --git a/backing-services/redis/templates/extra-list.yaml b/backing-services/redis/templates/extra-list.yaml new file mode 100644 index 0000000..2d35a58 --- /dev/null +++ b/backing-services/redis/templates/extra-list.yaml @@ -0,0 +1,9 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/backing-services/redis/templates/headless-svc.yaml b/backing-services/redis/templates/headless-svc.yaml new file mode 100644 index 0000000..e69329f --- /dev/null +++ b/backing-services/redis/templates/headless-svc.yaml @@ -0,0 +1,33 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-headless" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + annotations: + {{- if or .Values.sentinel.service.headless.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.sentinel.service.headless.annotations .Values.commonAnnotations ) "context" . ) }} + {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} + {{- include "redis.externalDNS.annotations" . | nindent 4 }} +spec: + type: ClusterIP + clusterIP: None + {{- if .Values.sentinel.enabled }} + publishNotReadyAddresses: true + {{- end }} + ports: + - name: tcp-redis + port: {{ if .Values.sentinel.enabled }}{{ .Values.sentinel.service.ports.redis }}{{ else }}{{ .Values.master.service.ports.redis }}{{ end }} + targetPort: redis + {{- if .Values.sentinel.enabled }} + - name: tcp-sentinel + port: {{ .Values.sentinel.service.ports.sentinel }} + targetPort: redis-sentinel + {{- end }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} diff --git a/backing-services/redis/templates/health-configmap.yaml b/backing-services/redis/templates/health-configmap.yaml new file mode 100644 index 0000000..5d15b06 --- /dev/null +++ b/backing-services/redis/templates/health-configmap.yaml @@ -0,0 +1,194 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-health" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + ping_readiness_local.sh: |- + #!/bin/bash + + [[ -f $REDIS_PASSWORD_FILE ]] && export REDIS_PASSWORD="$(< "${REDIS_PASSWORD_FILE}")" + [[ -n "$REDIS_PASSWORD" ]] && export REDISCLI_AUTH="$REDIS_PASSWORD" + response=$( + timeout -s 15 $1 \ + redis-cli \ + -h localhost \ +{{- if .Values.tls.enabled }} + -p $REDIS_TLS_PORT \ + --tls \ + --cacert {{ template "redis.tlsCACert" . }} \ + {{- if .Values.tls.authClients }} + --cert {{ template "redis.tlsCert" . }} \ + --key {{ template "redis.tlsCertKey" . }} \ + {{- end }} +{{- else }} + -p $REDIS_PORT \ +{{- end }} + ping + ) + if [ "$?" -eq "124" ]; then + echo "Timed out" + exit 1 + fi + if [ "$response" != "PONG" ]; then + echo "$response" + exit 1 + fi + ping_liveness_local.sh: |- + #!/bin/bash + + [[ -f $REDIS_PASSWORD_FILE ]] && export REDIS_PASSWORD="$(< "${REDIS_PASSWORD_FILE}")" + [[ -n "$REDIS_PASSWORD" ]] && export REDISCLI_AUTH="$REDIS_PASSWORD" + response=$( + timeout -s 15 $1 \ + redis-cli \ + -h localhost \ +{{- if .Values.tls.enabled }} + -p $REDIS_TLS_PORT \ + --tls \ + --cacert {{ template "redis.tlsCACert" . }} \ + {{- if .Values.tls.authClients }} + --cert {{ template "redis.tlsCert" . }} \ + --key {{ template "redis.tlsCertKey" . }} \ + {{- end }} +{{- else }} + -p $REDIS_PORT \ +{{- end }} + ping + ) + if [ "$?" -eq "124" ]; then + echo "Timed out" + exit 1 + fi + responseFirstWord=$(echo $response | head -n1 | awk '{print $1;}') + if [ "$response" != "PONG" ] && [ "$responseFirstWord" != "LOADING" ] && [ "$responseFirstWord" != "MASTERDOWN" ]; then + echo "$response" + exit 1 + fi +{{- if .Values.sentinel.enabled }} + ping_sentinel.sh: |- + #!/bin/bash + +{{- if .Values.auth.sentinel }} + [[ -f $REDIS_PASSWORD_FILE ]] && export REDIS_PASSWORD="$(< "${REDIS_PASSWORD_FILE}")" + [[ -n "$REDIS_PASSWORD" ]] && export REDISCLI_AUTH="$REDIS_PASSWORD" +{{- end }} + response=$( + timeout -s 15 $1 \ + redis-cli \ + -h localhost \ +{{- if .Values.tls.enabled }} + -p $REDIS_SENTINEL_TLS_PORT_NUMBER \ + --tls \ + --cacert "$REDIS_SENTINEL_TLS_CA_FILE" \ + {{- if .Values.tls.authClients }} + --cert "$REDIS_SENTINEL_TLS_CERT_FILE" \ + --key "$REDIS_SENTINEL_TLS_KEY_FILE" \ + {{- end }} +{{- else }} + -p $REDIS_SENTINEL_PORT \ +{{- end }} + ping + ) + if [ "$?" -eq "124" ]; then + echo "Timed out" + exit 1 + fi + if [ "$response" != "PONG" ]; then + echo "$response" + exit 1 + fi + parse_sentinels.awk: |- + /ip/ {FOUND_IP=1} + /port/ {FOUND_PORT=1} + /runid/ {FOUND_RUNID=1} + !/ip|port|runid/ { + if (FOUND_IP==1) { + IP=$1; FOUND_IP=0; + } + else if (FOUND_PORT==1) { + PORT=$1; + FOUND_PORT=0; + } else if (FOUND_RUNID==1) { + printf "\nsentinel known-sentinel {{ .Values.sentinel.masterSet }} %s %s %s", IP, PORT, $0; FOUND_RUNID=0; + } + } +{{- end }} + ping_readiness_master.sh: |- + #!/bin/bash + + [[ -f $REDIS_MASTER_PASSWORD_FILE ]] && export REDIS_MASTER_PASSWORD="$(< "${REDIS_MASTER_PASSWORD_FILE}")" + [[ -n "$REDIS_MASTER_PASSWORD" ]] && export REDISCLI_AUTH="$REDIS_MASTER_PASSWORD" + response=$( + timeout -s 15 $1 \ + redis-cli \ + -h $REDIS_MASTER_HOST \ + -p $REDIS_MASTER_PORT_NUMBER \ +{{- if .Values.tls.enabled }} + --tls \ + --cacert {{ template "redis.tlsCACert" . }} \ + {{- if .Values.tls.authClients }} + --cert {{ template "redis.tlsCert" . }} \ + --key {{ template "redis.tlsCertKey" . }} \ + {{- end }} +{{- end }} + ping + ) + if [ "$?" -eq "124" ]; then + echo "Timed out" + exit 1 + fi + if [ "$response" != "PONG" ]; then + echo "$response" + exit 1 + fi + ping_liveness_master.sh: |- + #!/bin/bash + + [[ -f $REDIS_MASTER_PASSWORD_FILE ]] && export REDIS_MASTER_PASSWORD="$(< "${REDIS_MASTER_PASSWORD_FILE}")" + [[ -n "$REDIS_MASTER_PASSWORD" ]] && export REDISCLI_AUTH="$REDIS_MASTER_PASSWORD" + response=$( + timeout -s 15 $1 \ + redis-cli \ + -h $REDIS_MASTER_HOST \ + -p $REDIS_MASTER_PORT_NUMBER \ +{{- if .Values.tls.enabled }} + --tls \ + --cacert {{ template "redis.tlsCACert" . }} \ + {{- if .Values.tls.authClients }} + --cert {{ template "redis.tlsCert" . }} \ + --key {{ template "redis.tlsCertKey" . }} \ + {{- end }} +{{- end }} + ping + ) + if [ "$?" -eq "124" ]; then + echo "Timed out" + exit 1 + fi + responseFirstWord=$(echo $response | head -n1 | awk '{print $1;}') + if [ "$response" != "PONG" ] && [ "$responseFirstWord" != "LOADING" ]; then + echo "$response" + exit 1 + fi + ping_readiness_local_and_master.sh: |- + script_dir="$(dirname "$0")" + exit_status=0 + "$script_dir/ping_readiness_local.sh" $1 || exit_status=$? + "$script_dir/ping_readiness_master.sh" $1 || exit_status=$? + exit $exit_status + ping_liveness_local_and_master.sh: |- + script_dir="$(dirname "$0")" + exit_status=0 + "$script_dir/ping_liveness_local.sh" $1 || exit_status=$? + "$script_dir/ping_liveness_master.sh" $1 || exit_status=$? + exit $exit_status diff --git a/backing-services/redis/templates/master/application.yaml b/backing-services/redis/templates/master/application.yaml new file mode 100644 index 0000000..2da5bd5 --- /dev/null +++ b/backing-services/redis/templates/master/application.yaml @@ -0,0 +1,532 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if gt (int64 .Values.master.count) 0 -}} +{{- if or (not (eq .Values.architecture "replication")) (not .Values.sentinel.enabled) }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: {{ .Values.master.kind }} +metadata: + name: {{ printf "%s-master" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: master + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if not (eq .Values.master.kind "DaemonSet") }} + replicas: {{ .Values.master.count }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.master.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: master + {{- if (eq .Values.master.kind "StatefulSet") }} + serviceName: {{ printf "%s-headless" (include "common.names.fullname" .) }} + {{- end }} + {{- if .Values.master.updateStrategy }} + {{- if (eq .Values.master.kind "Deployment") }} + strategy: {{- toYaml .Values.master.updateStrategy | nindent 4 }} + {{- else }} + updateStrategy: {{- toYaml .Values.master.updateStrategy | nindent 4 }} + {{- end }} + {{- if and .Values.master.minReadySeconds (semverCompare ">= 1.23-0" (include "common.capabilities.kubeVersion" .)) }} + minReadySeconds: {{ .Values.master.minReadySeconds }} + {{- end }} + {{- end }} + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: master + {{- if and .Values.metrics.enabled .Values.metrics.podLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.podLabels "context" $ ) | nindent 8 }} + {{- end }} + annotations: + {{- if (include "redis.createConfigmap" .) }} + checksum/configmap: {{ pick ( include (print $.Template.BasePath "/configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + {{- end }} + checksum/health: {{ pick ( include (print $.Template.BasePath "/health-configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + checksum/scripts: {{ pick ( include (print $.Template.BasePath "/scripts-configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + checksum/secret: {{ pick ( include (print $.Template.BasePath "/secret.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + {{- if .Values.master.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.master.podAnnotations "context" $ ) | nindent 8 }} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.podAnnotations "context" $ ) | nindent 8 }} + {{- end }} + spec: + {{- include "redis.imagePullSecrets" . | nindent 6 }} + {{- if .Values.master.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.master.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.master.podSecurityContext.enabled }} + securityContext: {{- omit .Values.master.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + serviceAccountName: {{ template "redis.masterServiceAccountName" . }} + automountServiceAccountToken: {{ .Values.master.serviceAccount.automountServiceAccountToken }} + {{- if .Values.master.priorityClassName }} + priorityClassName: {{ .Values.master.priorityClassName | quote }} + {{- end }} + {{- if .Values.master.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.master.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.master.podAffinityPreset "component" "master" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.master.podAntiAffinityPreset "component" "master" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.master.nodeAffinityPreset.type "key" .Values.master.nodeAffinityPreset.key "values" .Values.master.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.master.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.master.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.master.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.master.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.master.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.master.topologySpreadConstraints "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.master.shareProcessNamespace }} + shareProcessNamespace: {{ .Values.master.shareProcessNamespace }} + {{- end }} + {{- if .Values.master.schedulerName }} + schedulerName: {{ .Values.master.schedulerName | quote }} + {{- end }} + {{- if .Values.master.dnsPolicy }} + dnsPolicy: {{ .Values.master.dnsPolicy }} + {{- end }} + {{- if .Values.master.dnsConfig }} + dnsConfig: {{- include "common.tplvalues.render" (dict "value" .Values.master.dnsConfig "context" $) | nindent 8 }} + {{- end }} + enableServiceLinks: {{ .Values.master.enableServiceLinks }} + terminationGracePeriodSeconds: {{ .Values.master.terminationGracePeriodSeconds }} + containers: + - name: redis + image: {{ template "redis.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.master.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.master.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.master.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.master.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.master.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.master.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.master.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.master.args "context" $) | nindent 12 }} + {{- else }} + args: + - -c + - /opt/bitnami/scripts/start-scripts/start-master.sh + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + - name: REDIS_REPLICATION_MODE + value: master + - name: ALLOW_EMPTY_PASSWORD + value: {{ ternary "no" "yes" .Values.auth.enabled | quote }} + {{- if .Values.auth.enabled }} + {{- if .Values.auth.usePasswordFiles }} + - name: REDIS_PASSWORD_FILE + value: "/opt/bitnami/redis/secrets/redis-password" + {{- else }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "redis.secretName" . }} + key: {{ template "redis.secretPasswordKey" . }} + {{- end }} + {{- end }} + - name: REDIS_TLS_ENABLED + value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} + {{- if .Values.tls.enabled }} + - name: REDIS_TLS_PORT + value: {{ .Values.master.containerPorts.redis | quote }} + - name: REDIS_TLS_AUTH_CLIENTS + value: {{ ternary "yes" "no" .Values.tls.authClients | quote }} + - name: REDIS_TLS_CERT_FILE + value: {{ template "redis.tlsCert" . }} + - name: REDIS_TLS_KEY_FILE + value: {{ template "redis.tlsCertKey" . }} + - name: REDIS_TLS_CA_FILE + value: {{ template "redis.tlsCACert" . }} + {{- if .Values.tls.dhParamsFilename }} + - name: REDIS_TLS_DH_PARAMS_FILE + value: {{ template "redis.tlsDHParams" . }} + {{- end }} + {{- else }} + - name: REDIS_PORT + value: {{ .Values.master.containerPorts.redis | quote }} + {{- end }} + {{- if .Values.master.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.master.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.master.extraEnvVarsCM .Values.master.extraEnvVarsSecret }} + envFrom: + {{- if .Values.master.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.master.extraEnvVarsCM }} + {{- end }} + {{- if .Values.master.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.master.extraEnvVarsSecret }} + {{- end }} + {{- end }} + ports: + - name: redis + containerPort: {{ .Values.master.containerPorts.redis }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.master.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.master.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.master.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.master.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: redis + {{- end }} + {{- if .Values.master.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.master.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.master.livenessProbe.enabled }} + livenessProbe: + initialDelaySeconds: {{ .Values.master.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.master.livenessProbe.periodSeconds }} + # One second longer than command timeout should prevent generation of zombie processes. + timeoutSeconds: {{ add1 .Values.master.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.master.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.master.livenessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_liveness_local.sh {{ .Values.master.livenessProbe.timeoutSeconds }} + {{- end }} + {{- if .Values.master.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.master.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.master.readinessProbe.enabled }} + readinessProbe: + initialDelaySeconds: {{ .Values.master.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.master.readinessProbe.periodSeconds }} + timeoutSeconds: {{ add1 .Values.master.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.master.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.master.readinessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_readiness_local.sh {{ .Values.master.readinessProbe.timeoutSeconds }} + {{- end }} + {{- end }} + {{- if .Values.master.resources }} + resources: {{- toYaml .Values.master.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: start-scripts + mountPath: /opt/bitnami/scripts/start-scripts + - name: health + mountPath: /health + {{- if .Values.auth.usePasswordFiles }} + - name: redis-password + mountPath: /opt/bitnami/redis/secrets/ + {{- end }} + - name: redis-data + mountPath: {{ .Values.master.persistence.path }} + {{- if .Values.master.persistence.subPath }} + subPath: {{ .Values.master.persistence.subPath }} + {{- else if .Values.master.persistence.subPathExpr }} + subPathExpr: {{ .Values.master.persistence.subPathExpr }} + {{- end }} + - name: config + mountPath: /opt/bitnami/redis/mounted-etc + - name: redis-tmp-conf + mountPath: /opt/bitnami/redis/etc/ + - name: tmp + mountPath: /tmp + {{- if .Values.tls.enabled }} + - name: redis-certificates + mountPath: /opt/bitnami/redis/certs + readOnly: true + {{- end }} + {{- if .Values.master.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.master.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ include "redis.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.metrics.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.metrics.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.metrics.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -c + - | + if [[ -f '/secrets/redis-password' ]]; then + export REDIS_PASSWORD=$(cat /secrets/redis-password) + fi + redis_exporter{{- range $key, $value := .Values.metrics.extraArgs }} --{{ $key }}={{ $value }}{{- end }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- end }} + env: + - name: REDIS_ALIAS + value: {{ template "common.names.fullname" . }} + {{- if .Values.auth.enabled }} + - name: REDIS_USER + value: default + {{- if (not .Values.auth.usePasswordFiles) }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "redis.secretName" . }} + key: {{ template "redis.secretPasswordKey" . }} + {{- end }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: REDIS_ADDR + value: rediss://{{ .Values.metrics.redisTargetHost }}:{{ .Values.master.containerPorts.redis }} + {{- if .Values.tls.authClients }} + - name: REDIS_EXPORTER_TLS_CLIENT_KEY_FILE + value: {{ template "redis.tlsCertKey" . }} + - name: REDIS_EXPORTER_TLS_CLIENT_CERT_FILE + value: {{ template "redis.tlsCert" . }} + {{- end }} + - name: REDIS_EXPORTER_TLS_CA_CERT_FILE + value: {{ template "redis.tlsCACert" . }} + {{- end }} + {{- if .Values.metrics.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + ports: + - name: metrics + containerPort: 9121 + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- end }} + volumeMounts: + {{- if .Values.auth.usePasswordFiles }} + - name: redis-password + mountPath: /secrets/ + {{- end }} + {{- if .Values.tls.enabled }} + - name: redis-certificates + mountPath: /opt/bitnami/redis/certs + readOnly: true + {{- end }} + {{- if .Values.metrics.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.master.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.master.sidecars "context" $) | nindent 8 }} + {{- end }} + {{- $needsVolumePermissions := and .Values.volumePermissions.enabled .Values.master.persistence.enabled .Values.master.podSecurityContext.enabled .Values.master.containerSecurityContext.enabled }} + {{- if or .Values.master.initContainers $needsVolumePermissions .Values.sysctl.enabled }} + initContainers: + {{- if .Values.master.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.master.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if $needsVolumePermissions }} + - name: volume-permissions + image: {{ include "redis.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + - -ec + - | + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + chown -R `id -u`:`id -G | cut -d " " -f2` {{ .Values.master.persistence.path }} + {{- else }} + chown -R {{ .Values.master.containerSecurityContext.runAsUser }}:{{ .Values.master.podSecurityContext.fsGroup }} {{ .Values.master.persistence.path }} + {{- end }} + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.containerSecurityContext "runAsUser" | toYaml | nindent 12 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.containerSecurityContext | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: redis-data + mountPath: {{ .Values.master.persistence.path }} + {{- if .Values.master.persistence.subPath }} + subPath: {{ .Values.master.persistence.subPath }} + {{- else if .Values.master.persistence.subPathExpr }} + subPathExpr: {{ .Values.master.persistence.subPathExpr }} + {{- end }} + {{- end }} + {{- if .Values.sysctl.enabled }} + - name: init-sysctl + image: {{ include "redis.sysctl.image" . }} + imagePullPolicy: {{ default "" .Values.sysctl.image.pullPolicy | quote }} + securityContext: + privileged: true + runAsUser: 0 + {{- if .Values.sysctl.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.sysctl.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.sysctl.resources }} + resources: {{- toYaml .Values.sysctl.resources | nindent 12 }} + {{- end }} + {{- if .Values.sysctl.mountHostSys }} + volumeMounts: + - name: host-sys + mountPath: /host-sys + {{- end }} + {{- end }} + {{- end }} + volumes: + - name: start-scripts + configMap: + name: {{ printf "%s-scripts" (include "common.names.fullname" .) }} + defaultMode: 0755 + - name: health + configMap: + name: {{ printf "%s-health" (include "common.names.fullname" .) }} + defaultMode: 0755 + {{- if .Values.auth.usePasswordFiles }} + - name: redis-password + secret: + secretName: {{ template "redis.secretName" . }} + items: + - key: {{ template "redis.secretPasswordKey" . }} + path: redis-password + {{- end }} + - name: config + configMap: + name: {{ include "redis.configmapName" . }} + {{- if .Values.sysctl.mountHostSys }} + - name: host-sys + hostPath: + path: /sys + {{- end }} + - name: redis-tmp-conf + {{- if or .Values.master.persistence.medium .Values.master.persistence.sizeLimit }} + emptyDir: + {{- if .Values.master.persistence.medium }} + medium: {{ .Values.master.persistence.medium | quote }} + {{- end }} + {{- if .Values.master.persistence.sizeLimit }} + sizeLimit: {{ .Values.master.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + - name: tmp + {{- if or .Values.master.persistence.medium .Values.master.persistence.sizeLimit }} + emptyDir: + {{- if .Values.master.persistence.medium }} + medium: {{ .Values.master.persistence.medium | quote }} + {{- end }} + {{- if .Values.master.persistence.sizeLimit }} + sizeLimit: {{ .Values.master.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- if .Values.tls.enabled }} + - name: redis-certificates + secret: + secretName: {{ include "redis.tlsSecretName" . }} + defaultMode: 256 + {{- end }} + {{- if .Values.master.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.master.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if .Values.metrics.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if or (not .Values.master.persistence.enabled) (eq .Values.master.kind "DaemonSet") }} + - name: redis-data + {{- if or .Values.master.persistence.medium .Values.master.persistence.sizeLimit }} + emptyDir: + {{- if .Values.master.persistence.medium }} + medium: {{ .Values.master.persistence.medium | quote }} + {{- end }} + {{- if .Values.master.persistence.sizeLimit }} + sizeLimit: {{ .Values.master.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- else if .Values.master.persistence.existingClaim }} + - name: redis-data + persistentVolumeClaim: + claimName: {{ printf "%s" (tpl .Values.master.persistence.existingClaim .) }} + {{- else if (eq .Values.master.kind "Deployment") }} + - name: redis-data + persistentVolumeClaim: + claimName: {{ printf "redis-data-%s-master" (include "common.names.fullname" .) }} + {{- else }} + {{- if .Values.master.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.master.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.master.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: redis-data + {{- $claimLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.master.persistence.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.matchLabels" ( dict "customLabels" $claimLabels "context" $ ) | nindent 10 }} + app.kubernetes.io/component: master + {{- if .Values.master.persistence.annotations }} + annotations: {{- toYaml .Values.master.persistence.annotations | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.master.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.master.persistence.size | quote }} + {{- if .Values.master.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.master.persistence.selector "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.master.persistence.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.master.persistence.dataSource "context" $) | nindent 10 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" .Values.master.persistence "global" .Values.global) | nindent 8 }} + {{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/redis/templates/master/psp.yaml b/backing-services/redis/templates/master/psp.yaml new file mode 100644 index 0000000..5a47afb --- /dev/null +++ b/backing-services/redis/templates/master/psp.yaml @@ -0,0 +1,47 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (include "common.capabilities.psp.supported" .) .Values.podSecurityPolicy.create }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ printf "%s-master" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + allowPrivilegeEscalation: false + fsGroup: + rule: 'MustRunAs' + ranges: + - min: {{ .Values.master.podSecurityContext.fsGroup }} + max: {{ .Values.master.podSecurityContext.fsGroup }} + hostIPC: false + hostNetwork: false + hostPID: false + privileged: false + readOnlyRootFilesystem: false + requiredDropCapabilities: + - ALL + runAsUser: + rule: 'MustRunAs' + ranges: + - min: {{ .Values.master.containerSecurityContext.runAsUser }} + max: {{ .Values.master.containerSecurityContext.runAsUser }} + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + - min: {{ .Values.master.containerSecurityContext.runAsUser }} + max: {{ .Values.master.containerSecurityContext.runAsUser }} + volumes: + - 'configMap' + - 'secret' + - 'emptyDir' + - 'persistentVolumeClaim' +{{- end }} diff --git a/backing-services/redis/templates/master/pvc.yaml b/backing-services/redis/templates/master/pvc.yaml new file mode 100644 index 0000000..019f60d --- /dev/null +++ b/backing-services/redis/templates/master/pvc.yaml @@ -0,0 +1,33 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "standalone") (eq .Values.master.kind "Deployment") (.Values.master.persistence.enabled) (not .Values.master.persistence.existingClaim) }} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ printf "redis-data-%s-master" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.master.persistence.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: master + {{- if .Values.master.persistence.annotations }} + annotations: {{- toYaml .Values.master.persistence.annotations | nindent 4 }} + {{- end }} +spec: + accessModes: + {{- range .Values.master.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.master.persistence.size | quote }} + {{- if .Values.master.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.master.persistence.selector "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.master.persistence.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.master.persistence.dataSource "context" $) | nindent 4 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" .Values.master.persistence "global" .Values.global) | nindent 2 }} +{{- end }} diff --git a/backing-services/redis/templates/master/service.yaml b/backing-services/redis/templates/master/service.yaml new file mode 100644 index 0000000..ba744db --- /dev/null +++ b/backing-services/redis/templates/master/service.yaml @@ -0,0 +1,62 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (not .Values.sentinel.enabled) (gt (int64 .Values.master.count) 0) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-master" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: master + {{- if or .Values.master.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.master.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.master.service.type }} + {{- if or (eq .Values.master.service.type "LoadBalancer") (eq .Values.master.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.master.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if (semverCompare ">=1.22-0" (include "common.capabilities.kubeVersion" .)) }} + internalTrafficPolicy: {{ .Values.master.service.internalTrafficPolicy }} + {{- end }} + {{- if and (eq .Values.master.service.type "LoadBalancer") (not (empty .Values.master.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.master.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.master.service.type "LoadBalancer") .Values.master.service.loadBalancerClass }} + loadBalancerClass: {{ .Values.master.service.loadBalancerClass }} + {{- end }} + {{- if and (eq .Values.master.service.type "LoadBalancer") (not (empty .Values.master.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ toYaml .Values.master.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + {{- if and .Values.master.service.clusterIP (eq .Values.master.service.type "ClusterIP") }} + clusterIP: {{ .Values.master.service.clusterIP }} + {{- end }} + {{- if .Values.master.service.sessionAffinity }} + sessionAffinity: {{ .Values.master.service.sessionAffinity }} + {{- end }} + {{- if .Values.master.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.master.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.master.service.externalIPs }} + externalIPs: {{- include "common.tplvalues.render" (dict "value" .Values.master.service.externalIPs "context" $) | nindent 4 }} + {{- end }} + ports: + - name: tcp-redis + port: {{ .Values.master.service.ports.redis }} + targetPort: redis + {{- if and (or (eq .Values.master.service.type "NodePort") (eq .Values.master.service.type "LoadBalancer")) .Values.master.service.nodePorts.redis}} + nodePort: {{ .Values.master.service.nodePorts.redis}} + {{- else if eq .Values.master.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.master.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.master.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.master.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: master +{{- end }} diff --git a/backing-services/redis/templates/master/serviceaccount.yaml b/backing-services/redis/templates/master/serviceaccount.yaml new file mode 100644 index 0000000..4ba3052 --- /dev/null +++ b/backing-services/redis/templates/master/serviceaccount.yaml @@ -0,0 +1,18 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.master.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +automountServiceAccountToken: {{ .Values.master.serviceAccount.automountServiceAccountToken }} +metadata: + name: {{ template "redis.masterServiceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.master.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.master.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/redis/templates/metrics-svc.yaml b/backing-services/redis/templates/metrics-svc.yaml new file mode 100644 index 0000000..5e24b6d --- /dev/null +++ b/backing-services/redis/templates/metrics-svc.yaml @@ -0,0 +1,44 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.metrics.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-metrics" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: metrics + {{- if or .Values.metrics.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.metrics.service.type }} + {{- if and .Values.metrics.service.clusterIP (eq .Values.metrics.service.type "ClusterIP") }} + clusterIP: {{ .Values.metrics.service.clusterIP }} + {{- end }} + {{- if eq .Values.metrics.service.type "LoadBalancer" }} + externalTrafficPolicy: {{ .Values.metrics.service.externalTrafficPolicy }} + {{- end }} + {{- if and (eq .Values.metrics.service.type "LoadBalancer") .Values.metrics.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.metrics.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.metrics.service.type "LoadBalancer") .Values.metrics.service.loadBalancerClass }} + loadBalancerClass: {{ .Values.metrics.service.loadBalancerClass }} + {{- end }} + {{- if and (eq .Values.metrics.service.type "LoadBalancer") .Values.metrics.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{- toYaml .Values.metrics.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + ports: + - name: http-metrics + port: {{ .Values.metrics.service.port }} + protocol: TCP + targetPort: metrics + {{- if .Values.metrics.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} +{{- end }} diff --git a/backing-services/redis/templates/networkpolicy.yaml b/backing-services/redis/templates/networkpolicy.yaml new file mode 100644 index 0000000..84f5ada --- /dev/null +++ b/backing-services/redis/templates/networkpolicy.yaml @@ -0,0 +1,105 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ template "networkPolicy.apiVersion" . }} +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + policyTypes: + - Ingress + {{- if or (eq .Values.architecture "replication") .Values.networkPolicy.extraEgress }} + - Egress + egress: + {{- if eq .Values.architecture "replication" }} + # Allow dns resolution + - ports: + - port: 53 + protocol: UDP + # Allow outbound connections to other cluster pods + - ports: + - port: {{ .Values.master.containerPorts.redis }} + {{- if .Values.sentinel.enabled }} + - port: {{ .Values.sentinel.containerPorts.sentinel }} + {{- end }} + to: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }} + {{- end }} + {{- if .Values.networkPolicy.extraEgress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.networkPolicy.extraEgress "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} + ingress: + # Allow inbound connections + - ports: + - port: {{ .Values.master.containerPorts.redis }} + {{- if .Values.sentinel.enabled }} + - port: {{ .Values.sentinel.containerPorts.sentinel }} + {{- end }} + {{- if not .Values.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: + {{ template "common.names.fullname" . }}-client: "true" + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }} + {{- if or .Values.networkPolicy.ingressNSMatchLabels .Values.networkPolicy.ingressNSPodMatchLabels }} + - namespaceSelector: + matchLabels: + {{- if .Values.networkPolicy.ingressNSMatchLabels }} + {{- range $key, $value := .Values.networkPolicy.ingressNSMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{ else }} + {} + {{- end }} + {{- if .Values.networkPolicy.ingressNSPodMatchLabels }} + podSelector: + matchLabels: + {{- range $key, $value := .Values.networkPolicy.ingressNSPodMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.metrics.enabled }} + # Allow prometheus scrapes for metrics + - ports: + - port: 9121 + {{- if not .Values.networkPolicy.metrics.allowExternal }} + from: + {{- if or .Values.networkPolicy.metrics.ingressNSMatchLabels .Values.networkPolicy.metrics.ingressNSPodMatchLabels }} + - namespaceSelector: + matchLabels: + {{- if .Values.networkPolicy.metrics.ingressNSMatchLabels }} + {{- range $key, $value := .Values.networkPolicy.metrics.ingressNSMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{ else }} + {} + {{- end }} + {{- if .Values.networkPolicy.metrics.ingressNSPodMatchLabels }} + podSelector: + matchLabels: + {{- range $key, $value := .Values.networkPolicy.metrics.ingressNSPodMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.networkPolicy.extraIngress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.networkPolicy.extraIngress "context" $ ) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/redis/templates/pdb.yaml b/backing-services/redis/templates/pdb.yaml new file mode 100644 index 0000000..d2ca15d --- /dev/null +++ b/backing-services/redis/templates/pdb.yaml @@ -0,0 +1,25 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.pdb.minAvailable }} + minAvailable: {{ .Values.pdb.minAvailable }} + {{- end }} + {{- if .Values.pdb.maxUnavailable }} + maxUnavailable: {{ .Values.pdb.maxUnavailable }} + {{- end }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} +{{- end }} diff --git a/backing-services/redis/templates/podmonitor.yaml b/backing-services/redis/templates/podmonitor.yaml new file mode 100644 index 0000000..55bcd51 --- /dev/null +++ b/backing-services/redis/templates/podmonitor.yaml @@ -0,0 +1,52 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.podMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ default (include "common.names.namespace" .) .Values.metrics.podMonitor.namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.metrics.podMonitor.additionalLabels }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.podMonitor.additionalLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + podMetricsEndpoints: + - port: http-metrics + {{- if .Values.metrics.podMonitor.interval }} + interval: {{ .Values.metrics.podMonitor.interval }} + {{- end }} + {{- if .Values.metrics.podMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.metrics.podMonitor.scrapeTimeout }} + {{- end }} + {{- if .Values.metrics.podMonitor.honorLabels }} + honorLabels: {{ .Values.metrics.podMonitor.honorLabels }} + {{- end }} + {{- if .Values.metrics.podMonitor.relabellings }} + relabelings: {{- toYaml .Values.metrics.podMonitor.relabellings | nindent 6 }} + {{- end }} + {{- if .Values.metrics.podMonitor.metricRelabelings }} + metricRelabelings: {{- toYaml .Values.metrics.podMonitor.metricRelabelings | nindent 6 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.podTargetLabels }} + podTargetLabels: {{- toYaml .Values.metrics.podMonitor.podTargetLabels | nindent 4 }} + {{- end }} + {{- with .Values.metrics.podMonitor.sampleLimit -}} + sampleLimit: {{ . }} + {{- end }} + {{- with .Values.metrics.podMonitor.targetLimit -}} + targetLimit: {{ . }} + {{- end }} + namespaceSelector: + matchNames: + - {{ include "common.names.namespace" . | quote }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: metrics +{{- end }} diff --git a/backing-services/redis/templates/prometheusrule.yaml b/backing-services/redis/templates/prometheusrule.yaml new file mode 100644 index 0000000..3406918 --- /dev/null +++ b/backing-services/redis/templates/prometheusrule.yaml @@ -0,0 +1,23 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ default (include "common.names.namespace" .) .Values.metrics.prometheusRule.namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.metrics.prometheusRule.additionalLabels }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.prometheusRule.additionalLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + groups: + - name: {{ include "common.names.fullname" . }} + rules: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.prometheusRule.rules "context" $ ) | nindent 8 }} +{{- end }} diff --git a/backing-services/redis/templates/replicas/application.yaml b/backing-services/redis/templates/replicas/application.yaml new file mode 100644 index 0000000..67d83c8 --- /dev/null +++ b/backing-services/redis/templates/replicas/application.yaml @@ -0,0 +1,533 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replication") (not .Values.sentinel.enabled) }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: {{ .Values.replica.kind }} +metadata: + name: {{ printf "%s-replicas" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: replica + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if and (not (eq .Values.replica.kind "DaemonSet")) (not .Values.replica.autoscaling.enabled) }} + replicas: {{ .Values.replica.replicaCount }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.replica.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: replica + {{- if (eq .Values.replica.kind "StatefulSet") }} + serviceName: {{ printf "%s-headless" (include "common.names.fullname" .) }} + {{- end }} + {{- if .Values.replica.updateStrategy }} + updateStrategy: {{- toYaml .Values.replica.updateStrategy | nindent 4 }} + {{- end }} + {{- if and .Values.replica.minReadySeconds (semverCompare ">= 1.23-0" (include "common.capabilities.kubeVersion" .)) }} + minReadySeconds: {{ .Values.replica.minReadySeconds }} + {{- end }} + {{- if .Values.replica.podManagementPolicy }} + podManagementPolicy: {{ .Values.replica.podManagementPolicy | quote }} + {{- end }} + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: replica + {{- if and .Values.metrics.enabled .Values.metrics.podLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.podLabels "context" $ ) | nindent 8 }} + {{- end }} + annotations: + {{- if (include "redis.createConfigmap" .) }} + checksum/configmap: {{ pick ( include (print $.Template.BasePath "/configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + {{- end }} + checksum/health: {{ pick ( include (print $.Template.BasePath "/health-configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + checksum/scripts: {{ pick ( include (print $.Template.BasePath "/scripts-configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + checksum/secret: {{ pick ( include (print $.Template.BasePath "/secret.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + {{- if .Values.replica.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.podAnnotations "context" $ ) | nindent 8 }} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.podAnnotations "context" $ ) | nindent 8 }} + {{- end }} + spec: + {{- include "redis.imagePullSecrets" . | nindent 6 }} + {{- if .Values.replica.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.replica.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.podSecurityContext.enabled }} + securityContext: {{- omit .Values.replica.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + serviceAccountName: {{ template "redis.replicaServiceAccountName" . }} + automountServiceAccountToken: {{ .Values.replica.serviceAccount.automountServiceAccountToken }} + {{- if .Values.replica.priorityClassName }} + priorityClassName: {{ .Values.replica.priorityClassName | quote }} + {{- end }} + {{- if .Values.replica.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.replica.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.replica.podAffinityPreset "component" "replica" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.replica.podAntiAffinityPreset "component" "replica" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.replica.nodeAffinityPreset.type "key" .Values.replica.nodeAffinityPreset.key "values" .Values.replica.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.replica.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.replica.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.replica.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.replica.topologySpreadConstraints "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.shareProcessNamespace }} + shareProcessNamespace: {{ .Values.replica.shareProcessNamespace }} + {{- end }} + {{- if .Values.replica.schedulerName }} + schedulerName: {{ .Values.replica.schedulerName | quote }} + {{- end }} + {{- if .Values.replica.dnsPolicy }} + dnsPolicy: {{ .Values.replica.dnsPolicy }} + {{- end }} + {{- if .Values.replica.dnsConfig }} + dnsConfig: {{- include "common.tplvalues.render" (dict "value" .Values.replica.dnsConfig "context" $) | nindent 8 }} + {{- end }} + enableServiceLinks: {{ .Values.replica.enableServiceLinks }} + terminationGracePeriodSeconds: {{ .Values.replica.terminationGracePeriodSeconds }} + containers: + - name: redis + image: {{ template "redis.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.replica.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.replica.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.replica.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.replica.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.replica.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.replica.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.replica.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.replica.args "context" $) | nindent 12 }} + {{- else }} + args: + - -c + - /opt/bitnami/scripts/start-scripts/start-replica.sh + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + - name: REDIS_REPLICATION_MODE + value: replica + - name: REDIS_MASTER_HOST + {{- if .Values.replica.externalMaster.enabled }} + value: {{ .Values.replica.externalMaster.host | quote }} + {{- else if and (eq (int64 .Values.master.count) 1) (eq .Values.master.kind "StatefulSet") }} + value: {{ template "common.names.fullname" . }}-master-0.{{ template "common.names.fullname" . }}-headless.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }} + {{- else }} + value: {{ template "common.names.fullname" . }}-master.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }} + {{- end }} + - name: REDIS_MASTER_PORT_NUMBER + {{- if .Values.replica.externalMaster.enabled }} + value: {{ .Values.replica.externalMaster.port | quote }} + {{- else }} + value: {{ .Values.master.containerPorts.redis | quote }} + {{- end }} + - name: ALLOW_EMPTY_PASSWORD + value: {{ ternary "no" "yes" .Values.auth.enabled | quote }} + {{- if .Values.auth.enabled }} + {{- if .Values.auth.usePasswordFiles }} + - name: REDIS_PASSWORD_FILE + value: "/opt/bitnami/redis/secrets/redis-password" + - name: REDIS_MASTER_PASSWORD_FILE + value: "/opt/bitnami/redis/secrets/redis-password" + {{- else }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "redis.secretName" . }} + key: {{ template "redis.secretPasswordKey" . }} + - name: REDIS_MASTER_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "redis.secretName" . }} + key: {{ template "redis.secretPasswordKey" . }} + {{- end }} + {{- end }} + - name: REDIS_TLS_ENABLED + value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} + {{- if .Values.tls.enabled }} + - name: REDIS_TLS_PORT + value: {{ .Values.replica.containerPorts.redis | quote }} + - name: REDIS_TLS_AUTH_CLIENTS + value: {{ ternary "yes" "no" .Values.tls.authClients | quote }} + - name: REDIS_TLS_CERT_FILE + value: {{ template "redis.tlsCert" . }} + - name: REDIS_TLS_KEY_FILE + value: {{ template "redis.tlsCertKey" . }} + - name: REDIS_TLS_CA_FILE + value: {{ template "redis.tlsCACert" . }} + {{- if .Values.tls.dhParamsFilename }} + - name: REDIS_TLS_DH_PARAMS_FILE + value: {{ template "redis.tlsDHParams" . }} + {{- end }} + {{- else }} + - name: REDIS_PORT + value: {{ .Values.replica.containerPorts.redis | quote }} + {{- end }} + {{- if .Values.replica.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.replica.extraEnvVarsCM .Values.replica.extraEnvVarsSecret }} + envFrom: + {{- if .Values.replica.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.replica.extraEnvVarsCM }} + {{- end }} + {{- if .Values.replica.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.replica.extraEnvVarsSecret }} + {{- end }} + {{- end }} + ports: + - name: redis + containerPort: {{ .Values.replica.containerPorts.redis }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.replica.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.replica.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.replica.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.replica.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: redis + {{- end }} + {{- if .Values.replica.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.replica.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.replica.livenessProbe.enabled }} + livenessProbe: + initialDelaySeconds: {{ .Values.replica.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.replica.livenessProbe.periodSeconds }} + timeoutSeconds: {{ add1 .Values.replica.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.replica.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.replica.livenessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_liveness_local_and_master.sh {{ .Values.replica.livenessProbe.timeoutSeconds }} + {{- end }} + {{- if .Values.replica.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.replica.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.replica.readinessProbe.enabled }} + readinessProbe: + initialDelaySeconds: {{ .Values.replica.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.replica.readinessProbe.periodSeconds }} + timeoutSeconds: {{ add1 .Values.replica.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.replica.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.replica.readinessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_readiness_local_and_master.sh {{ .Values.replica.readinessProbe.timeoutSeconds }} + {{- end }} + {{- end }} + {{- if .Values.replica.resources }} + resources: {{- toYaml .Values.replica.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: start-scripts + mountPath: /opt/bitnami/scripts/start-scripts + - name: health + mountPath: /health + {{- if .Values.auth.usePasswordFiles }} + - name: redis-password + mountPath: /opt/bitnami/redis/secrets/ + {{- end }} + - name: redis-data + mountPath: /data + {{- if .Values.replica.persistence.subPath }} + subPath: {{ .Values.replica.persistence.subPath }} + {{- else if .Values.replica.persistence.subPathExpr }} + subPathExpr: {{ .Values.replica.persistence.subPathExpr }} + {{- end }} + - name: config + mountPath: /opt/bitnami/redis/mounted-etc + - name: redis-tmp-conf + mountPath: /opt/bitnami/redis/etc + {{- if .Values.tls.enabled }} + - name: redis-certificates + mountPath: /opt/bitnami/redis/certs + readOnly: true + {{- end }} + {{- if .Values.replica.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ include "redis.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.metrics.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.metrics.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.metrics.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -c + - | + if [[ -f '/secrets/redis-password' ]]; then + export REDIS_PASSWORD=$(cat /secrets/redis-password) + fi + redis_exporter{{- range $key, $value := .Values.metrics.extraArgs }} --{{ $key }}={{ $value }}{{- end }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- end }} + env: + - name: REDIS_ALIAS + value: {{ template "common.names.fullname" . }} + {{- if .Values.auth.enabled }} + - name: REDIS_USER + value: default + {{- if (not .Values.auth.usePasswordFiles) }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "redis.secretName" . }} + key: {{ template "redis.secretPasswordKey" . }} + {{- end }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: REDIS_ADDR + value: rediss://{{ .Values.metrics.redisTargetHost }}:{{ .Values.replica.containerPorts.redis }} + {{- if .Values.tls.authClients }} + - name: REDIS_EXPORTER_TLS_CLIENT_KEY_FILE + value: {{ template "redis.tlsCertKey" . }} + - name: REDIS_EXPORTER_TLS_CLIENT_CERT_FILE + value: {{ template "redis.tlsCert" . }} + {{- end }} + - name: REDIS_EXPORTER_TLS_CA_CERT_FILE + value: {{ template "redis.tlsCACert" . }} + {{- end }} + {{- if .Values.metrics.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + ports: + - name: metrics + containerPort: 9121 + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- end }} + volumeMounts: + {{- if .Values.auth.usePasswordFiles }} + - name: redis-password + mountPath: /secrets/ + {{- end }} + {{- if .Values.tls.enabled }} + - name: redis-certificates + mountPath: /opt/bitnami/redis/certs + readOnly: true + {{- end }} + {{- if .Values.metrics.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.replica.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.sidecars "context" $) | nindent 8 }} + {{- end }} + {{- $needsVolumePermissions := and .Values.volumePermissions.enabled .Values.replica.persistence.enabled .Values.replica.podSecurityContext.enabled .Values.replica.containerSecurityContext.enabled }} + {{- if or .Values.replica.initContainers $needsVolumePermissions .Values.sysctl.enabled }} + initContainers: + {{- if .Values.replica.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if $needsVolumePermissions }} + - name: volume-permissions + image: {{ include "redis.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + - -ec + - | + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + chown -R `id -u`:`id -G | cut -d " " -f2` {{ .Values.replica.persistence.path }} + {{- else }} + chown -R {{ .Values.replica.containerSecurityContext.runAsUser }}:{{ .Values.replica.podSecurityContext.fsGroup }} {{ .Values.replica.persistence.path }} + {{- end }} + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.containerSecurityContext "runAsUser" | toYaml | nindent 12 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.containerSecurityContext | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: redis-data + mountPath: {{ .Values.replica.persistence.path }} + {{- if .Values.replica.persistence.subPath }} + subPath: {{ .Values.replica.persistence.subPath }} + {{- else if .Values.replica.persistence.subPathExpr }} + subPathExpr: {{ .Values.replica.persistence.subPathExpr }} + {{- end }} + {{- end }} + {{- if .Values.sysctl.enabled }} + - name: init-sysctl + image: {{ include "redis.sysctl.image" . }} + imagePullPolicy: {{ default "" .Values.sysctl.image.pullPolicy | quote }} + securityContext: + privileged: true + runAsUser: 0 + {{- if .Values.sysctl.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.sysctl.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.sysctl.resources }} + resources: {{- toYaml .Values.sysctl.resources | nindent 12 }} + {{- end }} + {{- if .Values.sysctl.mountHostSys }} + volumeMounts: + - name: host-sys + mountPath: /host-sys + {{- end }} + {{- end }} + {{- end }} + volumes: + - name: start-scripts + configMap: + name: {{ printf "%s-scripts" (include "common.names.fullname" .) }} + defaultMode: 0755 + - name: health + configMap: + name: {{ printf "%s-health" (include "common.names.fullname" .) }} + defaultMode: 0755 + {{- if .Values.auth.usePasswordFiles }} + - name: redis-password + secret: + secretName: {{ template "redis.secretName" . }} + items: + - key: {{ template "redis.secretPasswordKey" . }} + path: redis-password + {{- end }} + - name: config + configMap: + name: {{ include "redis.configmapName" . }} + {{- if .Values.sysctl.mountHostSys }} + - name: host-sys + hostPath: + path: /sys + {{- end }} + - name: redis-tmp-conf + {{- if or .Values.replica.persistence.medium .Values.replica.persistence.sizeLimit }} + emptyDir: + {{- if .Values.replica.persistence.medium }} + medium: {{ .Values.replica.persistence.medium | quote }} + {{- end }} + {{- if .Values.replica.persistence.sizeLimit }} + sizeLimit: {{ .Values.replica.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- if .Values.tls.enabled }} + - name: redis-certificates + secret: + secretName: {{ include "redis.tlsSecretName" . }} + defaultMode: 256 + {{- end }} + {{- if .Values.replica.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if .Values.metrics.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if or (not .Values.replica.persistence.enabled) (not (eq .Values.replica.kind "StatefulSet")) }} + - name: redis-data + {{- if or .Values.replica.persistence.medium .Values.replica.persistence.sizeLimit }} + emptyDir: + {{- if .Values.replica.persistence.medium }} + medium: {{ .Values.replica.persistence.medium | quote }} + {{- end }} + {{- if .Values.replica.persistence.sizeLimit }} + sizeLimit: {{ .Values.replica.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- else if .Values.replica.persistence.existingClaim }} + - name: redis-data + persistentVolumeClaim: + claimName: {{ printf "%s" (tpl .Values.replica.persistence.existingClaim .) }} + {{- else }} + {{- if .Values.replica.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.replica.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.replica.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: redis-data + {{- $claimLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.master.persistence.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.matchLabels" ( dict "customLabels" $claimLabels "context" $ ) | nindent 10 }} + app.kubernetes.io/component: replica + {{- if .Values.replica.persistence.annotations }} + annotations: {{- toYaml .Values.replica.persistence.annotations | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.replica.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.replica.persistence.size | quote }} + {{- if .Values.replica.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.replica.persistence.selector "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.replica.persistence.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.replica.persistence.dataSource "context" $) | nindent 10 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" .Values.replica.persistence "global" .Values.global) | nindent 8 }} + {{- end }} +{{- end }} diff --git a/backing-services/redis/templates/replicas/hpa.yaml b/backing-services/redis/templates/replicas/hpa.yaml new file mode 100644 index 0000000..da69290 --- /dev/null +++ b/backing-services/redis/templates/replicas/hpa.yaml @@ -0,0 +1,49 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.replica.autoscaling.enabled (not .Values.sentinel.enabled) }} +apiVersion: {{ include "common.capabilities.hpa.apiVersion" ( dict "context" $ ) }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ printf "%s-replicas" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: replica + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + scaleTargetRef: + apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} + kind: StatefulSet + name: {{ printf "%s-replicas" (include "common.names.fullname" .) }} + minReplicas: {{ .Values.replica.autoscaling.minReplicas }} + maxReplicas: {{ .Values.replica.autoscaling.maxReplicas }} + metrics: + {{- if .Values.replica.autoscaling.targetCPU }} + - type: Resource + resource: + name: cpu + {{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .) }} + targetAverageUtilization: {{ .Values.replica.autoscaling.targetCPU }} + {{- else }} + target: + type: Utilization + averageUtilization: {{ .Values.replica.autoscaling.targetCPU }} + {{- end }} + {{- end }} + {{- if .Values.replica.autoscaling.targetMemory }} + - type: Resource + resource: + name: memory + {{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .) }} + targetAverageUtilization: {{ .Values.replica.autoscaling.targetMemory }} + {{- else }} + target: + type: Utilization + averageUtilization: {{ .Values.replica.autoscaling.targetMemory }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/redis/templates/replicas/service.yaml b/backing-services/redis/templates/replicas/service.yaml new file mode 100644 index 0000000..b54b85a --- /dev/null +++ b/backing-services/redis/templates/replicas/service.yaml @@ -0,0 +1,59 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replication") (not .Values.sentinel.enabled) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-replicas" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: replica + {{- if or .Values.replica.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.replica.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.replica.service.type }} + {{- if or (eq .Values.replica.service.type "LoadBalancer") (eq .Values.replica.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.replica.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if (semverCompare ">=1.22-0" (include "common.capabilities.kubeVersion" .)) }} + internalTrafficPolicy: {{ .Values.replica.service.internalTrafficPolicy }} + {{- end }} + {{- if and (eq .Values.replica.service.type "LoadBalancer") (not (empty .Values.replica.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.replica.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.replica.service.type "LoadBalancer") .Values.replica.service.loadBalancerClass }} + loadBalancerClass: {{ .Values.replica.service.loadBalancerClass }} + {{- end }} + {{- if and (eq .Values.replica.service.type "LoadBalancer") (not (empty .Values.replica.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ toYaml .Values.replica.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + {{- if and .Values.replica.service.clusterIP (eq .Values.replica.service.type "ClusterIP") }} + clusterIP: {{ .Values.replica.service.clusterIP }} + {{- end }} + {{- if .Values.replica.service.sessionAffinity }} + sessionAffinity: {{ .Values.replica.service.sessionAffinity }} + {{- end }} + {{- if .Values.replica.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.replica.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + ports: + - name: tcp-redis + port: {{ .Values.replica.service.ports.redis }} + targetPort: redis + {{- if and (or (eq .Values.replica.service.type "NodePort") (eq .Values.replica.service.type "LoadBalancer")) .Values.replica.service.nodePorts.redis}} + nodePort: {{ .Values.replica.service.nodePorts.redis}} + {{- else if eq .Values.replica.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.replica.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.replica.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: replica +{{- end }} diff --git a/backing-services/redis/templates/replicas/serviceaccount.yaml b/backing-services/redis/templates/replicas/serviceaccount.yaml new file mode 100644 index 0000000..ec5d666 --- /dev/null +++ b/backing-services/redis/templates/replicas/serviceaccount.yaml @@ -0,0 +1,18 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.replica.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +automountServiceAccountToken: {{ .Values.replica.serviceAccount.automountServiceAccountToken }} +metadata: + name: {{ template "redis.replicaServiceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.replica.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.replica.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/redis/templates/role.yaml b/backing-services/redis/templates/role.yaml new file mode 100644 index 0000000..5bab3b7 --- /dev/null +++ b/backing-services/redis/templates/role.yaml @@ -0,0 +1,29 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.rbac.create }} +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: Role +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: + {{- if and (include "common.capabilities.psp.supported" .) .Values.podSecurityPolicy.enabled }} + - apiGroups: + - '{{ template "podSecurityPolicy.apiGroup" . }}' + resources: + - 'podsecuritypolicies' + verbs: + - 'use' + resourceNames: [{{ printf "%s-master" (include "common.names.fullname" .) }}] + {{- end }} + {{- if .Values.rbac.rules }} + {{- include "common.tplvalues.render" ( dict "value" .Values.rbac.rules "context" $ ) | nindent 2 }} + {{- end }} +{{- end }} diff --git a/backing-services/redis/templates/rolebinding.yaml b/backing-services/redis/templates/rolebinding.yaml new file mode 100644 index 0000000..81c68f3 --- /dev/null +++ b/backing-services/redis/templates/rolebinding.yaml @@ -0,0 +1,23 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.rbac.create }} +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: RoleBinding +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "common.names.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "redis.serviceAccountName" . }} +{{- end }} diff --git a/backing-services/redis/templates/scripts-configmap.yaml b/backing-services/redis/templates/scripts-configmap.yaml new file mode 100644 index 0000000..f785faf --- /dev/null +++ b/backing-services/redis/templates/scripts-configmap.yaml @@ -0,0 +1,757 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-scripts" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: +{{- if and (eq .Values.architecture "replication") .Values.sentinel.enabled }} + start-node.sh: | + #!/bin/bash + + . /opt/bitnami/scripts/libos.sh + . /opt/bitnami/scripts/liblog.sh + . /opt/bitnami/scripts/libvalidations.sh + + get_port() { + hostname="$1" + type="$2" + + port_var=$(echo "${hostname^^}_SERVICE_PORT_$type" | sed "s/-/_/g") + port=${!port_var} + + if [ -z "$port" ]; then + case $type in + "SENTINEL") + echo {{ .Values.sentinel.containerPorts.sentinel }} + ;; + "REDIS") + echo {{ .Values.master.containerPorts.redis }} + ;; + esac + else + echo $port + fi + } + + get_full_hostname() { + hostname="$1" + + {{- if .Values.useExternalDNS.enabled }} + full_hostname="${hostname}.{{- include "redis.externalDNS.suffix" . }}" + {{- else if eq .Values.sentinel.service.type "NodePort" }} + full_hostname="${hostname}.{{- include "common.names.namespace" . }}" + {{- else }} + full_hostname="${hostname}.${HEADLESS_SERVICE}" + {{- end }} + + {{- if .Values.useHostnames }} + echo "${full_hostname}" + {{- else }} + retry_count=0 + until getent hosts "${full_hostname}" | awk '{ print $1; exit }' | grep .; do + if [[ $retry_count -lt {{ .Values.nameResolutionThreshold }} ]]; then + sleep {{ .Values.nameResolutionTimeout }} + else + error "IP address for ${full_hostname} not found" + exit 1 + fi + ((retry_count++)) + done + {{- end }} + } + + REDISPORT=$(get_port "$HOSTNAME" "REDIS") + + HEADLESS_SERVICE="{{ template "common.names.fullname" . }}-headless.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}" + + if [ -n "$REDIS_EXTERNAL_MASTER_HOST" ]; then + REDIS_SERVICE="$REDIS_EXTERNAL_MASTER_HOST" + else + REDIS_SERVICE="{{ template "common.names.fullname" . }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}" + fi + + SENTINEL_SERVICE_PORT=$(get_port "{{ include "common.names.fullname" . }}" "SENTINEL") + validate_quorum() { + if is_boolean_yes "$REDIS_TLS_ENABLED"; then + quorum_info_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$REDIS_PASSWORD" {{ end }}redis-cli -h $REDIS_SERVICE -p $SENTINEL_SERVICE_PORT --tls --cert ${REDIS_TLS_CERT_FILE} --key ${REDIS_TLS_KEY_FILE} --cacert ${REDIS_TLS_CA_FILE} sentinel master {{ .Values.sentinel.masterSet }}" + else + quorum_info_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$REDIS_PASSWORD" {{ end }}redis-cli -h $REDIS_SERVICE -p $SENTINEL_SERVICE_PORT sentinel master {{ .Values.sentinel.masterSet }}" + fi + info "about to run the command: $quorum_info_command" + eval $quorum_info_command | grep -Fq "s_down" + } + + trigger_manual_failover() { + if is_boolean_yes "$REDIS_TLS_ENABLED"; then + failover_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$REDIS_PASSWORD" {{ end }}redis-cli -h $REDIS_SERVICE -p $SENTINEL_SERVICE_PORT --tls --cert ${REDIS_TLS_CERT_FILE} --key ${REDIS_TLS_KEY_FILE} --cacert ${REDIS_TLS_CA_FILE} sentinel failover {{ .Values.sentinel.masterSet }}" + else + failover_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$REDIS_PASSWORD" {{ end }}redis-cli -h $REDIS_SERVICE -p $SENTINEL_SERVICE_PORT sentinel failover {{ .Values.sentinel.masterSet }}" + fi + + info "about to run the command: $failover_command" + eval $failover_command + } + + get_sentinel_master_info() { + if is_boolean_yes "$REDIS_TLS_ENABLED"; then + sentinel_info_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$REDIS_PASSWORD" {{ end }}timeout {{ .Values.sentinel.getMasterTimeout }} redis-cli -h $REDIS_SERVICE -p $SENTINEL_SERVICE_PORT --tls --cert ${REDIS_TLS_CERT_FILE} --key ${REDIS_TLS_KEY_FILE} --cacert ${REDIS_TLS_CA_FILE} sentinel get-master-addr-by-name {{ .Values.sentinel.masterSet }}" + else + sentinel_info_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$REDIS_PASSWORD" {{ end }}timeout {{ .Values.sentinel.getMasterTimeout }} redis-cli -h $REDIS_SERVICE -p $SENTINEL_SERVICE_PORT sentinel get-master-addr-by-name {{ .Values.sentinel.masterSet }}" + fi + + info "about to run the command: $sentinel_info_command" + retry_while "eval $sentinel_info_command" 2 5 + } + + {{- if and .Values.replica.containerSecurityContext.runAsUser (eq (.Values.replica.containerSecurityContext.runAsUser | int) 0) }} + useradd redis + chown -R redis {{ .Values.replica.persistence.path }} + {{- end }} + + [[ -f $REDIS_PASSWORD_FILE ]] && export REDIS_PASSWORD="$(< "${REDIS_PASSWORD_FILE}")" + [[ -f $REDIS_MASTER_PASSWORD_FILE ]] && export REDIS_MASTER_PASSWORD="$(< "${REDIS_MASTER_PASSWORD_FILE}")" + + # check if there is a master + master_in_persisted_conf="$(get_full_hostname "$HOSTNAME")" + master_port_in_persisted_conf="$REDIS_MASTER_PORT_NUMBER" + master_in_sentinel="$(get_sentinel_master_info)" + redisRetVal=$? + + {{- if .Values.sentinel.persistence.enabled }} + if [[ -f /opt/bitnami/redis-sentinel/etc/sentinel.conf ]]; then + master_in_persisted_conf="$(awk '/monitor/ {print $4}' /opt/bitnami/redis-sentinel/etc/sentinel.conf)" + master_port_in_persisted_conf="$(awk '/monitor/ {print $5}' /opt/bitnami/redis-sentinel/etc/sentinel.conf)" + info "Found previous master ${master_in_persisted_conf}:${master_port_in_persisted_conf} in /opt/bitnami/redis-sentinel/etc/sentinel.conf" + debug "$(cat /opt/bitnami/redis-sentinel/etc/sentinel.conf | grep monitor)" + touch /opt/bitnami/redis-sentinel/etc/.node_read + fi + {{- end }} + + if [[ $redisRetVal -ne 0 ]]; then + if [[ "$master_in_persisted_conf" == "$(get_full_hostname "$HOSTNAME")" ]]; then + # Case 1: No active sentinel and in previous sentinel.conf we were the master --> MASTER + info "Configuring the node as master" + export REDIS_REPLICATION_MODE="master" + else + # Case 2: No active sentinel and in previous sentinel.conf we were not master --> REPLICA + info "Configuring the node as replica" + export REDIS_REPLICATION_MODE="replica" + REDIS_MASTER_HOST=${master_in_persisted_conf} + REDIS_MASTER_PORT_NUMBER=${master_port_in_persisted_conf} + fi + else + # Fetches current master's host and port + REDIS_SENTINEL_INFO=($(get_sentinel_master_info)) + info "Current master: REDIS_SENTINEL_INFO=(${REDIS_SENTINEL_INFO[0]},${REDIS_SENTINEL_INFO[1]})" + REDIS_MASTER_HOST=${REDIS_SENTINEL_INFO[0]} + REDIS_MASTER_PORT_NUMBER=${REDIS_SENTINEL_INFO[1]} + + if [[ "$REDIS_MASTER_HOST" == "$(get_full_hostname "$HOSTNAME")" ]]; then + # Case 3: Active sentinel and master it is this node --> MASTER + info "Configuring the node as master" + export REDIS_REPLICATION_MODE="master" + else + # Case 4: Active sentinel and master is not this node --> REPLICA + info "Configuring the node as replica" + export REDIS_REPLICATION_MODE="replica" + + {{- if and .Values.sentinel.automateClusterRecovery (le (int .Values.sentinel.downAfterMilliseconds) 2000) }} + retry_count=1 + while validate_quorum + do + info "sleeping, waiting for Redis master to come up" + sleep 1s + if ! ((retry_count % 11)); then + info "Trying to manually failover" + failover_result=$(trigger_manual_failover) + + debug "Failover result: $failover_result" + fi + + ((retry_count+=1)) + done + info "Redis master is up now" + {{- end }} + fi + fi + + if [[ -n "$REDIS_EXTERNAL_MASTER_HOST" ]]; then + REDIS_MASTER_HOST="$REDIS_EXTERNAL_MASTER_HOST" + REDIS_MASTER_PORT_NUMBER="${REDIS_EXTERNAL_MASTER_PORT}" + fi + + if [[ -f /opt/bitnami/redis/mounted-etc/replica.conf ]];then + cp /opt/bitnami/redis/mounted-etc/replica.conf /opt/bitnami/redis/etc/replica.conf + fi + + if [[ -f /opt/bitnami/redis/mounted-etc/redis.conf ]];then + cp /opt/bitnami/redis/mounted-etc/redis.conf /opt/bitnami/redis/etc/redis.conf + fi + + echo "" >> /opt/bitnami/redis/etc/replica.conf + echo "replica-announce-port $REDISPORT" >> /opt/bitnami/redis/etc/replica.conf + echo "replica-announce-ip $(get_full_hostname "$HOSTNAME")" >> /opt/bitnami/redis/etc/replica.conf + + {{- if .Values.tls.enabled }} + ARGS=("--port" "0") + ARGS+=("--tls-port" "${REDIS_TLS_PORT}") + ARGS+=("--tls-cert-file" "${REDIS_TLS_CERT_FILE}") + ARGS+=("--tls-key-file" "${REDIS_TLS_KEY_FILE}") + ARGS+=("--tls-ca-cert-file" "${REDIS_TLS_CA_FILE}") + ARGS+=("--tls-auth-clients" "${REDIS_TLS_AUTH_CLIENTS}") + ARGS+=("--tls-replication" "yes") + {{- if .Values.tls.dhParamsFilename }} + ARGS+=("--tls-dh-params-file" "${REDIS_TLS_DH_PARAMS_FILE}") + {{- end }} + {{- else }} + ARGS=("--port" "${REDIS_PORT}") + {{- end }} + + if [[ "$REDIS_REPLICATION_MODE" = "slave" ]] || [[ "$REDIS_REPLICATION_MODE" = "replica" ]]; then + ARGS+=("--replicaof" "${REDIS_MASTER_HOST}" "${REDIS_MASTER_PORT_NUMBER}") + fi + + {{- if .Values.auth.enabled }} + ARGS+=("--requirepass" "${REDIS_PASSWORD}") + ARGS+=("--masterauth" "${REDIS_MASTER_PASSWORD}") + {{- else }} + ARGS+=("--protected-mode" "no") + {{- end }} + ARGS+=("--include" "/opt/bitnami/redis/etc/replica.conf") + ARGS+=("--include" "/opt/bitnami/redis/etc/redis.conf") + {{- if .Values.replica.extraFlags }} + {{- range .Values.replica.extraFlags }} + ARGS+=({{ . | quote }}) + {{- end }} + {{- end }} + + {{- if .Values.replica.preExecCmds }} + {{- .Values.replica.preExecCmds | nindent 4 }} + {{- end }} + + {{- if .Values.replica.command }} + exec {{ .Values.replica.command }} "${ARGS[@]}" + {{- else }} + exec redis-server "${ARGS[@]}" + {{- end }} + + start-sentinel.sh: | + #!/bin/bash + + . /opt/bitnami/scripts/libos.sh + . /opt/bitnami/scripts/libvalidations.sh + . /opt/bitnami/scripts/libfile.sh + + HEADLESS_SERVICE="{{ template "common.names.fullname" . }}-headless.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}" + REDIS_SERVICE="{{ template "common.names.fullname" . }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}" + + get_port() { + hostname="$1" + type="$2" + + port_var=$(echo "${hostname^^}_SERVICE_PORT_$type" | sed "s/-/_/g") + port=${!port_var} + + if [ -z "$port" ]; then + case $type in + "SENTINEL") + echo {{ .Values.sentinel.containerPorts.sentinel }} + ;; + "REDIS") + echo {{ .Values.master.containerPorts.redis }} + ;; + esac + else + echo $port + fi + } + + get_full_hostname() { + hostname="$1" + + {{- if .Values.useExternalDNS.enabled }} + full_hostname="${hostname}.{{- include "redis.externalDNS.suffix" . }}" + {{- else if eq .Values.sentinel.service.type "NodePort" }} + full_hostname="${hostname}.{{- include "common.names.namespace" . }}" + {{- else }} + full_hostname="${hostname}.${HEADLESS_SERVICE}" + {{- end }} + + {{- if .Values.useHostnames }} + echo "${full_hostname}" + {{- else }} + retry_count=0 + until getent hosts "${full_hostname}" | awk '{ print $1; exit }' | grep .; do + if [[ $retry_count -lt {{ .Values.nameResolutionThreshold }} ]]; then + sleep {{ .Values.nameResolutionTimeout }} + else + error "IP address for ${full_hostname} not found" + exit 1 + fi + ((retry_count++)) + done + {{- end }} + } + + SERVPORT=$(get_port "$HOSTNAME" "SENTINEL") + REDISPORT=$(get_port "$HOSTNAME" "REDIS") + SENTINEL_SERVICE_PORT=$(get_port "{{ include "common.names.fullname" . }}" "SENTINEL") + + sentinel_conf_set() { + local -r key="${1:?missing key}" + local value="${2:-}" + + # Sanitize inputs + value="${value//\\/\\\\}" + value="${value//&/\\&}" + value="${value//\?/\\?}" + [[ "$value" = "" ]] && value="\"$value\"" + + replace_in_file "/opt/bitnami/redis-sentinel/etc/sentinel.conf" "^#*\s*${key} .*" "${key} ${value}" false + } + sentinel_conf_add() { + echo $'\n'"$@" >> "/opt/bitnami/redis-sentinel/etc/sentinel.conf" + } + host_id() { + echo "$1" | openssl sha1 | awk '{print $2}' + } + get_sentinel_master_info() { + if is_boolean_yes "$REDIS_SENTINEL_TLS_ENABLED"; then + sentinel_info_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$REDIS_PASSWORD" {{ end }}timeout {{ .Values.sentinel.getMasterTimeout }} redis-cli -h $REDIS_SERVICE -p $SENTINEL_SERVICE_PORT --tls --cert ${REDIS_SENTINEL_TLS_CERT_FILE} --key ${REDIS_SENTINEL_TLS_KEY_FILE} --cacert ${REDIS_SENTINEL_TLS_CA_FILE} sentinel get-master-addr-by-name {{ .Values.sentinel.masterSet }}" + else + sentinel_info_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$REDIS_PASSWORD" {{ end }}timeout {{ .Values.sentinel.getMasterTimeout }} redis-cli -h $REDIS_SERVICE -p $SENTINEL_SERVICE_PORT sentinel get-master-addr-by-name {{ .Values.sentinel.masterSet }}" + fi + info "about to run the command: $sentinel_info_command" + retry_while "eval $sentinel_info_command" 2 5 + } + + [[ -f $REDIS_PASSWORD_FILE ]] && export REDIS_PASSWORD="$(< "${REDIS_PASSWORD_FILE}")" + + master_in_persisted_conf="$(get_full_hostname "$HOSTNAME")" + + {{- if .Values.sentinel.persistence.enabled }} + if [[ -f /opt/bitnami/redis-sentinel/etc/sentinel.conf ]]; then + check_lock_file() { + [[ -f /opt/bitnami/redis-sentinel/etc/.node_read ]] + } + retry_while "check_lock_file" + rm -f /opt/bitnami/redis-sentinel/etc/.node_read + master_in_persisted_conf="$(awk '/monitor/ {print $4}' /opt/bitnami/redis-sentinel/etc/sentinel.conf)" + info "Found previous master $master_in_persisted_conf in /opt/bitnami/redis-sentinel/etc/sentinel.conf" + debug "$(cat /opt/bitnami/redis-sentinel/etc/sentinel.conf | grep monitor)" + fi + {{- end }} + if ! get_sentinel_master_info && [[ "$master_in_persisted_conf" == "$(get_full_hostname "$HOSTNAME")" ]]; then + # No master found, lets create a master node + export REDIS_REPLICATION_MODE="master" + + REDIS_MASTER_HOST=$(get_full_hostname "$HOSTNAME") + REDIS_MASTER_PORT_NUMBER="$REDISPORT" + else + export REDIS_REPLICATION_MODE="replica" + + # Fetches current master's host and port + REDIS_SENTINEL_INFO=($(get_sentinel_master_info)) + info "printing REDIS_SENTINEL_INFO=(${REDIS_SENTINEL_INFO[0]},${REDIS_SENTINEL_INFO[1]})" + REDIS_MASTER_HOST=${REDIS_SENTINEL_INFO[0]} + REDIS_MASTER_PORT_NUMBER=${REDIS_SENTINEL_INFO[1]} + fi + + if [[ -n "$REDIS_EXTERNAL_MASTER_HOST" ]]; then + REDIS_MASTER_HOST="$REDIS_EXTERNAL_MASTER_HOST" + REDIS_MASTER_PORT_NUMBER="${REDIS_EXTERNAL_MASTER_PORT}" + fi + + cp /opt/bitnami/redis-sentinel/mounted-etc/sentinel.conf /opt/bitnami/redis-sentinel/etc/sentinel.conf + {{- if .Values.auth.enabled }} + printf "\nsentinel auth-pass %s %s" "{{ .Values.sentinel.masterSet }}" "$REDIS_PASSWORD" >> /opt/bitnami/redis-sentinel/etc/sentinel.conf + {{- if and .Values.auth.enabled .Values.auth.sentinel }} + printf "\nrequirepass %s" "$REDIS_PASSWORD" >> /opt/bitnami/redis-sentinel/etc/sentinel.conf + {{- end }} + {{- end }} + printf "\nsentinel myid %s" "$(host_id "$HOSTNAME")" >> /opt/bitnami/redis-sentinel/etc/sentinel.conf + + if [[ -z "$REDIS_MASTER_HOST" ]] || [[ -z "$REDIS_MASTER_PORT_NUMBER" ]] + then + # Prevent incorrect configuration to be written to sentinel.conf + error "Redis master host is configured incorrectly (host: $REDIS_MASTER_HOST, port: $REDIS_MASTER_PORT_NUMBER)" + exit 1 + fi + + sentinel_conf_set "sentinel monitor" "{{ .Values.sentinel.masterSet }} "$REDIS_MASTER_HOST" "$REDIS_MASTER_PORT_NUMBER" {{ .Values.sentinel.quorum }}" + + add_known_sentinel() { + hostname="$1" + ip="$2" + + if [[ -n "$hostname" && -n "$ip" && "$hostname" != "$HOSTNAME" ]]; then + sentinel_conf_add "sentinel known-sentinel {{ .Values.sentinel.masterSet }} $(get_full_hostname "$hostname") $(get_port "$hostname" "SENTINEL") $(host_id "$hostname")" + fi + } + add_known_replica() { + hostname="$1" + ip="$2" + + if [[ -n "$ip" && "$(get_full_hostname "$hostname")" != "$REDIS_MASTER_HOST" ]]; then + sentinel_conf_add "sentinel known-replica {{ .Values.sentinel.masterSet }} $(get_full_hostname "$hostname") $(get_port "$hostname" "REDIS")" + fi + } + + # Add available hosts on the network as known replicas & sentinels + for node in $(seq 0 $(({{ .Values.replica.replicaCount }}-1))); do + hostname="{{ template "common.names.fullname" . }}-node-$node" + ip="$(getent hosts "$hostname.$HEADLESS_SERVICE" | awk '{ print $1 }')" + add_known_sentinel "$hostname" "$ip" + add_known_replica "$hostname" "$ip" + done + + echo "" >> /opt/bitnami/redis-sentinel/etc/sentinel.conf + {{- if not (contains "sentinel announce-hostnames" .Values.sentinel.configuration) }} + echo "sentinel announce-hostnames yes" >> /opt/bitnami/redis-sentinel/etc/sentinel.conf + {{- end }} + {{- if not (contains "sentinel resolve-hostnames" .Values.sentinel.configuration) }} + echo "sentinel resolve-hostnames yes" >> /opt/bitnami/redis-sentinel/etc/sentinel.conf + {{- end }} + {{- if not (contains "sentinel announce-port" .Values.sentinel.configuration) }} + echo "sentinel announce-port $SERVPORT" >> /opt/bitnami/redis-sentinel/etc/sentinel.conf + {{- end }} + {{- if not (contains "sentinel announce-ip" .Values.sentinel.configuration) }} + echo "sentinel announce-ip $(get_full_hostname "$HOSTNAME")" >> /opt/bitnami/redis-sentinel/etc/sentinel.conf + {{- end }} + + {{- if .Values.tls.enabled }} + ARGS=("--port" "0") + ARGS+=("--tls-port" "${REDIS_SENTINEL_TLS_PORT_NUMBER}") + ARGS+=("--tls-cert-file" "${REDIS_SENTINEL_TLS_CERT_FILE}") + ARGS+=("--tls-key-file" "${REDIS_SENTINEL_TLS_KEY_FILE}") + ARGS+=("--tls-ca-cert-file" "${REDIS_SENTINEL_TLS_CA_FILE}") + ARGS+=("--tls-replication" "yes") + ARGS+=("--tls-auth-clients" "${REDIS_SENTINEL_TLS_AUTH_CLIENTS}") + {{- if .Values.tls.dhParamsFilename }} + ARGS+=("--tls-dh-params-file" "${REDIS_SENTINEL_TLS_DH_PARAMS_FILE}") + {{- end }} + {{- end }} + {{- if .Values.sentinel.preExecCmds }} + {{ .Values.sentinel.preExecCmds | nindent 4 }} + {{- end }} + exec redis-server /opt/bitnami/redis-sentinel/etc/sentinel.conf {{- if .Values.tls.enabled }} "${ARGS[@]}" {{- end }} --sentinel + prestop-sentinel.sh: | + #!/bin/bash + + . /opt/bitnami/scripts/libvalidations.sh + . /opt/bitnami/scripts/libos.sh + + HEADLESS_SERVICE="{{ template "common.names.fullname" . }}-headless.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}" + + get_full_hostname() { + hostname="$1" + + {{- if .Values.useExternalDNS.enabled }} + full_hostname="${hostname}.{{- include "redis.externalDNS.suffix" . }}" + {{- else if eq .Values.sentinel.service.type "NodePort" }} + full_hostname="${hostname}.{{- include "common.names.namespace" . }}" + {{- else }} + full_hostname="${hostname}.${HEADLESS_SERVICE}" + {{- end }} + + {{- if .Values.useHostnames }} + echo "${full_hostname}" + {{- else }} + retry_count=0 + until getent hosts "${full_hostname}" | awk '{ print $1; exit }' | grep .; do + if [[ $retry_count -lt {{ .Values.nameResolutionThreshold }} ]]; then + sleep {{ .Values.nameResolutionTimeout }} + else + error "IP address for ${full_hostname} not found" + exit 1 + fi + ((retry_count++)) + done + {{- end }} + } + + run_sentinel_command() { + if is_boolean_yes "$REDIS_SENTINEL_TLS_ENABLED"; then + redis-cli -h "$REDIS_SERVICE" -p "$REDIS_SENTINEL_PORT" --tls --cert "$REDIS_SENTINEL_TLS_CERT_FILE" --key "$REDIS_SENTINEL_TLS_KEY_FILE" --cacert "$REDIS_SENTINEL_TLS_CA_FILE" sentinel "$@" + else + redis-cli -h "$REDIS_SERVICE" -p "$REDIS_SENTINEL_PORT" sentinel "$@" + fi + } + sentinel_failover_finished() { + REDIS_SENTINEL_INFO=($(run_sentinel_command get-master-addr-by-name "{{ .Values.sentinel.masterSet }}")) + REDIS_MASTER_HOST="${REDIS_SENTINEL_INFO[0]}" + [[ "$REDIS_MASTER_HOST" != "$(get_full_hostname $HOSTNAME)" ]] + } + + REDIS_SERVICE="{{ include "common.names.fullname" . }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}" + + {{ if .Values.auth.sentinel -}} + # redis-cli automatically consumes credentials from the REDISCLI_AUTH variable + [[ -n "$REDIS_PASSWORD" ]] && export REDISCLI_AUTH="$REDIS_PASSWORD" + [[ -f "$REDIS_PASSWORD_FILE" ]] && export REDISCLI_AUTH="$(< "${REDIS_PASSWORD_FILE}")" + {{- end }} + + if ! sentinel_failover_finished; then + echo "I am the master pod and you are stopping me. Starting sentinel failover" + if retry_while "sentinel_failover_finished" "{{ sub .Values.sentinel.terminationGracePeriodSeconds 10 }}" 1; then + echo "Master has been successfuly failed over to a different pod." + exit 0 + else + echo "Master failover failed" + exit 1 + fi + else + exit 0 + fi + prestop-redis.sh: | + #!/bin/bash + + . /opt/bitnami/scripts/libvalidations.sh + . /opt/bitnami/scripts/libos.sh + + run_redis_command() { + if is_boolean_yes "$REDIS_TLS_ENABLED"; then + redis-cli -h 127.0.0.1 -p "$REDIS_TLS_PORT" --tls --cert "$REDIS_TLS_CERT_FILE" --key "$REDIS_TLS_KEY_FILE" --cacert "$REDIS_TLS_CA_FILE" "$@" + else + redis-cli -h 127.0.0.1 -p "$REDIS_PORT" "$@" + fi + } + is_master() { + REDIS_ROLE=$(run_redis_command role | head -1) + [[ "$REDIS_ROLE" == "master" ]] + } + + HEADLESS_SERVICE="{{ template "common.names.fullname" . }}-headless.{{- include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}" + + get_full_hostname() { + hostname="$1" + + {{- if .Values.useExternalDNS.enabled }} + full_hostname="${hostname}.{{- include "redis.externalDNS.suffix" . }}" + {{- else if eq .Values.sentinel.service.type "NodePort" }} + full_hostname="${hostname}.{{- include "common.names.namespace" . }}" + {{- else }} + full_hostname="${hostname}.${HEADLESS_SERVICE}" + {{- end }} + + {{- if .Values.useHostnames }} + echo "${full_hostname}" + {{- else }} + retry_count=0 + until getent hosts "${full_hostname}" | awk '{ print $1; exit }' | grep .; do + if [[ $retry_count -lt {{ .Values.nameResolutionThreshold }} ]]; then + sleep {{ .Values.nameResolutionTimeout }} + else + error "IP address for ${full_hostname} not found" + exit 1 + fi + ((retry_count++)) + done + {{- end }} + } + + run_sentinel_command() { + if is_boolean_yes "$REDIS_SENTINEL_TLS_ENABLED"; then + {{ .Values.auth.sentinel | ternary "" "env -u REDISCLI_AUTH " -}} redis-cli -h "$REDIS_SERVICE" -p "$REDIS_SENTINEL_PORT" --tls --cert "$REDIS_SENTINEL_TLS_CERT_FILE" --key "$REDIS_SENTINEL_TLS_KEY_FILE" --cacert "$REDIS_SENTINEL_TLS_CA_FILE" sentinel "$@" + else + {{ .Values.auth.sentinel | ternary "" "env -u REDISCLI_AUTH " -}} redis-cli -h "$REDIS_SERVICE" -p "$REDIS_SENTINEL_PORT" sentinel "$@" + fi + } + sentinel_failover_finished() { + REDIS_SENTINEL_INFO=($(run_sentinel_command get-master-addr-by-name "{{ .Values.sentinel.masterSet }}")) + REDIS_MASTER_HOST="${REDIS_SENTINEL_INFO[0]}" + [[ "$REDIS_MASTER_HOST" != "$(get_full_hostname $HOSTNAME)" ]] + } + + REDIS_SERVICE="{{ include "common.names.fullname" . }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}" + + # redis-cli automatically consumes credentials from the REDISCLI_AUTH variable + [[ -n "$REDIS_PASSWORD" ]] && export REDISCLI_AUTH="$REDIS_PASSWORD" + [[ -f "$REDIS_PASSWORD_FILE" ]] && export REDISCLI_AUTH="$(< "${REDIS_PASSWORD_FILE}")" + + + if is_master && ! sentinel_failover_finished; then + echo "I am the master pod and you are stopping me. Pausing client connections." + # Pausing client write connections to avoid data loss + run_redis_command CLIENT PAUSE "{{ mul (add 2 (sub .Values.sentinel.terminationGracePeriodSeconds 10)) 1000 }}" WRITE + + echo "Issuing failover" + # if I am the master, issue a command to failover once + run_sentinel_command failover "{{ .Values.sentinel.masterSet }}" + + {{- if .Values.sentinel.redisShutdownWaitFailover }} + echo "Waiting for sentinel to complete failover for up to {{ sub .Values.sentinel.terminationGracePeriodSeconds 10 }}s" + retry_while "sentinel_failover_finished" "{{ sub .Values.sentinel.terminationGracePeriodSeconds 10 }}" 1 + {{- end }} + else + exit 0 + fi + +{{- else }} + start-master.sh: | + #!/bin/bash + + [[ -f $REDIS_PASSWORD_FILE ]] && export REDIS_PASSWORD="$(< "${REDIS_PASSWORD_FILE}")" + {{- if and .Values.master.containerSecurityContext.runAsUser (eq (.Values.master.containerSecurityContext.runAsUser | int) 0) }} + useradd redis + chown -R redis {{ .Values.master.persistence.path }} + {{- end }} + if [[ -f /opt/bitnami/redis/mounted-etc/master.conf ]];then + cp /opt/bitnami/redis/mounted-etc/master.conf /opt/bitnami/redis/etc/master.conf + fi + if [[ -f /opt/bitnami/redis/mounted-etc/redis.conf ]];then + cp /opt/bitnami/redis/mounted-etc/redis.conf /opt/bitnami/redis/etc/redis.conf + fi + {{- if .Values.tls.enabled }} + ARGS=("--port" "0") + ARGS+=("--tls-port" "${REDIS_TLS_PORT}") + ARGS+=("--tls-cert-file" "${REDIS_TLS_CERT_FILE}") + ARGS+=("--tls-key-file" "${REDIS_TLS_KEY_FILE}") + ARGS+=("--tls-ca-cert-file" "${REDIS_TLS_CA_FILE}") + ARGS+=("--tls-auth-clients" "${REDIS_TLS_AUTH_CLIENTS}") + {{- if .Values.tls.dhParamsFilename }} + ARGS+=("--tls-dh-params-file" "${REDIS_TLS_DH_PARAMS_FILE}") + {{- end }} + {{- else }} + ARGS=("--port" "${REDIS_PORT}") + {{- end }} + {{- if .Values.auth.enabled }} + ARGS+=("--requirepass" "${REDIS_PASSWORD}") + ARGS+=("--masterauth" "${REDIS_PASSWORD}") + {{- else }} + ARGS+=("--protected-mode" "no") + {{- end }} + ARGS+=("--include" "/opt/bitnami/redis/etc/redis.conf") + ARGS+=("--include" "/opt/bitnami/redis/etc/master.conf") + {{- if .Values.master.extraFlags }} + {{- range .Values.master.extraFlags }} + ARGS+=({{ . | quote }}) + {{- end }} + {{- end }} + {{- if .Values.master.preExecCmds }} + {{ .Values.master.preExecCmds | nindent 4 }} + {{- end }} + {{- if .Values.master.command }} + exec {{ .Values.master.command }} "${ARGS[@]}" + {{- else }} + exec redis-server "${ARGS[@]}" + {{- end }} + {{- if eq .Values.architecture "replication" }} + start-replica.sh: | + #!/bin/bash + + get_port() { + hostname="$1" + type="$2" + + port_var=$(echo "${hostname^^}_SERVICE_PORT_$type" | sed "s/-/_/g") + port=${!port_var} + + if [ -z "$port" ]; then + case $type in + "SENTINEL") + echo {{ .Values.sentinel.containerPorts.sentinel }} + ;; + "REDIS") + echo {{ .Values.master.containerPorts.redis }} + ;; + esac + else + echo $port + fi + } + + get_full_hostname() { + hostname="$1" + + {{- if .Values.useExternalDNS.enabled }} + full_hostname="${hostname}.{{- include "redis.externalDNS.suffix" . }}" + {{- else if eq .Values.sentinel.service.type "NodePort" }} + full_hostname="${hostname}.{{- include "common.names.namespace" . }}" + {{- else }} + full_hostname="${hostname}.${HEADLESS_SERVICE}" + {{- end }} + + {{- if .Values.useHostnames }} + echo "${full_hostname}" + {{- else }} + retry_count=0 + until getent hosts "${full_hostname}" | awk '{ print $1; exit }' | grep .; do + if [[ $retry_count -lt {{ .Values.nameResolutionThreshold }} ]]; then + sleep {{ .Values.nameResolutionTimeout }} + else + error "IP address for ${full_hostname} not found" + exit 1 + fi + ((retry_count++)) + done + {{- end }} + } + + REDISPORT=$(get_port "$HOSTNAME" "REDIS") + HEADLESS_SERVICE="{{ template "common.names.fullname" . }}-headless.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}" + + [[ -f $REDIS_PASSWORD_FILE ]] && export REDIS_PASSWORD="$(< "${REDIS_PASSWORD_FILE}")" + [[ -f $REDIS_MASTER_PASSWORD_FILE ]] && export REDIS_MASTER_PASSWORD="$(< "${REDIS_MASTER_PASSWORD_FILE}")" + {{- if and .Values.replica.containerSecurityContext.runAsUser (eq (.Values.replica.containerSecurityContext.runAsUser | int) 0) }} + useradd redis + chown -R redis {{ .Values.replica.persistence.path }} + {{- end }} + if [[ -f /opt/bitnami/redis/mounted-etc/replica.conf ]];then + cp /opt/bitnami/redis/mounted-etc/replica.conf /opt/bitnami/redis/etc/replica.conf + fi + if [[ -f /opt/bitnami/redis/mounted-etc/redis.conf ]];then + cp /opt/bitnami/redis/mounted-etc/redis.conf /opt/bitnami/redis/etc/redis.conf + fi + + echo "" >> /opt/bitnami/redis/etc/replica.conf + echo "replica-announce-port $REDISPORT" >> /opt/bitnami/redis/etc/replica.conf + echo "replica-announce-ip $(get_full_hostname "$HOSTNAME")" >> /opt/bitnami/redis/etc/replica.conf + + {{- if .Values.tls.enabled }} + ARGS=("--port" "0") + ARGS+=("--tls-port" "${REDIS_TLS_PORT}") + ARGS+=("--tls-cert-file" "${REDIS_TLS_CERT_FILE}") + ARGS+=("--tls-key-file" "${REDIS_TLS_KEY_FILE}") + ARGS+=("--tls-ca-cert-file" "${REDIS_TLS_CA_FILE}") + ARGS+=("--tls-auth-clients" "${REDIS_TLS_AUTH_CLIENTS}") + ARGS+=("--tls-replication" "yes") + {{- if .Values.tls.dhParamsFilename }} + ARGS+=("--tls-dh-params-file" "${REDIS_TLS_DH_PARAMS_FILE}") + {{- end }} + {{- else }} + ARGS=("--port" "${REDIS_PORT}") + {{- end }} + ARGS+=("--replicaof" "${REDIS_MASTER_HOST}" "${REDIS_MASTER_PORT_NUMBER}") + {{- if .Values.auth.enabled }} + ARGS+=("--requirepass" "${REDIS_PASSWORD}") + ARGS+=("--masterauth" "${REDIS_MASTER_PASSWORD}") + {{- else }} + ARGS+=("--protected-mode" "no") + {{- end }} + ARGS+=("--include" "/opt/bitnami/redis/etc/redis.conf") + ARGS+=("--include" "/opt/bitnami/redis/etc/replica.conf") + {{- if .Values.replica.extraFlags }} + {{- range .Values.replica.extraFlags }} + ARGS+=({{ . | quote }}) + {{- end }} + {{- end }} + {{- if .Values.replica.preExecCmds }} + {{ .Values.replica.preExecCmds | nindent 4 }} + {{- end }} + {{- if .Values.replica.command }} + exec {{ .Values.replica.command }} "${ARGS[@]}" + {{- else }} + exec redis-server "${ARGS[@]}" + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/redis/templates/secret-svcbind.yaml b/backing-services/redis/templates/secret-svcbind.yaml new file mode 100644 index 0000000..de74913 --- /dev/null +++ b/backing-services/redis/templates/secret-svcbind.yaml @@ -0,0 +1,37 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.serviceBindings.enabled }} +{{- $host := include "common.names.fullname" . }} +{{- if not .Values.sentinel.enabled }} +{{- $host = printf "%s-master" (include "common.names.fullname" .) }} +{{- end }} +{{- $port := print .Values.master.service.ports.redis }} +{{- if .Values.sentinel.enabled }} +{{- $port = print .Values.sentinel.service.ports.redis }} +{{- end }} +{{- $password := include "redis.password" . }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }}-svcbind + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: servicebinding.io/redis +data: + provider: {{ print "bitnami" | b64enc | quote }} + type: {{ print "redis" | b64enc | quote }} + host: {{ print $host | b64enc | quote }} + port: {{ print $port | b64enc | quote }} + password: {{ print $password | b64enc | quote }} + {{- if $password }} + uri: {{ printf "redis://:%s@%s:%s" $password $host $port | b64enc | quote }} + {{- else }} + uri: {{ printf "redis://%s:%s" $host $port | b64enc | quote }} + {{- end }} +{{- end }} diff --git a/backing-services/redis/templates/secret.yaml b/backing-services/redis/templates/secret.yaml new file mode 100644 index 0000000..003a276 --- /dev/null +++ b/backing-services/redis/templates/secret.yaml @@ -0,0 +1,25 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.auth.enabled (not .Values.auth.existingSecret) -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.secretAnnotations .Values.commonAnnotations }} + annotations: + {{- if .Values.secretAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.secretAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} +type: Opaque +data: + redis-password: {{ include "redis.password" . | b64enc | quote }} +{{- end -}} diff --git a/backing-services/redis/templates/sentinel/hpa.yaml b/backing-services/redis/templates/sentinel/hpa.yaml new file mode 100644 index 0000000..f8bd356 --- /dev/null +++ b/backing-services/redis/templates/sentinel/hpa.yaml @@ -0,0 +1,49 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.replica.autoscaling.enabled .Values.sentinel.enabled }} +apiVersion: {{ include "common.capabilities.hpa.apiVersion" ( dict "context" $ ) }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ printf "%s-node" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: replica + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + scaleTargetRef: + apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} + kind: StatefulSet + name: {{ printf "%s-node" (include "common.names.fullname" .) }} + minReplicas: {{ .Values.replica.autoscaling.minReplicas }} + maxReplicas: {{ .Values.replica.autoscaling.maxReplicas }} + metrics: + {{- if .Values.replica.autoscaling.targetMemory }} + - type: Resource + resource: + name: memory + {{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .) }} + targetAverageUtilization: {{ .Values.replica.autoscaling.targetMemory }} + {{- else }} + target: + type: Utilization + averageUtilization: {{ .Values.replica.autoscaling.targetMemory }} + {{- end }} + {{- end }} + {{- if .Values.replica.autoscaling.targetCPU }} + - type: Resource + resource: + name: cpu + {{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .) }} + targetAverageUtilization: {{ .Values.replica.autoscaling.targetCPU }} + {{- else }} + target: + type: Utilization + averageUtilization: {{ .Values.replica.autoscaling.targetCPU }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/redis/templates/sentinel/node-services.yaml b/backing-services/redis/templates/sentinel/node-services.yaml new file mode 100644 index 0000000..672de5c --- /dev/null +++ b/backing-services/redis/templates/sentinel/node-services.yaml @@ -0,0 +1,67 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replication") .Values.sentinel.enabled (eq .Values.sentinel.service.type "NodePort") (or .Release.IsUpgrade .Values.sentinel.service.nodePorts.redis ) }} + +{{- range $i := until (int .Values.replica.replicaCount) }} + +{{ $portsmap := (lookup "v1" "ConfigMap" (include "common.names.namespace" $) (printf "%s-%s" ( include "common.names.fullname" $ ) "ports-configmap")).data }} + +{{ $sentinelport := 0}} +{{ $redisport := 0}} +{{- if $portsmap }} +{{ $sentinelport = index $portsmap (printf "%s-node-%s-%s" (include "common.names.fullname" $) (toString $i) "sentinel") }} +{{ $redisport = index $portsmap (printf "%s-node-%s-%s" (include "common.names.fullname" $) (toString $i) "redis") }} +{{- else }} +{{- end }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "common.names.fullname" $ }}-node-{{ $i }} + namespace: {{ include "common.names.namespace" $ | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $.Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: node + {{- if or $.Values.commonAnnotations $.Values.sentinel.service.annotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list $.Values.sentinel.service.annotations $.Values.commonAnnotations ) "context" $ ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: NodePort + ports: + - name: sentinel + {{- if $.Values.sentinel.service.nodePorts.sentinel }} + nodePort: {{ (add $.Values.sentinel.service.nodePorts.sentinel $i 1) }} + port: {{ (add $.Values.sentinel.service.nodePorts.sentinel $i 1) }} + {{- else }} + nodePort: {{ $sentinelport }} + port: {{ $sentinelport }} + {{- end }} + protocol: TCP + targetPort: {{ $.Values.sentinel.containerPorts.sentinel }} + - name: redis + {{- if $.Values.sentinel.service.nodePorts.redis }} + nodePort: {{ (add $.Values.sentinel.service.nodePorts.redis $i 1) }} + port: {{ (add $.Values.sentinel.service.nodePorts.redis $i 1) }} + {{- else }} + nodePort: {{ $redisport }} + port: {{ $redisport }} + {{- end }} + protocol: TCP + targetPort: {{ $.Values.replica.containerPorts.redis }} + - name: sentinel-internal + nodePort: null + port: {{ $.Values.sentinel.containerPorts.sentinel }} + protocol: TCP + targetPort: {{ $.Values.sentinel.containerPorts.sentinel }} + - name: redis-internal + nodePort: null + port: {{ $.Values.replica.containerPorts.redis }} + protocol: TCP + targetPort: {{ $.Values.replica.containerPorts.redis }} + selector: + statefulset.kubernetes.io/pod-name: {{ template "common.names.fullname" $ }}-node-{{ $i }} +--- +{{- end }} +{{- end }} diff --git a/backing-services/redis/templates/sentinel/ports-configmap.yaml b/backing-services/redis/templates/sentinel/ports-configmap.yaml new file mode 100644 index 0000000..3efed74 --- /dev/null +++ b/backing-services/redis/templates/sentinel/ports-configmap.yaml @@ -0,0 +1,102 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replication") .Values.sentinel.enabled (eq .Values.sentinel.service.type "NodePort") (not .Values.sentinel.service.nodePorts.redis ) }} +{{- /* create a list to keep track of ports we choose to use */}} +{{ $chosenports := (list ) }} + +{{- /* Get list of all used nodeports */}} +{{ $usedports := (list ) }} +{{- range $index, $service := (lookup "v1" "Service" "" "").items }} + {{- range.spec.ports }} + {{- if .nodePort }} + {{- $usedports = (append $usedports .nodePort) }} + {{- end }} + {{- end }} +{{- end }} + +{{- /* +comments that start with # are rendered in the output when you debug, so you can less and search for them +Vars in the comment will be rendered out, so you can check their value this way. +https://helm.sh/docs/chart_best_practices/templates/#comments-yaml-comments-vs-template-comments + +remove the template comments and leave the yaml comments to help debug +*/}} + +{{- /* Sort the list */}} +{{ $usedports = $usedports | sortAlpha }} +#usedports {{ $usedports }} + +{{- /* How many nodeports per service do we want to create, except for the main service which is always two */}} +{{ $numberofPortsPerNodeService := 2 }} + +{{- /* for every nodeport we want, loop though the used ports to get an unused port */}} +{{- range $j := until (int (add (mul (int .Values.replica.replicaCount) $numberofPortsPerNodeService) 2)) }} + {{- /* #j={{ $j }} */}} + {{- $nodeport := (add $j 30000) }} + {{- $nodeportfound := false }} + {{- range $i := $usedports }} + {{- /* #i={{ $i }} + #nodeport={{ $nodeport }} + #usedports={{ $usedports }} */}} + {{- if and (has (toString $nodeport) $usedports) (eq $nodeportfound false) }} + {{- /* nodeport conflicts with in use */}} + {{- $nodeport = (add $nodeport 1) }} + {{- else if and ( has $nodeport $chosenports) (eq $nodeportfound false) }} + {{- /* nodeport already chosen, try another */}} + {{- $nodeport = (add $nodeport 1) }} + {{- else if (eq $nodeportfound false) }} + {{- /* nodeport free to use: not already claimed and not in use */}} + {{- /* select nodeport, and place into usedports */}} + {{- $chosenports = (append $chosenports $nodeport) }} + {{- $nodeportfound = true }} + {{- else }} + {{- /* nodeport has already been chosen and locked in, just work through the rest of the list to get to the next nodeport selection */}} + {{- end }} + {{- end }} + {{- if (eq $nodeportfound false) }} + {{- $chosenports = (append $chosenports $nodeport) }} + {{- end }} + +{{- end }} + +{{- /* print the usedports and chosenports for debugging */}} +#usedports {{ $usedports }} +#chosenports {{ $chosenports }}}} + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "common.names.fullname" . }}-ports-configmap + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: +{{ $portsmap := (lookup "v1" "ConfigMap" (include "common.names.namespace" .) (printf "%s-%s" ( include "common.names.fullname" . ) "ports-configmap")).data }} +{{- if $portsmap }} +{{- /* configmap already exists, do not install again */ -}} + {{- range $name, $value := $portsmap }} + "{{ $name }}": "{{ $value }}" + {{- end }} +{{- else }} +{{- /* configmap being set for first time */ -}} + {{- range $index, $port := $chosenports }} + {{- $nodenumber := (floor (div $index 2)) }} + {{- if (eq $index 0) }} + "{{ template "common.names.fullname" $ }}-sentinel": "{{ $port }}" + {{- else if (eq $index 1) }} + "{{ template "common.names.fullname" $ }}-redis": "{{ $port }}" + {{- else if (eq (mod $index 2) 0) }} + "{{ template "common.names.fullname" $ }}-node-{{ (sub $nodenumber 1) }}-sentinel": "{{ $port }}" + {{- else if (eq (mod $index 2) 1) }} + "{{ template "common.names.fullname" $ }}-node-{{ (sub $nodenumber 1) }}-redis": "{{ $port }}" + {{- end }} + {{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/redis/templates/sentinel/service.yaml b/backing-services/redis/templates/sentinel/service.yaml new file mode 100644 index 0000000..f80e644 --- /dev/null +++ b/backing-services/redis/templates/sentinel/service.yaml @@ -0,0 +1,104 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if or .Release.IsUpgrade (ne .Values.sentinel.service.type "NodePort") .Values.sentinel.service.nodePorts.redis -}} +{{- if and (eq .Values.architecture "replication") .Values.sentinel.enabled }} +{{ $portsmap := (lookup "v1" "ConfigMap" (include "common.names.namespace" .) (printf "%s-%s" ( include "common.names.fullname" . ) "ports-configmap")).data }} + +{{ $sentinelport := 0}} +{{ $redisport := 0}} +{{- if $portsmap }} +{{ $sentinelport = index $portsmap (printf "%s-%s" (include "common.names.fullname" $) "sentinel") }} +{{ $redisport = index $portsmap (printf "%s-%s" (include "common.names.fullname" $) "redis") }} +{{- else }} +{{- end }} + +apiVersion: v1 +kind: Service +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: node + {{- if or .Values.sentinel.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.sentinel.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.sentinel.service.type }} + {{- if or (eq .Values.sentinel.service.type "LoadBalancer") (eq .Values.sentinel.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.sentinel.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.sentinel.service.type "LoadBalancer") (not (empty .Values.sentinel.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.sentinel.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.sentinel.service.type "LoadBalancer") .Values.sentinel.service.loadBalancerClass }} + loadBalancerClass: {{ .Values.sentinel.service.loadBalancerClass }} + {{- end }} + {{- if and (eq .Values.sentinel.service.type "LoadBalancer") (not (empty .Values.sentinel.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ toYaml .Values.sentinel.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + {{- if and .Values.sentinel.service.clusterIP (eq .Values.sentinel.service.type "ClusterIP") }} + clusterIP: {{ .Values.sentinel.service.clusterIP }} + {{- end }} + {{- if .Values.sentinel.service.sessionAffinity }} + sessionAffinity: {{ .Values.sentinel.service.sessionAffinity }} + {{- end }} + {{- if .Values.sentinel.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + ports: + - name: tcp-redis + {{- if and (or (eq .Values.sentinel.service.type "NodePort") (eq .Values.sentinel.service.type "LoadBalancer")) .Values.sentinel.service.nodePorts.redis }} + port: {{ .Values.sentinel.service.nodePorts.redis }} + {{- else if eq .Values.sentinel.service.type "NodePort" }} + port: {{ $redisport }} + {{- else}} + port: {{ .Values.sentinel.service.ports.redis }} + {{- end }} + targetPort: {{ .Values.replica.containerPorts.redis }} + {{- if and (or (eq .Values.sentinel.service.type "NodePort") (eq .Values.sentinel.service.type "LoadBalancer")) .Values.sentinel.service.nodePorts.redis }} + nodePort: {{ .Values.sentinel.service.nodePorts.redis }} + {{- else if eq .Values.sentinel.service.type "ClusterIP" }} + nodePort: null + {{- else if eq .Values.sentinel.service.type "NodePort" }} + nodePort: {{ $redisport }} + {{- end }} + - name: tcp-sentinel + {{- if and (or (eq .Values.sentinel.service.type "NodePort") (eq .Values.sentinel.service.type "LoadBalancer")) .Values.sentinel.service.nodePorts.sentinel }} + port: {{ .Values.sentinel.service.nodePorts.sentinel }} + {{- else if eq .Values.sentinel.service.type "NodePort" }} + port: {{ $sentinelport }} + {{- else }} + port: {{ .Values.sentinel.service.ports.sentinel }} + {{- end }} + targetPort: {{ .Values.sentinel.containerPorts.sentinel }} + {{- if and (or (eq .Values.sentinel.service.type "NodePort") (eq .Values.sentinel.service.type "LoadBalancer")) .Values.sentinel.service.nodePorts.sentinel }} + nodePort: {{ .Values.sentinel.service.nodePorts.sentinel }} + {{- else if eq .Values.sentinel.service.type "ClusterIP" }} + nodePort: null + {{- else if eq .Values.sentinel.service.type "NodePort" }} + nodePort: {{ $sentinelport }} + {{- end }} + {{- if eq .Values.sentinel.service.type "NodePort" }} + - name: sentinel-internal + nodePort: null + port: {{ .Values.sentinel.containerPorts.sentinel }} + protocol: TCP + targetPort: {{ .Values.sentinel.containerPorts.sentinel }} + - name: redis-internal + nodePort: null + port: {{ .Values.replica.containerPorts.redis }} + protocol: TCP + targetPort: {{ .Values.replica.containerPorts.redis }} + {{- end }} + {{- if .Values.sentinel.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.replica.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: node +{{- end }} +{{- end }} diff --git a/backing-services/redis/templates/sentinel/statefulset.yaml b/backing-services/redis/templates/sentinel/statefulset.yaml new file mode 100644 index 0000000..5b28f8c --- /dev/null +++ b/backing-services/redis/templates/sentinel/statefulset.yaml @@ -0,0 +1,785 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if or .Release.IsUpgrade (ne .Values.sentinel.service.type "NodePort") .Values.sentinel.service.nodePorts.redis -}} +{{- if and (eq .Values.architecture "replication") .Values.sentinel.enabled }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ printf "%s-node" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: node + {{- if or .Values.commonAnnotations .Values.sentinel.annotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.sentinel.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.replica.replicaCount }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.replica.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: node + serviceName: {{ printf "%s-headless" (include "common.names.fullname" .) }} + {{- if .Values.replica.updateStrategy }} + updateStrategy: {{- toYaml .Values.replica.updateStrategy | nindent 4 }} + {{- end }} + {{- if and .Values.replica.minReadySeconds (semverCompare ">= 1.23-0" (include "common.capabilities.kubeVersion" .)) }} + minReadySeconds: {{ .Values.replica.minReadySeconds }} + {{- end }} + {{- if .Values.replica.podManagementPolicy }} + podManagementPolicy: {{ .Values.replica.podManagementPolicy | quote }} + {{- end }} + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: node + {{- if and .Values.metrics.enabled .Values.metrics.podLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.podLabels "context" $ ) | nindent 8 }} + {{- end }} + annotations: + {{- if (include "redis.createConfigmap" .) }} + checksum/configmap: {{ pick ( include (print $.Template.BasePath "/configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + {{- end }} + checksum/health: {{ pick ( include (print $.Template.BasePath "/health-configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + checksum/scripts: {{ pick ( include (print $.Template.BasePath "/scripts-configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + checksum/secret: {{ pick ( include (print $.Template.BasePath "/secret.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + {{- if .Values.replica.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.podAnnotations "context" $ ) | nindent 8 }} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.podAnnotations "context" $ ) | nindent 8 }} + {{- end }} + spec: + {{- include "redis.imagePullSecrets" . | nindent 6 }} + {{- if .Values.replica.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.replica.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.podSecurityContext.enabled }} + securityContext: {{- omit .Values.replica.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} + serviceAccountName: {{ template "redis.serviceAccountName" . }} + {{- if .Values.replica.priorityClassName }} + priorityClassName: {{ .Values.replica.priorityClassName | quote }} + {{- end }} + {{- if .Values.replica.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.replica.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.replica.podAffinityPreset "component" "node" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.replica.podAntiAffinityPreset "component" "node" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.replica.nodeAffinityPreset.type "key" .Values.replica.nodeAffinityPreset.key "values" .Values.replica.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.replica.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.replica.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.replica.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.replica.topologySpreadConstraints "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.shareProcessNamespace }} + shareProcessNamespace: {{ .Values.replica.shareProcessNamespace }} + {{- end }} + {{- if .Values.replica.schedulerName }} + schedulerName: {{ .Values.replica.schedulerName | quote }} + {{- end }} + {{- if .Values.replica.dnsPolicy }} + dnsPolicy: {{ .Values.replica.dnsPolicy }} + {{- end }} + {{- if .Values.replica.dnsConfig }} + dnsConfig: {{- include "common.tplvalues.render" (dict "value" .Values.replica.dnsConfig "context" $) | nindent 8 }} + {{- end }} + enableServiceLinks: {{ .Values.sentinel.enableServiceLinks }} + terminationGracePeriodSeconds: {{ .Values.sentinel.terminationGracePeriodSeconds }} + containers: + - name: redis + image: {{ template "redis.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.replica.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.replica.lifecycleHooks "context" $) | nindent 12 }} + {{- else }} + lifecycle: + preStop: + exec: + command: + - /bin/bash + - -c + - /opt/bitnami/scripts/start-scripts/prestop-redis.sh + {{- end }} + {{- end }} + {{- if .Values.replica.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.replica.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.replica.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.replica.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.replica.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.replica.args "context" $) | nindent 12 }} + {{- else }} + args: + - -c + - /opt/bitnami/scripts/start-scripts/start-node.sh + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + - name: REDIS_MASTER_PORT_NUMBER + value: {{ .Values.replica.containerPorts.redis | quote }} + - name: ALLOW_EMPTY_PASSWORD + value: {{ ternary "no" "yes" .Values.auth.enabled | quote }} + {{- if .Values.auth.enabled }} + {{- if .Values.auth.usePasswordFiles }} + - name: REDIS_PASSWORD_FILE + value: "/opt/bitnami/redis/secrets/redis-password" + - name: REDIS_MASTER_PASSWORD_FILE + value: "/opt/bitnami/redis/secrets/redis-password" + {{- else }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "redis.secretName" . }} + key: {{ template "redis.secretPasswordKey" . }} + - name: REDIS_MASTER_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "redis.secretName" . }} + key: {{ template "redis.secretPasswordKey" . }} + {{- end }} + {{- end }} + - name: REDIS_TLS_ENABLED + value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} + {{- if .Values.tls.enabled }} + - name: REDIS_TLS_PORT + value: {{ .Values.replica.containerPorts.redis | quote }} + - name: REDIS_TLS_AUTH_CLIENTS + value: {{ ternary "yes" "no" .Values.tls.authClients | quote }} + - name: REDIS_TLS_CERT_FILE + value: {{ template "redis.tlsCert" . }} + - name: REDIS_TLS_KEY_FILE + value: {{ template "redis.tlsCertKey" . }} + - name: REDIS_TLS_CA_FILE + value: {{ template "redis.tlsCACert" . }} + {{- if .Values.tls.dhParamsFilename }} + - name: REDIS_TLS_DH_PARAMS_FILE + value: {{ template "redis.tlsDHParams" . }} + {{- end }} + {{- else }} + - name: REDIS_PORT + value: {{ .Values.replica.containerPorts.redis | quote }} + {{- end }} + - name: REDIS_SENTINEL_TLS_ENABLED + value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} + {{- if .Values.tls.enabled }} + - name: REDIS_SENTINEL_TLS_PORT_NUMBER + value: {{ .Values.sentinel.containerPorts.sentinel | quote }} + - name: REDIS_SENTINEL_TLS_AUTH_CLIENTS + value: {{ ternary "yes" "no" .Values.tls.authClients | quote }} + - name: REDIS_SENTINEL_TLS_CERT_FILE + value: {{ template "redis.tlsCert" . }} + - name: REDIS_SENTINEL_TLS_KEY_FILE + value: {{ template "redis.tlsCertKey" . }} + - name: REDIS_SENTINEL_TLS_CA_FILE + value: {{ template "redis.tlsCACert" . }} + {{- if .Values.tls.dhParamsFilename }} + - name: REDIS_SENTINEL_TLS_DH_PARAMS_FILE + value: {{ template "redis.tlsDHParams" . }} + {{- end }} + {{- else }} + - name: REDIS_SENTINEL_PORT + value: {{ .Values.sentinel.containerPorts.sentinel | quote }} + {{- end }} + - name: REDIS_DATA_DIR + value: {{ .Values.replica.persistence.path }} + {{- if .Values.replica.externalMaster.enabled }} + - name: REDIS_EXTERNAL_MASTER_HOST + value: {{ .Values.replica.externalMaster.host | quote }} + - name: REDIS_EXTERNAL_MASTER_PORT + value: {{ .Values.replica.externalMaster.port | quote }} + {{- end }} + {{- if .Values.replica.extraEnvVars }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.extraEnvVars "context" $ ) | nindent 12 }} + {{- end }} + {{- if or .Values.replica.extraEnvVarsCM .Values.replica.extraEnvVarsSecret }} + envFrom: + {{- if .Values.replica.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.replica.extraEnvVarsCM }} + {{- end }} + {{- if .Values.replica.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.replica.extraEnvVarsSecret }} + {{- end }} + {{- end }} + ports: + - name: redis + containerPort: {{ .Values.replica.containerPorts.redis }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.replica.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.replica.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.replica.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.replica.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - sh + - -c + - /health/ping_liveness_local.sh {{ .Values.replica.livenessProbe.timeoutSeconds }} + {{- end }} + {{- if .Values.replica.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.replica.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.replica.livenessProbe.enabled }} + livenessProbe: + initialDelaySeconds: {{ .Values.replica.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.replica.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.replica.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.replica.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.replica.livenessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_liveness_local.sh {{ .Values.replica.livenessProbe.timeoutSeconds }} + {{- end }} + {{- if .Values.replica.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.replica.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.replica.readinessProbe.enabled }} + readinessProbe: + initialDelaySeconds: {{ .Values.replica.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.replica.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.replica.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.replica.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.replica.readinessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_readiness_local.sh {{ .Values.replica.readinessProbe.timeoutSeconds }} + {{- end }} + {{- end }} + {{- if .Values.replica.resources }} + resources: {{- toYaml .Values.replica.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: start-scripts + mountPath: /opt/bitnami/scripts/start-scripts + - name: health + mountPath: /health + {{- if .Values.sentinel.persistence.enabled }} + - name: sentinel-data + mountPath: /opt/bitnami/redis-sentinel/etc + {{- end }} + {{- if .Values.auth.usePasswordFiles }} + - name: redis-password + mountPath: /opt/bitnami/redis/secrets/ + {{- end }} + - name: redis-data + mountPath: {{ .Values.replica.persistence.path }} + {{- if .Values.replica.persistence.subPath }} + subPath: {{ .Values.replica.persistence.subPath }} + {{- else if .Values.replica.persistence.subPathExpr }} + subPathExpr: {{ .Values.replica.persistence.subPathExpr }} + {{- end }} + - name: config + mountPath: /opt/bitnami/redis/mounted-etc + - name: redis-tmp-conf + mountPath: /opt/bitnami/redis/etc + - name: tmp + mountPath: /tmp + {{- if .Values.tls.enabled }} + - name: redis-certificates + mountPath: /opt/bitnami/redis/certs + readOnly: true + {{- end }} + {{- if .Values.replica.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + - name: sentinel + image: {{ template "redis.sentinel.image" . }} + imagePullPolicy: {{ .Values.sentinel.image.pullPolicy | quote }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.sentinel.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.lifecycleHooks "context" $) | nindent 12 }} + {{- else }} + lifecycle: + preStop: + exec: + command: + - /bin/bash + - -c + - /opt/bitnami/scripts/start-scripts/prestop-sentinel.sh + {{- end }} + {{- end }} + {{- if .Values.sentinel.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.sentinel.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.sentinel.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.sentinel.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.args "context" $) | nindent 12 }} + {{- else }} + args: + - -c + - /opt/bitnami/scripts/start-scripts/start-sentinel.sh + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.sentinel.image.debug .Values.diagnosticMode.enabled) | quote }} + {{- if .Values.auth.enabled }} + {{- if .Values.auth.usePasswordFiles }} + - name: REDIS_PASSWORD_FILE + value: "/opt/bitnami/redis/secrets/redis-password" + {{- else }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "redis.secretName" . }} + key: {{ template "redis.secretPasswordKey" . }} + {{- end }} + {{- else }} + - name: ALLOW_EMPTY_PASSWORD + value: "yes" + {{- end }} + - name: REDIS_SENTINEL_TLS_ENABLED + value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} + {{- if .Values.tls.enabled }} + - name: REDIS_SENTINEL_TLS_PORT_NUMBER + value: {{ .Values.sentinel.containerPorts.sentinel | quote }} + - name: REDIS_SENTINEL_TLS_AUTH_CLIENTS + value: {{ ternary "yes" "no" .Values.tls.authClients | quote }} + - name: REDIS_SENTINEL_TLS_CERT_FILE + value: {{ template "redis.tlsCert" . }} + - name: REDIS_SENTINEL_TLS_KEY_FILE + value: {{ template "redis.tlsCertKey" . }} + - name: REDIS_SENTINEL_TLS_CA_FILE + value: {{ template "redis.tlsCACert" . }} + {{- if .Values.tls.dhParamsFilename }} + - name: REDIS_SENTINEL_TLS_DH_PARAMS_FILE + value: {{ template "redis.tlsDHParams" . }} + {{- end }} + {{- else }} + - name: REDIS_SENTINEL_PORT + value: {{ .Values.sentinel.containerPorts.sentinel | quote }} + {{- end }} + {{- if .Values.sentinel.externalMaster.enabled }} + - name: REDIS_EXTERNAL_MASTER_HOST + value: {{ .Values.sentinel.externalMaster.host | quote }} + - name: REDIS_EXTERNAL_MASTER_PORT + value: {{ .Values.sentinel.externalMaster.port | quote }} + {{- end }} + {{- if .Values.sentinel.extraEnvVars }} + {{- include "common.tplvalues.render" ( dict "value" .Values.sentinel.extraEnvVars "context" $ ) | nindent 12 }} + {{- end }} + {{- if or .Values.sentinel.extraEnvVarsCM .Values.sentinel.extraEnvVarsSecret }} + envFrom: + {{- if .Values.sentinel.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.sentinel.extraEnvVarsCM }} + {{- end }} + {{- if .Values.sentinel.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.sentinel.extraEnvVarsSecret }} + {{- end }} + {{- end }} + ports: + - name: redis-sentinel + containerPort: {{ .Values.sentinel.containerPorts.sentinel }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.sentinel.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.sentinel.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.sentinel.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - sh + - -c + - /health/ping_sentinel.sh {{ .Values.sentinel.livenessProbe.timeoutSeconds }} + {{- end }} + {{- if .Values.sentinel.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.sentinel.livenessProbe.enabled }} + livenessProbe: + initialDelaySeconds: {{ .Values.sentinel.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.sentinel.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.sentinel.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.sentinel.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.sentinel.livenessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_sentinel.sh {{ .Values.sentinel.livenessProbe.timeoutSeconds }} + {{- end }} + {{- end }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.sentinel.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.sentinel.readinessProbe.enabled }} + readinessProbe: + initialDelaySeconds: {{ .Values.sentinel.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.sentinel.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.sentinel.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.sentinel.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.sentinel.readinessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_sentinel.sh {{ .Values.sentinel.readinessProbe.timeoutSeconds }} + {{- end }} + {{- end }} + {{- if .Values.sentinel.resources }} + resources: {{- toYaml .Values.sentinel.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: start-scripts + mountPath: /opt/bitnami/scripts/start-scripts + - name: health + mountPath: /health + - name: sentinel-data + mountPath: /opt/bitnami/redis-sentinel/etc + {{- if .Values.auth.usePasswordFiles }} + - name: redis-password + mountPath: /opt/bitnami/redis/secrets/ + {{- end }} + - name: redis-data + mountPath: {{ .Values.replica.persistence.path }} + {{- if .Values.replica.persistence.subPath }} + subPath: {{ .Values.replica.persistence.subPath }} + {{- else if .Values.replica.persistence.subPathExpr }} + subPathExpr: {{ .Values.replica.persistence.subPathExpr }} + {{- end }} + - name: config + mountPath: /opt/bitnami/redis-sentinel/mounted-etc + {{- if .Values.tls.enabled }} + - name: redis-certificates + mountPath: /opt/bitnami/redis/certs + readOnly: true + {{- end }} + {{- if .Values.sentinel.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.sentinel.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ template "redis.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.metrics.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.metrics.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -c + - | + if [[ -f '/secrets/redis-password' ]]; then + export REDIS_PASSWORD=$(cat /secrets/redis-password) + fi + redis_exporter{{- range $key, $value := .Values.metrics.extraArgs }} --{{ $key }}={{ $value }}{{- end }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- end }} + env: + - name: REDIS_ALIAS + value: {{ template "common.names.fullname" . }} + {{- if .Values.auth.enabled }} + - name: REDIS_USER + value: default + {{- if (not .Values.auth.usePasswordFiles) }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "redis.secretName" . }} + key: {{ template "redis.secretPasswordKey" . }} + {{- end }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: REDIS_ADDR + value: rediss://{{ .Values.metrics.redisTargetHost }}:{{ .Values.replica.containerPorts.redis }} + {{- if .Values.tls.authClients }} + - name: REDIS_EXPORTER_TLS_CLIENT_KEY_FILE + value: {{ template "redis.tlsCertKey" . }} + - name: REDIS_EXPORTER_TLS_CLIENT_CERT_FILE + value: {{ template "redis.tlsCert" . }} + {{- end }} + - name: REDIS_EXPORTER_TLS_CA_CERT_FILE + value: {{ template "redis.tlsCACert" . }} + {{- end }} + {{- if .Values.metrics.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + ports: + - name: metrics + containerPort: 9121 + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- end }} + volumeMounts: + {{- if .Values.auth.usePasswordFiles }} + - name: redis-password + mountPath: /secrets/ + {{- end }} + {{- if .Values.tls.enabled }} + - name: redis-certificates + mountPath: /opt/bitnami/redis/certs + readOnly: true + {{- end }} + {{- if .Values.metrics.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.replica.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.sidecars "context" $) | nindent 8 }} + {{- end }} + {{- $needsVolumePermissions := and .Values.volumePermissions.enabled .Values.replica.persistence.enabled .Values.replica.podSecurityContext.enabled .Values.replica.containerSecurityContext.enabled }} + {{- if or .Values.replica.initContainers $needsVolumePermissions .Values.sysctl.enabled }} + initContainers: + {{- if .Values.replica.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if $needsVolumePermissions }} + - name: volume-permissions + image: {{ include "redis.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + - -ec + - | + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + chown -R `id -u`:`id -G | cut -d " " -f2` {{ .Values.replica.persistence.path }} + {{- else }} + chown -R {{ .Values.replica.containerSecurityContext.runAsUser }}:{{ .Values.replica.podSecurityContext.fsGroup }} {{ .Values.replica.persistence.path }} + {{- end }} + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.containerSecurityContext "runAsUser" | toYaml | nindent 12 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.containerSecurityContext | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: redis-data + mountPath: {{ .Values.replica.persistence.path }} + {{- if .Values.replica.persistence.subPath }} + subPath: {{ .Values.replica.persistence.subPath }} + {{- else if .Values.replica.persistence.subPathExpr }} + subPathExpr: {{ .Values.replica.persistence.subPathExpr }} + {{- end }} + {{- end }} + {{- if .Values.sysctl.enabled }} + - name: init-sysctl + image: {{ include "redis.sysctl.image" . }} + imagePullPolicy: {{ default "" .Values.sysctl.image.pullPolicy | quote }} + securityContext: + privileged: true + runAsUser: 0 + {{- if .Values.sysctl.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.sysctl.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.sysctl.resources }} + resources: {{- toYaml .Values.sysctl.resources | nindent 12 }} + {{- end }} + {{- if .Values.sysctl.mountHostSys }} + volumeMounts: + - name: host-sys + mountPath: /host-sys + {{- end }} + {{- end }} + {{- end }} + volumes: + - name: start-scripts + configMap: + name: {{ printf "%s-scripts" (include "common.names.fullname" .) }} + defaultMode: 0755 + - name: health + configMap: + name: {{ printf "%s-health" (include "common.names.fullname" .) }} + defaultMode: 0755 + {{- if .Values.auth.usePasswordFiles }} + - name: redis-password + secret: + secretName: {{ template "redis.secretName" . }} + items: + - key: {{ template "redis.secretPasswordKey" . }} + path: redis-password + {{- end }} + - name: config + configMap: + name: {{ include "redis.configmapName" . }} + {{- if .Values.sysctl.mountHostSys }} + - name: host-sys + hostPath: + path: /sys + {{- end }} + {{- if not .Values.sentinel.persistence.enabled }} + - name: sentinel-data + {{- if or .Values.sentinel.persistence.medium .Values.sentinel.persistence.sizeLimit }} + emptyDir: + {{- if .Values.sentinel.persistence.medium }} + medium: {{ .Values.sentinel.persistence.medium | quote }} + {{- end }} + {{- if .Values.sentinel.persistence.sizeLimit }} + sizeLimit: {{ .Values.sentinel.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- end }} + - name: redis-tmp-conf + {{- if or .Values.sentinel.persistence.medium .Values.sentinel.persistence.sizeLimit }} + emptyDir: + {{- if .Values.sentinel.persistence.medium }} + medium: {{ .Values.sentinel.persistence.medium | quote }} + {{- end }} + {{- if .Values.sentinel.persistence.sizeLimit }} + sizeLimit: {{ .Values.sentinel.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + - name: tmp + {{- if or .Values.sentinel.persistence.medium .Values.sentinel.persistence.sizeLimit }} + emptyDir: + {{- if .Values.sentinel.persistence.medium }} + medium: {{ .Values.sentinel.persistence.medium | quote }} + {{- end }} + {{- if .Values.sentinel.persistence.sizeLimit }} + sizeLimit: {{ .Values.sentinel.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- if .Values.replica.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if .Values.metrics.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if .Values.sentinel.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.sentinel.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: redis-certificates + secret: + secretName: {{ include "redis.tlsSecretName" . }} + defaultMode: 256 + {{- end }} + {{- if not .Values.replica.persistence.enabled }} + - name: redis-data + {{- if or .Values.replica.persistence.medium .Values.replica.persistence.sizeLimit }} + emptyDir: + {{- if .Values.replica.persistence.medium }} + medium: {{ .Values.replica.persistence.medium | quote }} + {{- end }} + {{- if .Values.replica.persistence.sizeLimit }} + sizeLimit: {{ .Values.replica.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- else if .Values.replica.persistence.existingClaim }} + - name: redis-data + persistentVolumeClaim: + claimName: {{ printf "%s" (tpl .Values.replica.persistence.existingClaim .) }} + {{- else }} + {{- if .Values.sentinel.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.sentinel.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.sentinel.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: redis-data + labels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 10 }} + app.kubernetes.io/component: node + {{- if .Values.replica.persistence.annotations }} + annotations: {{- toYaml .Values.replica.persistence.annotations | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.replica.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.replica.persistence.size | quote }} + {{- if .Values.replica.persistence.selector }} + selector: {{- include "common.tplvalues.render" ( dict "value" .Values.replica.persistence.selector "context" $) | nindent 10 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" .Values.replica.persistence "global" .Values.global) | nindent 8 }} + {{- if .Values.sentinel.persistence.enabled }} + - metadata: + name: sentinel-data + {{- $claimLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.sentinel.persistence.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.matchLabels" ( dict "customLabels" $claimLabels "context" $ ) | nindent 10 }} + app.kubernetes.io/component: node + {{- if .Values.sentinel.persistence.annotations }} + annotations: {{- toYaml .Values.sentinel.persistence.annotations | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.sentinel.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.sentinel.persistence.size | quote }} + {{- if .Values.sentinel.persistence.selector }} + selector: {{- include "common.tplvalues.render" ( dict "value" .Values.sentinel.persistence.selector "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.sentinel.persistence.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.persistence.dataSource "context" $) | nindent 10 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" .Values.sentinel.persistence "global" .Values.global) | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/redis/templates/serviceaccount.yaml b/backing-services/redis/templates/serviceaccount.yaml new file mode 100644 index 0000000..95432dd --- /dev/null +++ b/backing-services/redis/templates/serviceaccount.yaml @@ -0,0 +1,18 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.serviceAccount.create (and (not .Values.master.serviceAccount.create) (not .Values.replica.serviceAccount.create)) }} +apiVersion: v1 +kind: ServiceAccount +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +metadata: + name: {{ template "redis.serviceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.commonAnnotations .Values.serviceAccount.annotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backing-services/redis/templates/servicemonitor.yaml b/backing-services/redis/templates/servicemonitor.yaml new file mode 100644 index 0000000..8641ea1 --- /dev/null +++ b/backing-services/redis/templates/servicemonitor.yaml @@ -0,0 +1,52 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ default (include "common.names.namespace" .) .Values.metrics.serviceMonitor.namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.metrics.serviceMonitor.additionalLabels }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.serviceMonitor.additionalLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 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 }} + {{- if .Values.metrics.serviceMonitor.honorLabels }} + honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.relabellings }} + relabelings: {{- toYaml .Values.metrics.serviceMonitor.relabellings | nindent 6 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: {{- toYaml .Values.metrics.serviceMonitor.metricRelabelings | nindent 6 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.podTargetLabels }} + podTargetLabels: {{- toYaml .Values.metrics.serviceMonitor.podTargetLabels | nindent 4 }} + {{- end }} + {{ with .Values.metrics.serviceMonitor.sampleLimit }} + sampleLimit: {{ . }} + {{- end }} + {{ with .Values.metrics.serviceMonitor.targetLimit }} + targetLimit: {{ . }} + {{- end }} + namespaceSelector: + matchNames: + - {{ include "common.names.namespace" . | quote }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: metrics +{{- end }} diff --git a/backing-services/redis/templates/tls-secret.yaml b/backing-services/redis/templates/tls-secret.yaml new file mode 100644 index 0000000..8498394 --- /dev/null +++ b/backing-services/redis/templates/tls-secret.yaml @@ -0,0 +1,31 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "redis.createTlsSecret" .) }} +{{- $secretName := printf "%s-crt" (include "common.names.fullname" .) }} +{{- $ca := genCA "redis-ca" 365 }} +{{- $releaseNamespace := (include "common.names.namespace" .) }} +{{- $clusterDomain := .Values.clusterDomain }} +{{- $fullname := include "common.names.fullname" . }} +{{- $serviceName := include "common.names.fullname" . }} +{{- $headlessServiceName := printf "%s-headless" (include "common.names.fullname" .) }} +{{- $masterServiceName := printf "%s-master" (include "common.names.fullname" .) }} +{{- $altNames := list (printf "*.%s.%s.svc.%s" $serviceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $masterServiceName $releaseNamespace $clusterDomain) (printf "*.%s.%s.svc.%s" $masterServiceName $releaseNamespace $clusterDomain) (printf "*.%s.%s.svc.%s" $headlessServiceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $headlessServiceName $releaseNamespace $clusterDomain) "127.0.0.1" "localhost" $fullname }} +{{- $cert := genSignedCert $fullname nil $altNames 365 $ca }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.crt" "defaultValue" $cert.Cert "context" $) }} + tls.key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.key" "defaultValue" $cert.Key "context" $) }} + ca.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }} +{{- end }} diff --git a/backing-services/redis/values.schema.json b/backing-services/redis/values.schema.json new file mode 100644 index 0000000..e9feba6 --- /dev/null +++ b/backing-services/redis/values.schema.json @@ -0,0 +1,163 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "architecture": { + "type": "string", + "title": "Redis architecture", + "form": true, + "description": "Allowed values: `standalone` or `replication`", + "enum": ["standalone", "replication"] + }, + "auth": { + "type": "object", + "title": "Authentication configuration", + "form": true, + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Use password authentication" + }, + "password": { + "type": "string", + "title": "Redis password", + "form": true, + "description": "Defaults to a random 10-character alphanumeric string if not set", + "hidden": { + "value": false, + "path": "auth/enabled" + } + } + } + }, + "master": { + "type": "object", + "title": "Master replicas settings", + "form": true, + "properties": { + "kind": { + "type": "string", + "title": "Workload Kind", + "form": true, + "description": "Allowed values: `Deployment`, `StatefulSet` or `DaemonSet`", + "enum": ["Deployment", "StatefulSet", "DaemonSet"] + }, + "persistence": { + "type": "object", + "title": "Persistence for master replicas", + "form": true, + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable persistence", + "description": "Enable persistence using Persistent Volume Claims" + }, + "size": { + "type": "string", + "title": "Persistent Volume Size", + "form": true, + "render": "slider", + "sliderMin": 1, + "sliderMax": 100, + "sliderUnit": "Gi", + "hidden": { + "value": false, + "path": "master/persistence/enabled" + } + } + } + } + } + }, + "replica": { + "type": "object", + "title": "Redis replicas settings", + "form": true, + "hidden": { + "value": "standalone", + "path": "architecture" + }, + "properties": { + "kind": { + "type": "string", + "title": "Workload Kind", + "form": true, + "description": "Allowed values: `DaemonSet` or `StatefulSet`", + "enum": ["DaemonSet", "StatefulSet"] + }, + "replicaCount": { + "type": "integer", + "form": true, + "title": "Number of Redis replicas" + }, + "persistence": { + "type": "object", + "title": "Persistence for Redis replicas", + "form": true, + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable persistence", + "description": "Enable persistence using Persistent Volume Claims" + }, + "size": { + "type": "string", + "title": "Persistent Volume Size", + "form": true, + "render": "slider", + "sliderMin": 1, + "sliderMax": 100, + "sliderUnit": "Gi", + "hidden": { + "value": false, + "path": "replica/persistence/enabled" + } + } + } + } + } + }, + "volumePermissions": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable Init Containers", + "description": "Use an init container to set required folder permissions on the data volume before mounting it in the final destination" + } + } + }, + "metrics": { + "type": "object", + "form": true, + "title": "Prometheus metrics details", + "properties": { + "enabled": { + "type": "boolean", + "title": "Create Prometheus metrics exporter", + "description": "Create a side-car container to expose Prometheus metrics", + "form": true + }, + "serviceMonitor": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Create Prometheus Operator ServiceMonitor", + "description": "Create a ServiceMonitor to track metrics using Prometheus Operator", + "form": true, + "hidden": { + "value": false, + "path": "metrics/enabled" + } + } + } + } + } + } + } +} diff --git a/backing-services/redis/values.yaml b/backing-services/redis/values.yaml new file mode 100644 index 0000000..75d788a --- /dev/null +++ b/backing-services/redis/values.yaml @@ -0,0 +1,1958 @@ +# Copyright VMware, Inc. +# SPDX-License-Identifier: APACHE-2.0 + +## @section Global parameters +## 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, imagePullSecrets and storageClass +## + +## @param global.imageRegistry Global Docker image registry +## @param global.imagePullSecrets Global Docker registry secret names as an array +## @param global.storageClass Global StorageClass for Persistent Volume(s) +## @param global.redis.password Global Redis® password (overrides `auth.password`) +## +global: + imageRegistry: "" + ## E.g. + ## imagePullSecrets: + ## - myRegistryKeySecretName + ## + imagePullSecrets: [] + storageClass: "" + redis: + password: "" + +## @section Common parameters +## + +## @param kubeVersion Override Kubernetes version +## +kubeVersion: "" +## @param nameOverride String to partially override common.names.fullname +## +nameOverride: "" +## @param fullnameOverride String to fully override common.names.fullname +## +fullnameOverride: "" +## @param namespaceOverride String to fully override common.names.namespace +## +namespaceOverride: "" +## @param commonLabels Labels to add to all deployed objects +## +commonLabels: {} +## @param commonAnnotations Annotations to add to all deployed objects +## +commonAnnotations: {} +## @param secretAnnotations Annotations to add to secret +## +secretAnnotations: {} +## @param clusterDomain Kubernetes cluster domain name +## +clusterDomain: cluster.local +## @param extraDeploy Array of extra objects to deploy with the release +## +extraDeploy: [] +## @param useHostnames Use hostnames internally when announcing replication. If false, the hostname will be resolved to an IP address +## +useHostnames: true +## @param nameResolutionThreshold Failure threshold for internal hostnames resolution +## +nameResolutionThreshold: 5 +## @param nameResolutionTimeout Timeout seconds between probes for internal hostnames resolution +## +nameResolutionTimeout: 5 + +## Enable diagnostic mode in the deployment +## +diagnosticMode: + ## @param diagnosticMode.enabled Enable diagnostic mode (all probes will be disabled and the command will be overridden) + ## + enabled: false + ## @param diagnosticMode.command Command to override all containers in the deployment + ## + command: + - sleep + ## @param diagnosticMode.args Args to override all containers in the deployment + ## + args: + - infinity + +## @section Redis® Image parameters +## + +## Bitnami Redis® image +## ref: https://hub.docker.com/r/bitnami/redis/tags/ +## @param image.registry [default: REGISTRY_NAME] Redis® image registry +## @param image.repository [default: REPOSITORY_NAME/redis] Redis® image repository +## @skip image.tag Redis® image tag (immutable tags are recommended) +## @param image.digest Redis® image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag +## @param image.pullPolicy Redis® image pull policy +## @param image.pullSecrets Redis® image pull secrets +## @param image.debug Enable image debug mode +## +image: + registry: 172.16.16.1:30516 + repository: bitnami/redis + tag: 7.2.4-debian-11-r0 + digest: "" + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Enable debug mode + ## + debug: false + +## @section Redis® common configuration parameters +## https://github.com/bitnami/containers/tree/main/bitnami/redis#configuration +## + +## @param architecture Redis® architecture. Allowed values: `standalone` or `replication` +## +architecture: replication +## Redis® Authentication parameters +## ref: https://github.com/bitnami/containers/tree/main/bitnami/redis#setting-the-server-password-on-first-run +## +auth: + ## @param auth.enabled Enable password authentication + ## + enabled: false + ## @param auth.sentinel Enable password authentication on sentinels too + ## + sentinel: true + ## @param auth.password Redis® password + ## Defaults to a random 10-character alphanumeric string if not set + ## + password: "" + ## @param auth.existingSecret The name of an existing secret with Redis® credentials + ## NOTE: When it's set, the previous `auth.password` parameter is ignored + ## + existingSecret: "" + ## @param auth.existingSecretPasswordKey Password key to be retrieved from existing secret + ## NOTE: ignored unless `auth.existingSecret` parameter is set + ## + existingSecretPasswordKey: "" + ## @param auth.usePasswordFiles Mount credentials as files instead of using an environment variable + ## + usePasswordFiles: false + +## @param commonConfiguration [string] Common configuration to be added into the ConfigMap +## ref: https://redis.io/topics/config +## +commonConfiguration: |- + # Enable AOF https://redis.io/topics/persistence#append-only-file + appendonly yes + # Disable RDB persistence, AOF persistence already enabled. + save "" +## @param existingConfigmap The name of an existing ConfigMap with your custom configuration for Redis® nodes +## +existingConfigmap: "" + +## @section Redis® master configuration parameters +## + +master: + ## @param master.count Number of Redis® master instances to deploy (experimental, requires additional configuration) + ## + count: 1 + ## @param master.configuration Configuration for Redis® master nodes + ## ref: https://redis.io/topics/config + ## + configuration: "" + ## @param master.disableCommands Array with Redis® commands to disable on master nodes + ## Commands will be completely disabled by renaming each to an empty string. + ## ref: https://redis.io/topics/security#disabling-of-specific-commands + ## + disableCommands: + - FLUSHDB + - FLUSHALL + ## @param master.command Override default container command (useful when using custom images) + ## + command: [] + ## @param master.args Override default container args (useful when using custom images) + ## + args: [] + ## @param master.enableServiceLinks Whether information about services should be injected into pod's environment variable + ## + enableServiceLinks: true + ## @param master.preExecCmds Additional commands to run prior to starting Redis® master + ## + preExecCmds: [] + ## @param master.extraFlags Array with additional command line flags for Redis® master + ## e.g: + ## extraFlags: + ## - "--maxmemory-policy volatile-ttl" + ## - "--repl-backlog-size 1024mb" + ## + extraFlags: [] + ## @param master.extraEnvVars Array with extra environment variables to add to Redis® master nodes + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param master.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for Redis® master nodes + ## + extraEnvVarsCM: "" + ## @param master.extraEnvVarsSecret Name of existing Secret containing extra env vars for Redis® master nodes + ## + extraEnvVarsSecret: "" + ## @param master.containerPorts.redis Container port to open on Redis® master nodes + ## + containerPorts: + redis: 6379 + ## Configure extra options for Redis® containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param master.startupProbe.enabled Enable startupProbe on Redis® master nodes + ## @param master.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param master.startupProbe.periodSeconds Period seconds for startupProbe + ## @param master.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param master.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param master.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param master.livenessProbe.enabled Enable livenessProbe on Redis® master nodes + ## @param master.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param master.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param master.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param master.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param master.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param master.readinessProbe.enabled Enable readinessProbe on Redis® master nodes + ## @param master.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param master.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param master.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param master.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param master.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 5 + ## @param master.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param master.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param master.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## Redis® master resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param master.resources.limits The resources limits for the Redis® master containers + ## @param master.resources.requests The requested resources for the Redis® master containers + ## + resources: + limits: {} + requests: {} + ## Configure Pods Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param master.podSecurityContext.enabled Enabled Redis® master pods' Security Context + ## @param master.podSecurityContext.fsGroup Set Redis® master pod's Security Context fsGroup + ## + podSecurityContext: + enabled: true + fsGroup: 1001 + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param master.containerSecurityContext.enabled Enabled Redis® master containers' Security Context + ## @param master.containerSecurityContext.runAsUser Set Redis® master containers' Security Context runAsUser + ## @param master.containerSecurityContext.runAsGroup Set Redis® master containers' Security Context runAsGroup + ## @param master.containerSecurityContext.runAsNonRoot Set Redis® master containers' Security Context runAsNonRoot + ## @param master.containerSecurityContext.allowPrivilegeEscalation Is it possible to escalate Redis® pod(s) privileges + ## @param master.containerSecurityContext.seccompProfile.type Set Redis® master containers' Security Context seccompProfile + ## @param master.containerSecurityContext.capabilities.drop Set Redis® master containers' Security Context capabilities to drop + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsGroup: 0 + runAsNonRoot: true + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + ## @param master.kind Use either Deployment, StatefulSet (default) or DaemonSet + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/ + ## + kind: StatefulSet + ## @param master.schedulerName Alternate scheduler for Redis® master pods + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param master.updateStrategy.type Redis® master statefulset strategy type + ## @skip master.updateStrategy.rollingUpdate + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## + updateStrategy: + ## StrategyType + ## Can be set to RollingUpdate, OnDelete (statefulset), Recreate (deployment) + ## + type: RollingUpdate + ## @param master.minReadySeconds How many seconds a pod needs to be ready before killing the next, during update + ## + minReadySeconds: 0 + ## @param master.priorityClassName Redis® master pods' priorityClassName + ## + priorityClassName: "" + ## @param master.hostAliases Redis® master pods host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param master.podLabels Extra labels for Redis® master pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param master.podAnnotations Annotations for Redis® master pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param master.shareProcessNamespace Share a single process namespace between all of the containers in Redis® master pods + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/share-process-namespace/ + ## + shareProcessNamespace: false + ## @param master.podAffinityPreset Pod affinity preset. Ignored if `master.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param master.podAntiAffinityPreset Pod anti-affinity preset. Ignored if `master.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Node master.affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param master.nodeAffinityPreset.type Node affinity preset type. Ignored if `master.affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param master.nodeAffinityPreset.key Node label key to match. Ignored if `master.affinity` is set + ## + key: "" + ## @param master.nodeAffinityPreset.values Node label values to match. Ignored if `master.affinity` is set + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param master.affinity Affinity for Redis® master pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## NOTE: `master.podAffinityPreset`, `master.podAntiAffinityPreset`, and `master.nodeAffinityPreset` will be ignored when it's set + ## + affinity: {} + ## @param master.nodeSelector Node labels for Redis® master pods assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + ## @param master.tolerations Tolerations for Redis® master pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param master.topologySpreadConstraints Spread Constraints for Redis® master pod assignment + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## E.g. + ## topologySpreadConstraints: + ## - maxSkew: 1 + ## topologyKey: node + ## whenUnsatisfiable: DoNotSchedule + ## + topologySpreadConstraints: [] + ## @param master.dnsPolicy DNS Policy for Redis® master pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/ + ## E.g. + ## dnsPolicy: ClusterFirst + ## + dnsPolicy: "" + ## @param master.dnsConfig DNS Configuration for Redis® master pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/ + ## E.g. + ## dnsConfig: + ## options: + ## - name: ndots + ## value: "4" + ## - name: single-request-reopen + ## + dnsConfig: {} + ## @param master.lifecycleHooks for the Redis® master container(s) to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param master.extraVolumes Optionally specify extra list of additional volumes for the Redis® master pod(s) + ## + extraVolumes: [] + ## @param master.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the Redis® master container(s) + ## + extraVolumeMounts: [] + ## @param master.sidecars Add additional sidecar containers to the Redis® master pod(s) + ## e.g: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param master.initContainers Add additional init containers to the Redis® master pod(s) + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + ## e.g: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## command: ['sh', '-c', 'echo "hello world"'] + ## + initContainers: [] + ## Persistence parameters + ## ref: https://kubernetes.io/docs/user-guide/persistent-volumes/ + ## + persistence: + ## @param master.persistence.enabled Enable persistence on Redis® master nodes using Persistent Volume Claims + ## + enabled: true + ## @param master.persistence.medium Provide a medium for `emptyDir` volumes. + ## + medium: "" + ## @param master.persistence.sizeLimit Set this to enable a size limit for `emptyDir` volumes. + ## + sizeLimit: "" + ## @param master.persistence.path The path the volume will be mounted at on Redis® master containers + ## NOTE: Useful when using different Redis® images + ## + path: /data + ## @param master.persistence.subPath The subdirectory of the volume to mount on Redis® master containers + ## NOTE: Useful in dev environments + ## + subPath: "" + ## @param master.persistence.subPathExpr Used to construct the subPath subdirectory of the volume to mount on Redis® master containers + ## + subPathExpr: "" + ## @param master.persistence.storageClass 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 + ## + storageClass: "" + ## @param master.persistence.accessModes Persistent Volume access modes + ## + accessModes: + - ReadWriteOnce + ## @param master.persistence.size Persistent Volume size + ## + size: 8Gi + ## @param master.persistence.annotations Additional custom annotations for the PVC + ## + annotations: {} + ## @param master.persistence.labels Additional custom labels for the PVC + ## + labels: {} + ## @param master.persistence.selector Additional labels to match for the PVC + ## e.g: + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## @param master.persistence.dataSource Custom PVC data source + ## + dataSource: {} + ## @param master.persistence.existingClaim Use a existing PVC which must be created manually before bound + ## NOTE: requires master.persistence.enabled: true + ## + existingClaim: "" + ## persistentVolumeClaimRetentionPolicy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention + ## @param master.persistentVolumeClaimRetentionPolicy.enabled Controls if and how PVCs are deleted during the lifecycle of a StatefulSet + ## @param master.persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced + ## @param master.persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted + ## + persistentVolumeClaimRetentionPolicy: + enabled: false + whenScaled: Retain + whenDeleted: Retain + ## Redis® master service parameters + ## + service: + ## @param master.service.type Redis® master service type + ## + type: NodePort + ## @param master.service.ports.redis Redis® master service port + ## + ports: + redis: 6379 + ## @param master.service.nodePorts.redis Node port for Redis® master + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## NOTE: choose port between <30000-32767> + ## + nodePorts: + redis: "" + ## @param master.service.externalTrafficPolicy Redis® master service external traffic policy + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param master.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param master.service.internalTrafficPolicy Redis® master service internal traffic policy (requires Kubernetes v1.22 or greater to be usable) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/ + ## + internalTrafficPolicy: Cluster + ## @param master.service.clusterIP Redis® master service Cluster IP + ## + clusterIP: "" + ## @param master.service.loadBalancerIP Redis® master service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param master.service.loadBalancerClass master service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerClass: "" + ## @param master.service.loadBalancerSourceRanges Redis® master service Load Balancer sources + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g. + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param master.service.externalIPs Redis® master service External IPs + ## https://kubernetes.io/docs/concepts/services-networking/service/#external-ips + ## e.g. + ## externalIPs: + ## - 10.10.10.1 + ## - 201.22.30.1 + ## + externalIPs: [] + ## @param master.service.annotations Additional custom annotations for Redis® master service + ## + annotations: {} + ## @param master.service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param master.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## @param master.terminationGracePeriodSeconds Integer setting the termination grace period for the redis-master pods + ## + terminationGracePeriodSeconds: 30 + ## ServiceAccount configuration + ## + serviceAccount: + ## @param master.serviceAccount.create Specifies whether a ServiceAccount should be created + ## + create: false + ## @param master.serviceAccount.name The name of the ServiceAccount to use. + ## If not set and create is true, a name is generated using the common.names.fullname template + ## + name: "" + ## @param master.serviceAccount.automountServiceAccountToken Whether to auto mount the service account token + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server + ## + automountServiceAccountToken: true + ## @param master.serviceAccount.annotations Additional custom annotations for the ServiceAccount + ## + annotations: {} + +## @section Redis® replicas configuration parameters +## + +replica: + ## @param replica.kind Use either DaemonSet or StatefulSet (default) + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/ + ## + kind: StatefulSet + ## @param replica.replicaCount Number of Redis® replicas to deploy + ## + replicaCount: 1 + ## @param replica.configuration Configuration for Redis® replicas nodes + ## ref: https://redis.io/topics/config + ## + configuration: "" + ## @param replica.disableCommands Array with Redis® commands to disable on replicas nodes + ## Commands will be completely disabled by renaming each to an empty string. + ## ref: https://redis.io/topics/security#disabling-of-specific-commands + ## + disableCommands: + - FLUSHDB + - FLUSHALL + ## @param replica.command Override default container command (useful when using custom images) + ## + command: [] + ## @param replica.args Override default container args (useful when using custom images) + ## + args: [] + ## @param replica.enableServiceLinks Whether information about services should be injected into pod's environment variable + ## + enableServiceLinks: true + ## @param replica.preExecCmds Additional commands to run prior to starting Redis® replicas + ## + preExecCmds: [] + ## @param replica.extraFlags Array with additional command line flags for Redis® replicas + ## e.g: + ## extraFlags: + ## - "--maxmemory-policy volatile-ttl" + ## - "--repl-backlog-size 1024mb" + ## + extraFlags: [] + ## @param replica.extraEnvVars Array with extra environment variables to add to Redis® replicas nodes + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param replica.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for Redis® replicas nodes + ## + extraEnvVarsCM: "" + ## @param replica.extraEnvVarsSecret Name of existing Secret containing extra env vars for Redis® replicas nodes + ## + extraEnvVarsSecret: "" + ## @param replica.externalMaster.enabled Use external master for bootstrapping + ## @param replica.externalMaster.host External master host to bootstrap from + ## @param replica.externalMaster.port Port for Redis service external master host + ## + externalMaster: + enabled: false + host: "" + port: 6379 + ## @param replica.containerPorts.redis Container port to open on Redis® replicas nodes + ## + containerPorts: + redis: 6379 + ## Configure extra options for Redis® containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param replica.startupProbe.enabled Enable startupProbe on Redis® replicas nodes + ## @param replica.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param replica.startupProbe.periodSeconds Period seconds for startupProbe + ## @param replica.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param replica.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param replica.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: true + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 22 + ## @param replica.livenessProbe.enabled Enable livenessProbe on Redis® replicas nodes + ## @param replica.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param replica.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param replica.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param replica.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param replica.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param replica.readinessProbe.enabled Enable readinessProbe on Redis® replicas nodes + ## @param replica.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param replica.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param replica.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param replica.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param replica.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 5 + ## @param replica.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param replica.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param replica.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## Redis® replicas resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param replica.resources.limits The resources limits for the Redis® replicas containers + ## @param replica.resources.requests The requested resources for the Redis® replicas containers + ## + 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: 250m + # memory: 256Mi + requests: {} + # cpu: 250m + # memory: 256Mi + ## Configure Pods Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param replica.podSecurityContext.enabled Enabled Redis® replicas pods' Security Context + ## @param replica.podSecurityContext.fsGroup Set Redis® replicas pod's Security Context fsGroup + ## + podSecurityContext: + enabled: true + fsGroup: 1001 + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param replica.containerSecurityContext.enabled Enabled Redis® replicas containers' Security Context + ## @param replica.containerSecurityContext.runAsUser Set Redis® replicas containers' Security Context runAsUser + ## @param replica.containerSecurityContext.runAsGroup Set Redis® replicas containers' Security Context runAsGroup + ## @param replica.containerSecurityContext.runAsNonRoot Set Redis® replicas containers' Security Context runAsNonRoot + ## @param replica.containerSecurityContext.allowPrivilegeEscalation Set Redis® replicas pod's Security Context allowPrivilegeEscalation + ## @param replica.containerSecurityContext.seccompProfile.type Set Redis® replicas containers' Security Context seccompProfile + ## @param replica.containerSecurityContext.capabilities.drop Set Redis® replicas containers' Security Context capabilities to drop + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsGroup: 0 + runAsNonRoot: true + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + ## @param replica.schedulerName Alternate scheduler for Redis® replicas pods + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param replica.updateStrategy.type Redis® replicas statefulset strategy type + ## @skip replica.updateStrategy.rollingUpdate + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## + updateStrategy: + ## StrategyType + ## Can be set to RollingUpdate, OnDelete (statefulset), Recreate (deployment) + ## + type: RollingUpdate + ## @param replica.minReadySeconds How many seconds a pod needs to be ready before killing the next, during update + ## + minReadySeconds: 0 + ## @param replica.priorityClassName Redis® replicas pods' priorityClassName + ## + priorityClassName: "" + ## @param replica.podManagementPolicy podManagementPolicy to manage scaling operation of %%MAIN_CONTAINER_NAME%% pods + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#pod-management-policies + ## + podManagementPolicy: "" + ## @param replica.hostAliases Redis® replicas pods host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param replica.podLabels Extra labels for Redis® replicas pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param replica.podAnnotations Annotations for Redis® replicas pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param replica.shareProcessNamespace Share a single process namespace between all of the containers in Redis® replicas pods + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/share-process-namespace/ + ## + shareProcessNamespace: false + ## @param replica.podAffinityPreset Pod affinity preset. Ignored if `replica.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param replica.podAntiAffinityPreset Pod anti-affinity preset. Ignored if `replica.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param replica.nodeAffinityPreset.type Node affinity preset type. Ignored if `replica.affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param replica.nodeAffinityPreset.key Node label key to match. Ignored if `replica.affinity` is set + ## + key: "" + ## @param replica.nodeAffinityPreset.values Node label values to match. Ignored if `replica.affinity` is set + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param replica.affinity Affinity for Redis® replicas pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## NOTE: `replica.podAffinityPreset`, `replica.podAntiAffinityPreset`, and `replica.nodeAffinityPreset` will be ignored when it's set + ## + affinity: {} + ## @param replica.nodeSelector Node labels for Redis® replicas pods assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + ## @param replica.tolerations Tolerations for Redis® replicas pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param replica.topologySpreadConstraints Spread Constraints for Redis® replicas pod assignment + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## E.g. + ## topologySpreadConstraints: + ## - maxSkew: 1 + ## topologyKey: node + ## whenUnsatisfiable: DoNotSchedule + ## + topologySpreadConstraints: [] + ## @param replica.dnsPolicy DNS Policy for Redis® replica pods + ## ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/ + ## E.g. + ## dnsPolicy: ClusterFirst + ## + dnsPolicy: "" + ## @param replica.dnsConfig DNS Configuration for Redis® replica pods + ## ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/ + ## E.g. + ## dnsConfig: + ## options: + ## - name: ndots + ## value: "4" + ## - name: single-request-reopen + ## + dnsConfig: {} + ## @param replica.lifecycleHooks for the Redis® replica container(s) to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param replica.extraVolumes Optionally specify extra list of additional volumes for the Redis® replicas pod(s) + ## + extraVolumes: [] + ## @param replica.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the Redis® replicas container(s) + ## + extraVolumeMounts: [] + ## @param replica.sidecars Add additional sidecar containers to the Redis® replicas pod(s) + ## e.g: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param replica.initContainers Add additional init containers to the Redis® replicas pod(s) + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + ## e.g: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## command: ['sh', '-c', 'echo "hello world"'] + ## + initContainers: [] + ## Persistence Parameters + ## ref: https://kubernetes.io/docs/user-guide/persistent-volumes/ + ## + persistence: + ## @param replica.persistence.enabled Enable persistence on Redis® replicas nodes using Persistent Volume Claims + ## + enabled: true + ## @param replica.persistence.medium Provide a medium for `emptyDir` volumes. + ## + medium: "" + ## @param replica.persistence.sizeLimit Set this to enable a size limit for `emptyDir` volumes. + ## + sizeLimit: "" + ## @param replica.persistence.path The path the volume will be mounted at on Redis® replicas containers + ## NOTE: Useful when using different Redis® images + ## + path: /data + ## @param replica.persistence.subPath The subdirectory of the volume to mount on Redis® replicas containers + ## NOTE: Useful in dev environments + ## + subPath: "" + ## @param replica.persistence.subPathExpr Used to construct the subPath subdirectory of the volume to mount on Redis® replicas containers + ## + subPathExpr: "" + ## @param replica.persistence.storageClass 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 + ## + storageClass: "" + ## @param replica.persistence.accessModes Persistent Volume access modes + ## + accessModes: + - ReadWriteOnce + ## @param replica.persistence.size Persistent Volume size + ## + size: 8Gi + ## @param replica.persistence.annotations Additional custom annotations for the PVC + ## + annotations: {} + ## @param replica.persistence.labels Additional custom labels for the PVC + ## + labels: {} + ## @param replica.persistence.selector Additional labels to match for the PVC + ## e.g: + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## @param replica.persistence.dataSource Custom PVC data source + ## + dataSource: {} + ## @param replica.persistence.existingClaim Use a existing PVC which must be created manually before bound + ## NOTE: requires replica.persistence.enabled: true + ## + existingClaim: "" + ## persistentVolumeClaimRetentionPolicy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention + ## @param replica.persistentVolumeClaimRetentionPolicy.enabled Controls if and how PVCs are deleted during the lifecycle of a StatefulSet + ## @param replica.persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced + ## @param replica.persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted + ## + persistentVolumeClaimRetentionPolicy: + enabled: false + whenScaled: Retain + whenDeleted: Retain + ## Redis® replicas service parameters + ## + service: + ## @param replica.service.type Redis® replicas service type + ## + type: ClusterIP + ## @param replica.service.ports.redis Redis® replicas service port + ## + ports: + redis: 6379 + ## @param replica.service.nodePorts.redis Node port for Redis® replicas + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## NOTE: choose port between <30000-32767> + ## + nodePorts: + redis: "" + ## @param replica.service.externalTrafficPolicy Redis® replicas service external traffic policy + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param replica.service.internalTrafficPolicy Redis® replicas service internal traffic policy (requires Kubernetes v1.22 or greater to be usable) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/ + ## + internalTrafficPolicy: Cluster + ## @param replica.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param replica.service.clusterIP Redis® replicas service Cluster IP + ## + clusterIP: "" + ## @param replica.service.loadBalancerIP Redis® replicas service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param replica.service.loadBalancerClass replicas service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerClass: "" + ## @param replica.service.loadBalancerSourceRanges Redis® replicas service Load Balancer sources + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g. + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param replica.service.annotations Additional custom annotations for Redis® replicas service + ## + annotations: {} + ## @param replica.service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param replica.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## @param replica.terminationGracePeriodSeconds Integer setting the termination grace period for the redis-replicas pods + ## + terminationGracePeriodSeconds: 30 + ## Autoscaling configuration + ## + autoscaling: + ## @param replica.autoscaling.enabled Enable replica autoscaling settings + ## + enabled: false + ## @param replica.autoscaling.minReplicas Minimum replicas for the pod autoscaling + ## + minReplicas: 1 + ## @param replica.autoscaling.maxReplicas Maximum replicas for the pod autoscaling + ## + maxReplicas: 11 + ## @param replica.autoscaling.targetCPU Percentage of CPU to consider when autoscaling + ## + targetCPU: "" + ## @param replica.autoscaling.targetMemory Percentage of Memory to consider when autoscaling + ## + targetMemory: "" + ## ServiceAccount configuration + ## + serviceAccount: + ## @param replica.serviceAccount.create Specifies whether a ServiceAccount should be created + ## + create: false + ## @param replica.serviceAccount.name The name of the ServiceAccount to use. + ## If not set and create is true, a name is generated using the common.names.fullname template + ## + name: "" + ## @param replica.serviceAccount.automountServiceAccountToken Whether to auto mount the service account token + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server + ## + automountServiceAccountToken: true + ## @param replica.serviceAccount.annotations Additional custom annotations for the ServiceAccount + ## + annotations: {} +## @section Redis® Sentinel configuration parameters +## + +sentinel: + ## @param sentinel.enabled Use Redis® Sentinel on Redis® pods. + ## IMPORTANT: this will disable the master and replicas services and + ## create a single Redis® service exposing both the Redis and Sentinel ports + ## + enabled: false + ## Bitnami Redis® Sentinel image version + ## ref: https://hub.docker.com/r/bitnami/redis-sentinel/tags/ + ## @param sentinel.image.registry [default: REGISTRY_NAME] Redis® Sentinel image registry + ## @param sentinel.image.repository [default: REPOSITORY_NAME/redis-sentinel] Redis® Sentinel image repository + ## @skip sentinel.image.tag Redis® Sentinel image tag (immutable tags are recommended) + ## @param sentinel.image.digest Redis® Sentinel image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param sentinel.image.pullPolicy Redis® Sentinel image pull policy + ## @param sentinel.image.pullSecrets Redis® Sentinel image pull secrets + ## @param sentinel.image.debug Enable image debug mode + ## + image: + registry: docker.io + repository: bitnami/redis-sentinel + tag: 7.2.4-debian-11-r0 + digest: "" + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Enable debug mode + ## + debug: false + ## @param sentinel.annotations Additional custom annotations for Redis® Sentinel resource + ## + annotations: {} + ## @param sentinel.masterSet Master set name + ## + masterSet: mymaster + ## @param sentinel.quorum Sentinel Quorum + ## + quorum: 2 + ## @param sentinel.getMasterTimeout Amount of time to allow before get_sentinel_master_info() times out. + ## + getMasterTimeout: 90 + ## @param sentinel.automateClusterRecovery Automate cluster recovery in cases where the last replica is not considered a good replica and Sentinel won't automatically failover to it. + ## This also prevents any new replica from starting until the last remaining replica is elected as master to guarantee that it is the one to be elected by Sentinel, and not a newly started replica with no data. + ## NOTE: This feature requires a "downAfterMilliseconds" value less or equal to 2000. + ## + automateClusterRecovery: false + ## @param sentinel.redisShutdownWaitFailover Whether the Redis® master container waits for the failover at shutdown (in addition to the Redis® Sentinel container). + ## + redisShutdownWaitFailover: true + ## Sentinel timing restrictions + ## @param sentinel.downAfterMilliseconds Timeout for detecting a Redis® node is down + ## @param sentinel.failoverTimeout Timeout for performing a election failover + ## + downAfterMilliseconds: 60000 + failoverTimeout: 180000 + ## @param sentinel.parallelSyncs Number of replicas that can be reconfigured in parallel to use the new master after a failover + ## + parallelSyncs: 1 + ## @param sentinel.configuration Configuration for Redis® Sentinel nodes + ## ref: https://redis.io/topics/sentinel + ## + configuration: "" + ## @param sentinel.command Override default container command (useful when using custom images) + ## + command: [] + ## @param sentinel.args Override default container args (useful when using custom images) + ## + args: [] + ## @param sentinel.enableServiceLinks Whether information about services should be injected into pod's environment variable + ## + enableServiceLinks: true + ## @param sentinel.preExecCmds Additional commands to run prior to starting Redis® Sentinel + ## + preExecCmds: [] + ## @param sentinel.extraEnvVars Array with extra environment variables to add to Redis® Sentinel nodes + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param sentinel.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for Redis® Sentinel nodes + ## + extraEnvVarsCM: "" + ## @param sentinel.extraEnvVarsSecret Name of existing Secret containing extra env vars for Redis® Sentinel nodes + ## + extraEnvVarsSecret: "" + ## @param sentinel.externalMaster.enabled Use external master for bootstrapping + ## @param sentinel.externalMaster.host External master host to bootstrap from + ## @param sentinel.externalMaster.port Port for Redis service external master host + ## + externalMaster: + enabled: false + host: "" + port: 6379 + ## @param sentinel.containerPorts.sentinel Container port to open on Redis® Sentinel nodes + ## + containerPorts: + sentinel: 26379 + ## Configure extra options for Redis® containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param sentinel.startupProbe.enabled Enable startupProbe on Redis® Sentinel nodes + ## @param sentinel.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param sentinel.startupProbe.periodSeconds Period seconds for startupProbe + ## @param sentinel.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param sentinel.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param sentinel.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: true + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 22 + ## @param sentinel.livenessProbe.enabled Enable livenessProbe on Redis® Sentinel nodes + ## @param sentinel.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param sentinel.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param sentinel.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param sentinel.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param sentinel.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 6 + ## @param sentinel.readinessProbe.enabled Enable readinessProbe on Redis® Sentinel nodes + ## @param sentinel.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param sentinel.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param sentinel.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param sentinel.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param sentinel.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 6 + ## @param sentinel.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param sentinel.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param sentinel.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## Persistence parameters + ## ref: https://kubernetes.io/docs/user-guide/persistent-volumes/ + ## + persistence: + ## @param sentinel.persistence.enabled Enable persistence on Redis® sentinel nodes using Persistent Volume Claims (Experimental) + ## + enabled: false + ## @param sentinel.persistence.storageClass 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 + ## + storageClass: "" + ## @param sentinel.persistence.accessModes Persistent Volume access modes + ## + accessModes: + - ReadWriteOnce + ## @param sentinel.persistence.size Persistent Volume size + ## + size: 100Mi + ## @param sentinel.persistence.annotations Additional custom annotations for the PVC + ## + annotations: {} + ## @param sentinel.persistence.labels Additional custom labels for the PVC + ## + labels: {} + ## @param sentinel.persistence.selector Additional labels to match for the PVC + ## e.g: + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## @param sentinel.persistence.dataSource Custom PVC data source + ## + dataSource: {} + ## @param sentinel.persistence.medium Provide a medium for `emptyDir` volumes. + ## + medium: "" + ## @param sentinel.persistence.sizeLimit Set this to enable a size limit for `emptyDir` volumes. + ## + sizeLimit: "" + ## persistentVolumeClaimRetentionPolicy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention + ## @param sentinel.persistentVolumeClaimRetentionPolicy.enabled Controls if and how PVCs are deleted during the lifecycle of a StatefulSet + ## @param sentinel.persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced + ## @param sentinel.persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted + ## + persistentVolumeClaimRetentionPolicy: + enabled: false + whenScaled: Retain + whenDeleted: Retain + ## Redis® Sentinel resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param sentinel.resources.limits The resources limits for the Redis® Sentinel containers + ## @param sentinel.resources.requests The requested resources for the Redis® Sentinel containers + ## + resources: + limits: {} + requests: {} + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param sentinel.containerSecurityContext.enabled Enabled Redis® Sentinel containers' Security Context + ## @param sentinel.containerSecurityContext.runAsUser Set Redis® Sentinel containers' Security Context runAsUser + ## @param sentinel.containerSecurityContext.runAsGroup Set Redis® Sentinel containers' Security Context runAsGroup + ## @param sentinel.containerSecurityContext.runAsNonRoot Set Redis® Sentinel containers' Security Context runAsNonRoot + ## @param sentinel.containerSecurityContext.allowPrivilegeEscalation Set Redis® Sentinel containers' Security Context allowPrivilegeEscalation + ## @param sentinel.containerSecurityContext.seccompProfile.type Set Redis® Sentinel containers' Security Context seccompProfile + ## @param sentinel.containerSecurityContext.capabilities.drop Set Redis® Sentinel containers' Security Context capabilities to drop + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsGroup: 0 + runAsNonRoot: true + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + ## @param sentinel.lifecycleHooks for the Redis® sentinel container(s) to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param sentinel.extraVolumes Optionally specify extra list of additional volumes for the Redis® Sentinel + ## + extraVolumes: [] + ## @param sentinel.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the Redis® Sentinel container(s) + ## + extraVolumeMounts: [] + ## Redis® Sentinel service parameters + ## + service: + ## @param sentinel.service.type Redis® Sentinel service type + ## + type: ClusterIP + ## @param sentinel.service.ports.redis Redis® service port for Redis® + ## @param sentinel.service.ports.sentinel Redis® service port for Redis® Sentinel + ## + ports: + redis: 6379 + sentinel: 26379 + ## @param sentinel.service.nodePorts.redis Node port for Redis® + ## @param sentinel.service.nodePorts.sentinel Node port for Sentinel + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## NOTE: choose port between <30000-32767> + ## NOTE: By leaving these values blank, they will be generated by ports-configmap + ## If setting manually, please leave at least replica.replicaCount + 1 in between sentinel.service.nodePorts.redis and sentinel.service.nodePorts.sentinel to take into account the ports that will be created while incrementing that base port + ## + nodePorts: + redis: "" + sentinel: "" + ## @param sentinel.service.externalTrafficPolicy Redis® Sentinel service external traffic policy + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param sentinel.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param sentinel.service.clusterIP Redis® Sentinel service Cluster IP + ## + clusterIP: "" + ## @param sentinel.service.loadBalancerIP Redis® Sentinel service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param sentinel.service.loadBalancerClass sentinel service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerClass: "" + ## @param sentinel.service.loadBalancerSourceRanges Redis® Sentinel service Load Balancer sources + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g. + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param sentinel.service.annotations Additional custom annotations for Redis® Sentinel service + ## + annotations: {} + ## @param sentinel.service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param sentinel.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## Headless service properties + ## + headless: + ## @param sentinel.service.headless.annotations Annotations for the headless service. + ## + annotations: {} + ## @param sentinel.terminationGracePeriodSeconds Integer setting the termination grace period for the redis-node pods + ## + terminationGracePeriodSeconds: 30 + +## @section Other Parameters +## + +## @param serviceBindings.enabled Create secret for service binding (Experimental) +## Ref: https://servicebinding.io/service-provider/ +## +serviceBindings: + enabled: false + +## Network Policy configuration +## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ +## +networkPolicy: + ## @param networkPolicy.enabled Enable creation of NetworkPolicy resources + ## + enabled: false + ## @param networkPolicy.allowExternal Don't require client label for connections + ## When set to false, only pods with the correct client label will have network access to the ports + ## Redis® is listening on. When true, Redis® will accept connections from any source + ## (with the correct destination port). + ## + allowExternal: true + ## @param networkPolicy.extraIngress Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraIngress: + ## - ports: + ## - port: 1234 + ## from: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraIngress: [] + ## @param networkPolicy.extraEgress Add extra egress rules to the NetworkPolicy + ## e.g: + ## extraEgress: + ## - ports: + ## - port: 1234 + ## to: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraEgress: [] + ## @param networkPolicy.ingressNSMatchLabels Labels to match to allow traffic from other namespaces + ## @param networkPolicy.ingressNSPodMatchLabels Pod labels to match to allow traffic from other namespaces + ## + ingressNSMatchLabels: {} + ingressNSPodMatchLabels: {} + + metrics: + ## @param networkPolicy.metrics.allowExternal Don't require client label for connections for metrics endpoint + ## When set to false, only pods with the correct client label will have network access to the metrics port + ## + allowExternal: true + ## @param networkPolicy.metrics.ingressNSMatchLabels Labels to match to allow traffic from other namespaces to metrics endpoint + ## @param networkPolicy.metrics.ingressNSPodMatchLabels Pod labels to match to allow traffic from other namespaces to metrics endpoint + ## + ingressNSMatchLabels: {} + ingressNSPodMatchLabels: {} + +## PodSecurityPolicy configuration +## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ +## +podSecurityPolicy: + ## @param podSecurityPolicy.create Whether to create a PodSecurityPolicy. WARNING: PodSecurityPolicy is deprecated in Kubernetes v1.21 or later, unavailable in v1.25 or later + ## + create: false + ## @param podSecurityPolicy.enabled Enable PodSecurityPolicy's RBAC rules + ## + enabled: false +## RBAC configuration +## +rbac: + ## @param rbac.create Specifies whether RBAC resources should be created + ## + create: false + ## @param rbac.rules Custom RBAC rules to set + ## e.g: + ## rules: + ## - apiGroups: + ## - "" + ## resources: + ## - pods + ## verbs: + ## - get + ## - list + ## + rules: [] +## ServiceAccount configuration +## +serviceAccount: + ## @param serviceAccount.create Specifies whether a ServiceAccount should be created + ## + create: true + ## @param serviceAccount.name The name of the ServiceAccount to use. + ## If not set and create is true, a name is generated using the common.names.fullname template + ## + name: "" + ## @param serviceAccount.automountServiceAccountToken Whether to auto mount the service account token + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server + ## + automountServiceAccountToken: true + ## @param serviceAccount.annotations Additional custom annotations for the ServiceAccount + ## + annotations: {} +## Redis® Pod Disruption Budget configuration +## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ +## +pdb: + ## @param pdb.create Specifies whether a PodDisruptionBudget should be created + ## + create: false + ## @param pdb.minAvailable Min number of pods that must still be available after the eviction + ## + minAvailable: 1 + ## @param pdb.maxUnavailable Max number of pods that can be unavailable after the eviction + ## + maxUnavailable: "" +## TLS configuration +## +tls: + ## @param tls.enabled Enable TLS traffic + ## + enabled: false + ## @param tls.authClients Require clients to authenticate + ## + authClients: true + ## @param tls.autoGenerated Enable autogenerated certificates + ## + autoGenerated: false + ## @param tls.existingSecret The name of the existing secret that contains the TLS certificates + ## + existingSecret: "" + ## @param tls.certificatesSecret DEPRECATED. Use existingSecret instead. + ## + certificatesSecret: "" + ## @param tls.certFilename Certificate filename + ## + certFilename: "" + ## @param tls.certKeyFilename Certificate Key filename + ## + certKeyFilename: "" + ## @param tls.certCAFilename CA Certificate filename + ## + certCAFilename: "" + ## @param tls.dhParamsFilename File containing DH params (in order to support DH based ciphers) + ## + dhParamsFilename: "" + +## @section Metrics Parameters +## + +metrics: + ## @param metrics.enabled Start a sidecar prometheus exporter to expose Redis® metrics + ## + enabled: false + ## Bitnami Redis® Exporter image + ## ref: https://hub.docker.com/r/bitnami/redis-exporter/tags/ + ## @param metrics.image.registry [default: REGISTRY_NAME] Redis® Exporter image registry + ## @param metrics.image.repository [default: REPOSITORY_NAME/redis-exporter] Redis® Exporter image repository + ## @skip metrics.image.tag Redis® Exporter image tag (immutable tags are recommended) + ## @param metrics.image.digest Redis® Exporter image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param metrics.image.pullPolicy Redis® Exporter image pull policy + ## @param metrics.image.pullSecrets Redis® Exporter image pull secrets + ## + image: + registry: docker.io + repository: bitnami/redis-exporter + tag: 1.56.0-debian-11-r0 + digest: "" + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Configure extra options for Redis® containers' liveness, readiness & startup probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ + ## @param metrics.startupProbe.enabled Enable startupProbe on Redis® replicas nodes + ## @param metrics.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param metrics.startupProbe.periodSeconds Period seconds for startupProbe + ## @param metrics.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param metrics.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param metrics.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param metrics.livenessProbe.enabled Enable livenessProbe on Redis® replicas nodes + ## @param metrics.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param metrics.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param metrics.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param metrics.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param metrics.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param metrics.readinessProbe.enabled Enable readinessProbe on Redis® replicas nodes + ## @param metrics.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param metrics.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param metrics.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param metrics.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param metrics.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 3 + ## @param metrics.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param metrics.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param metrics.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param metrics.command Override default metrics container init command (useful when using custom images) + ## + command: [] + ## @param metrics.redisTargetHost A way to specify an alternative Redis® hostname + ## Useful for certificate CN/SAN matching + ## + redisTargetHost: "localhost" + ## @param metrics.extraArgs Extra arguments for Redis® exporter, for example: + ## e.g.: + ## extraArgs: + ## check-keys: myKey,myOtherKey + ## + extraArgs: {} + ## @param metrics.extraEnvVars Array with extra environment variables to add to Redis® exporter + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param metrics.containerSecurityContext.enabled Enabled Redis® exporter containers' Security Context + ## @param metrics.containerSecurityContext.runAsUser Set Redis® exporter containers' Security Context runAsUser + ## @param metrics.containerSecurityContext.runAsGroup Set Redis® exporter containers' Security Context runAsGroup + ## @param metrics.containerSecurityContext.runAsNonRoot Set Redis® exporter containers' Security Context runAsNonRoot + ## @param metrics.containerSecurityContext.allowPrivilegeEscalation Set Redis® exporter containers' Security Context allowPrivilegeEscalation + ## @param metrics.containerSecurityContext.seccompProfile.type Set Redis® exporter containers' Security Context seccompProfile + ## @param metrics.containerSecurityContext.capabilities.drop Set Redis® exporter containers' Security Context capabilities to drop + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsGroup: 0 + runAsNonRoot: true + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + ## @param metrics.extraVolumes Optionally specify extra list of additional volumes for the Redis® metrics sidecar + ## + extraVolumes: [] + ## @param metrics.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the Redis® metrics sidecar + ## + extraVolumeMounts: [] + ## Redis® exporter resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param metrics.resources.limits The resources limits for the Redis® exporter container + ## @param metrics.resources.requests The requested resources for the Redis® exporter container + ## + resources: + limits: {} + requests: {} + ## @param metrics.podLabels Extra labels for Redis® exporter pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param metrics.podAnnotations [object] Annotations for Redis® exporter pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: + prometheus.io/scrape: "true" + prometheus.io/port: "9121" + ## Redis® exporter service parameters + ## + service: + ## @param metrics.service.type Redis® exporter service type + ## + type: ClusterIP + ## @param metrics.service.port Redis® exporter service port + ## + port: 9121 + ## @param metrics.service.externalTrafficPolicy Redis® exporter service external traffic policy + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param metrics.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param metrics.service.loadBalancerIP Redis® exporter service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param metrics.service.loadBalancerClass exporter service Load Balancer class if service type is `LoadBalancer` (optional, cloud specific) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerClass: "" + ## @param metrics.service.loadBalancerSourceRanges Redis® exporter service Load Balancer sources + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g. + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param metrics.service.annotations Additional custom annotations for Redis® exporter service + ## + annotations: {} + ## @param metrics.service.clusterIP Redis® exporter service Cluster IP + ## + clusterIP: "" + ## Prometheus Service Monitor + ## ref: https://github.com/coreos/prometheus-operator + ## https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint + ## + serviceMonitor: + ## @param metrics.serviceMonitor.enabled Create ServiceMonitor resource(s) for scraping metrics using PrometheusOperator + ## + enabled: false + ## @param metrics.serviceMonitor.namespace The namespace in which the ServiceMonitor will be created + ## + namespace: "" + ## @param metrics.serviceMonitor.interval The interval at which metrics should be scraped + ## + interval: 30s + ## @param metrics.serviceMonitor.scrapeTimeout The timeout after which the scrape is ended + ## + scrapeTimeout: "" + ## @param metrics.serviceMonitor.relabellings Metrics RelabelConfigs to apply to samples before scraping. + ## + relabellings: [] + ## @param metrics.serviceMonitor.metricRelabelings Metrics RelabelConfigs to apply to samples before ingestion. + ## + metricRelabelings: [] + ## @param metrics.serviceMonitor.honorLabels Specify honorLabels parameter to add the scrape endpoint + ## + honorLabels: false + ## @param metrics.serviceMonitor.additionalLabels Additional labels that can be used so ServiceMonitor resource(s) can be discovered by Prometheus + ## + additionalLabels: {} + ## @param metrics.serviceMonitor.podTargetLabels Labels from the Kubernetes pod to be transferred to the created metrics + ## + podTargetLabels: [] + ## @param metrics.serviceMonitor.sampleLimit Limit of how many samples should be scraped from every Pod + ## + sampleLimit: false + ## @param metrics.serviceMonitor.targetLimit Limit of how many targets should be scraped + ## + targetLimit: false + ## Prometheus Pod Monitor + ## ref: https://github.com/coreos/prometheus-operator + ## https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#podmonitor + ## + podMonitor: + ## @param metrics.podMonitor.enabled Create PodMonitor resource(s) for scraping metrics using PrometheusOperator + ## + enabled: false + ## @param metrics.podMonitor.namespace The namespace in which the PodMonitor will be created + ## + namespace: "" + ## @param metrics.podMonitor.interval The interval at which metrics should be scraped + ## + interval: 30s + ## @param metrics.podMonitor.scrapeTimeout The timeout after which the scrape is ended + ## + scrapeTimeout: "" + ## @param metrics.podMonitor.relabellings Metrics RelabelConfigs to apply to samples before scraping. + ## + relabellings: [] + ## @param metrics.podMonitor.metricRelabelings Metrics RelabelConfigs to apply to samples before ingestion. + ## + metricRelabelings: [] + ## @param metrics.podMonitor.honorLabels Specify honorLabels parameter to add the scrape endpoint + ## + honorLabels: false + ## @param metrics.podMonitor.additionalLabels Additional labels that can be used so PodMonitor resource(s) can be discovered by Prometheus + ## + additionalLabels: {} + ## @param metrics.podMonitor.podTargetLabels Labels from the Kubernetes pod to be transferred to the created metrics + ## + podTargetLabels: [] + ## @param metrics.podMonitor.sampleLimit Limit of how many samples should be scraped from every Pod + ## + sampleLimit: false + ## @param metrics.podMonitor.targetLimit Limit of how many targets should be scraped + ## + targetLimit: false + + ## Custom PrometheusRule to be defined + ## ref: https://github.com/coreos/prometheus-operator#customresourcedefinitions + ## + prometheusRule: + ## @param metrics.prometheusRule.enabled Create a custom prometheusRule Resource for scraping metrics using PrometheusOperator + ## + enabled: false + ## @param metrics.prometheusRule.namespace The namespace in which the prometheusRule will be created + ## + namespace: "" + ## @param metrics.prometheusRule.additionalLabels Additional labels for the prometheusRule + ## + additionalLabels: {} + ## @param metrics.prometheusRule.rules Custom Prometheus rules + ## e.g: + ## rules: + ## - alert: RedisDown + ## expr: redis_up{service="{{ template "common.names.fullname" . }}-metrics"} == 0 + ## for: 2m + ## labels: + ## severity: error + ## annotations: + ## summary: Redis® instance {{ "{{ $labels.instance }}" }} down + ## description: Redis® instance {{ "{{ $labels.instance }}" }} is down + ## - alert: RedisMemoryHigh + ## expr: > + ## redis_memory_used_bytes{service="{{ template "common.names.fullname" . }}-metrics"} * 100 + ## / + ## redis_memory_max_bytes{service="{{ template "common.names.fullname" . }}-metrics"} + ## > 90 + ## for: 2m + ## labels: + ## severity: error + ## annotations: + ## summary: Redis® instance {{ "{{ $labels.instance }}" }} is using too much memory + ## description: | + ## Redis® instance {{ "{{ $labels.instance }}" }} is using {{ "{{ $value }}" }}% of its available memory. + ## - alert: RedisKeyEviction + ## expr: | + ## increase(redis_evicted_keys_total{service="{{ template "common.names.fullname" . }}-metrics"}[5m]) > 0 + ## for: 1s + ## labels: + ## severity: error + ## annotations: + ## summary: Redis® instance {{ "{{ $labels.instance }}" }} has evicted keys + ## description: | + ## Redis® instance {{ "{{ $labels.instance }}" }} has evicted {{ "{{ $value }}" }} keys in the last 5 minutes. + ## + rules: [] + +## @section Init Container Parameters +## + +## 'volumePermissions' init container parameters +## Changes the owner and group of the persistent volume mount point to runAsUser:fsGroup values +## based on the *podSecurityContext/*containerSecurityContext parameters +## +volumePermissions: + ## @param volumePermissions.enabled Enable init container that changes the owner/group of the PV mount point to `runAsUser:fsGroup` + ## + enabled: false + ## OS Shell + Utility image + ## ref: https://hub.docker.com/r/bitnami/os-shell/tags/ + ## @param volumePermissions.image.registry [default: REGISTRY_NAME] OS Shell + Utility image registry + ## @param volumePermissions.image.repository [default: REPOSITORY_NAME/os-shell] OS Shell + Utility image repository + ## @skip volumePermissions.image.tag OS Shell + Utility image tag (immutable tags are recommended) + ## @param volumePermissions.image.digest OS Shell + Utility image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param volumePermissions.image.pullPolicy OS Shell + Utility image pull policy + ## @param volumePermissions.image.pullSecrets OS Shell + Utility image pull secrets + ## + image: + registry: docker.io + repository: bitnami/os-shell + tag: 11-debian-11-r93 + digest: "" + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Init container's resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param volumePermissions.resources.limits The resources limits for the init container + ## @param volumePermissions.resources.requests The requested resources for the init container + ## + resources: + limits: {} + requests: {} + ## Init container Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param volumePermissions.containerSecurityContext.runAsUser Set init container's Security Context runAsUser + ## NOTE: when runAsUser is set to special value "auto", init container will try to chown the + ## data folder to auto-determined user&group, using commands: `id -u`:`id -G | cut -d" " -f2` + ## "auto" is especially useful for OpenShift which has scc with dynamic user ids (and 0 is not allowed) + ## + containerSecurityContext: + runAsUser: 0 + +## init-sysctl container parameters +## used to perform sysctl operation to modify Kernel settings (needed sometimes to avoid warnings) +## +sysctl: + ## @param sysctl.enabled Enable init container to modify Kernel settings + ## + enabled: false + ## OS Shell + Utility image + ## ref: https://hub.docker.com/r/bitnami/os-shell/tags/ + ## @param sysctl.image.registry [default: REGISTRY_NAME] OS Shell + Utility image registry + ## @param sysctl.image.repository [default: REPOSITORY_NAME/os-shell] OS Shell + Utility image repository + ## @skip sysctl.image.tag OS Shell + Utility image tag (immutable tags are recommended) + ## @param sysctl.image.digest OS Shell + Utility image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param sysctl.image.pullPolicy OS Shell + Utility image pull policy + ## @param sysctl.image.pullSecrets OS Shell + Utility image pull secrets + ## + image: + registry: docker.io + repository: bitnami/os-shell + tag: 11-debian-11-r93 + digest: "" + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## @param sysctl.command Override default init-sysctl container command (useful when using custom images) + ## + command: [] + ## @param sysctl.mountHostSys Mount the host `/sys` folder to `/host-sys` + ## + mountHostSys: false + ## Init container's resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param sysctl.resources.limits The resources limits for the init container + ## @param sysctl.resources.requests The requested resources for the init container + ## + resources: + limits: {} + requests: {} + +## @section useExternalDNS Parameters +## +## @param useExternalDNS.enabled Enable various syntax that would enable external-dns to work. Note this requires a working installation of `external-dns` to be usable. +## @param useExternalDNS.additionalAnnotations Extra annotations to be utilized when `external-dns` is enabled. +## @param useExternalDNS.annotationKey The annotation key utilized when `external-dns` is enabled. Setting this to `false` will disable annotations. +## @param useExternalDNS.suffix The DNS suffix utilized when `external-dns` is enabled. Note that we prepend the suffix with the full name of the release. +## +useExternalDNS: + enabled: false + suffix: "" + annotationKey: external-dns.alpha.kubernetes.io/ + additionalAnnotations: {} diff --git a/backing-services/secretstore/.helmignore b/backing-services/secretstore/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/backing-services/secretstore/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/backing-services/secretstore/Chart.yaml b/backing-services/secretstore/Chart.yaml new file mode 100644 index 0000000..1c3e493 --- /dev/null +++ b/backing-services/secretstore/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: SecretStore +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/backing-services/secretstore/auction-onsite-alpha.values.yaml b/backing-services/secretstore/auction-onsite-alpha.values.yaml new file mode 100644 index 0000000..6544e08 --- /dev/null +++ b/backing-services/secretstore/auction-onsite-alpha.values.yaml @@ -0,0 +1,3 @@ +server: http://192.168.2.172:32742 +token: aHZzLnp6aVZwTnRzWVpXcUFVbHJINGN4enJMQw== +namespace: default diff --git a/backing-services/secretstore/hospital-bahman-production.values.yaml b/backing-services/secretstore/hospital-bahman-production.values.yaml new file mode 100644 index 0000000..610f904 --- /dev/null +++ b/backing-services/secretstore/hospital-bahman-production.values.yaml @@ -0,0 +1,3 @@ +server: http://2.187.128.125:35742 +token: aHZzLnp6aVZwTnRzWVpXcUFVbHJINGN4enJMQw== +namespace: default diff --git a/backing-services/secretstore/hospital-bahman.values.yaml b/backing-services/secretstore/hospital-bahman.values.yaml new file mode 100644 index 0000000..610f904 --- /dev/null +++ b/backing-services/secretstore/hospital-bahman.values.yaml @@ -0,0 +1,3 @@ +server: http://2.187.128.125:35742 +token: aHZzLnp6aVZwTnRzWVpXcUFVbHJINGN4enJMQw== +namespace: default diff --git a/backing-services/secretstore/ride-stage-tavana.values.yaml b/backing-services/secretstore/ride-stage-tavana.values.yaml new file mode 100644 index 0000000..36f9e40 --- /dev/null +++ b/backing-services/secretstore/ride-stage-tavana.values.yaml @@ -0,0 +1,3 @@ +server: http://2.187.128.125:35742 +token: aHZzLnp6aVZwTnRzWVpXcUFVbHJINGN4enJMQw== +namespace: ride diff --git a/backing-services/secretstore/schoobus-onsite.values.yaml b/backing-services/secretstore/schoobus-onsite.values.yaml new file mode 100644 index 0000000..55cf6f7 --- /dev/null +++ b/backing-services/secretstore/schoobus-onsite.values.yaml @@ -0,0 +1,3 @@ +server: http://192.168.2.172:32742 +token: aHZzLnp6aVZwTnRzWVpXcUFVbHJINGN4enJMQw== +namespace: schoolbus diff --git a/backing-services/secretstore/school-stage-tavana.values.yaml b/backing-services/secretstore/school-stage-tavana.values.yaml new file mode 100644 index 0000000..05dacd8 --- /dev/null +++ b/backing-services/secretstore/school-stage-tavana.values.yaml @@ -0,0 +1,3 @@ +server: http://2.187.128.125:35742 +token: aHZzLnp6aVZwTnRzWVpXcUFVbHJINGN4enJMQw== +namespace: schoolbus diff --git a/backing-services/secretstore/schoolbus-demo.values.yaml b/backing-services/secretstore/schoolbus-demo.values.yaml new file mode 100644 index 0000000..05dacd8 --- /dev/null +++ b/backing-services/secretstore/schoolbus-demo.values.yaml @@ -0,0 +1,3 @@ +server: http://2.187.128.125:35742 +token: aHZzLnp6aVZwTnRzWVpXcUFVbHJINGN4enJMQw== +namespace: schoolbus diff --git a/backing-services/secretstore/templates/NOTES.txt b/backing-services/secretstore/templates/NOTES.txt new file mode 100644 index 0000000..0aee50c --- /dev/null +++ b/backing-services/secretstore/templates/NOTES.txt @@ -0,0 +1 @@ +note \ No newline at end of file diff --git a/backing-services/secretstore/templates/_helpers.tpl b/backing-services/secretstore/templates/_helpers.tpl new file mode 100644 index 0000000..e69de29 diff --git a/backing-services/secretstore/templates/secretstore.yaml b/backing-services/secretstore/templates/secretstore.yaml new file mode 100644 index 0000000..4f73bab --- /dev/null +++ b/backing-services/secretstore/templates/secretstore.yaml @@ -0,0 +1,22 @@ +apiVersion: external-secrets.io/v1beta1 +kind: SecretStore +metadata: + name: vault-backend + namespace: "{{ .Values.namespace }}" +spec: + provider: + vault: + server: "{{ .Values.server }}" + path: "secret" + version: "v2" + auth: + tokenSecretRef: + name: "vault-token" + key: "token" +--- +apiVersion: v1 +kind: Secret +metadata: + name: vault-token +data: + token: "{{ .Values.token }}" diff --git a/backing-services/secretstore/values.yaml b/backing-services/secretstore/values.yaml new file mode 100644 index 0000000..6a24dc6 --- /dev/null +++ b/backing-services/secretstore/values.yaml @@ -0,0 +1,3 @@ +server: "" +token: "" +namespace: default \ No newline at end of file diff --git a/backing-services/vault/.helmignore b/backing-services/vault/.helmignore new file mode 100644 index 0000000..f0c1319 --- /dev/null +++ b/backing-services/vault/.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/backing-services/vault/Chart.lock b/backing-services/vault/Chart.lock new file mode 100644 index 0000000..0485504 --- /dev/null +++ b/backing-services/vault/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + version: 2.13.3 +digest: sha256:9a971689db0c66ea95ac2e911c05014c2b96c6077c991131ff84f2982f88fb83 +generated: "2023-10-25T05:55:48.853010235Z" diff --git a/backing-services/vault/Chart.yaml b/backing-services/vault/Chart.yaml new file mode 100644 index 0000000..98eec2d --- /dev/null +++ b/backing-services/vault/Chart.yaml @@ -0,0 +1,38 @@ +# Copyright VMware, Inc. +# SPDX-License-Identifier: APACHE-2.0 + +annotations: + category: Infrastructure + licenses: Apache-2.0 + images: | + - name: os-shell + image: docker.io/bitnami/os-shell:11-debian-11-r92 + - name: vault-csi-provider + image: docker.io/bitnami/vault-csi-provider:1.4.1-debian-11-r3 + - name: vault-k8s + image: docker.io/bitnami/vault-k8s:1.3.1-debian-11-r3 + - name: vault + image: docker.io/bitnami/vault:1.15.4-debian-11-r0 +apiVersion: v2 +appVersion: 1.15.4 +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + tags: + - bitnami-common + version: 2.x.x +description: Vault is a tool for securely managing and accessing secrets using a unified interface. Features secure storage, dynamic secrets, data encryption and revocation. +home: https://bitnami.com +icon: https://bitnami.com/assets/stacks/vault/img/vault-stack-220x234.png +keywords: +- security +- secrets +- injection +- vault +maintainers: +- name: VMware, Inc. + url: https://github.com/bitnami/charts +name: vault +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/vault +version: 0.4.6 diff --git a/backing-services/vault/README.md b/backing-services/vault/README.md new file mode 100644 index 0000000..18de911 --- /dev/null +++ b/backing-services/vault/README.md @@ -0,0 +1,573 @@ + + +# Bitnami package for HashiCorp Vault + +Vault is a tool for securely managing and accessing secrets using a unified interface. Features secure storage, dynamic secrets, data encryption and revocation. + +[Overview of HashiCorp Vault](https://www.vaultproject.io/) + +Trademarks: This software listing is packaged by Bitnami. The respective trademarks mentioned in the offering are owned by the respective companies, and use of them does not imply any affiliation or endorsement. + +## TL;DR + +```console +helm install my-release oci://registry-1.docker.io/bitnamicharts/vault +``` + +Looking to use HashiCorp Vault in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the enterprise edition of Bitnami Application Catalog. + +## Introduction + +This chart bootstraps a [HashiCorp Vault](https://github.com/bitnami/containers/tree/main/bitnami/vault) deployment on a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```console +helm install my-release my-repo/vault +``` + +The command deploys vault 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 + +### Global parameters + +| Name | Description | Value | +| ------------------------- | ----------------------------------------------- | ----- | +| `global.imageRegistry` | Global Docker image registry | `""` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | +| `global.storageClass` | Global StorageClass for Persistent Volume(s) | `""` | + +### Common parameters + +| Name | Description | Value | +| ------------------------ | --------------------------------------------------------------------------------------- | --------------- | +| `kubeVersion` | Override Kubernetes version | `""` | +| `nameOverride` | String to partially override common.names.name | `""` | +| `fullnameOverride` | String to fully override common.names.fullname | `""` | +| `namespaceOverride` | String to fully override common.names.namespace | `""` | +| `commonLabels` | Labels to add to all deployed objects | `{}` | +| `commonAnnotations` | Annotations to add to all deployed objects | `{}` | +| `clusterDomain` | Kubernetes cluster domain name | `cluster.local` | +| `extraDeploy` | Array of extra objects to deploy with the release | `[]` | +| `diagnosticMode.enabled` | Enable diagnostic mode (all probes will be disabled and the command will be overridden) | `false` | +| `diagnosticMode.command` | Command to override all containers in the deployment | `["sleep"]` | +| `diagnosticMode.args` | Args to override all containers in the deployment | `["infinity"]` | + +### Vault Server Parameters + +| Name | Description | Value | +| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | +| `server.enabled` | Enable Vault Server | `true` | +| `server.image.registry` | Vault Server image registry | `REGISTRY_NAME` | +| `server.image.repository` | Vault Server image repository | `REPOSITORY_NAME/vault` | +| `server.image.digest` | Vault Server image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag image tag (immutable tags are recommended) | `""` | +| `server.image.pullPolicy` | Vault Server image pull policy | `IfNotPresent` | +| `server.image.pullSecrets` | Vault Server image pull secrets | `[]` | +| `server.image.debug` | Enable Vault Server image debug mode | `false` | +| `server.replicaCount` | Number of Vault Server replicas to deploy | `1` | +| `server.podManagementPolicy` | Pod management policy | `Parallel` | +| `server.containerPorts.http` | Vault Server http container port | `8200` | +| `server.containerPorts.internal` | Vault Server internal (HTTPS) container port | `8201` | +| `server.livenessProbe.enabled` | Enable livenessProbe on Vault Server containers | `false` | +| `server.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `5` | +| `server.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `server.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `server.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `5` | +| `server.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `server.readinessProbe.enabled` | Enable readinessProbe on Vault Server containers | `true` | +| `server.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `server.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `server.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` | +| `server.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `5` | +| `server.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `server.startupProbe.enabled` | Enable startupProbe on Vault Server containers | `false` | +| `server.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `5` | +| `server.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `server.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `server.startupProbe.failureThreshold` | Failure threshold for startupProbe | `5` | +| `server.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `server.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `server.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `server.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `server.resources.limits` | The resources limits for the Vault Server containers | `{}` | +| `server.resources.requests` | The requested resources for the Vault Server containers | `{}` | +| `server.podSecurityContext.enabled` | Enabled Vault Server pods' Security Context | `true` | +| `server.podSecurityContext.fsGroup` | Set Vault Server pod's Security Context fsGroup | `1001` | +| `server.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `server.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `server.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `server.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `server.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `server.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `server.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `server.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `server.command` | Override default container command (useful when using custom images) | `[]` | +| `server.args` | Override default container args (useful when using custom images) | `[]` | +| `server.hostAliases` | Vault Server pods host aliases | `[]` | +| `server.config` | Vault server configuration (evaluated as a template) | `""` | +| `server.existingConfigMap` | name of a ConfigMap with existing configuration for the server | `""` | +| `server.podLabels` | Extra labels for Vault Server pods | `{}` | +| `server.podAnnotations` | Annotations for Vault Server pods | `{}` | +| `server.podAffinityPreset` | Pod affinity preset. Ignored if `server.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `server.podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `server.affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `server.pdb.create` | Enable/disable a Pod Disruption Budget creation | `false` | +| `server.pdb.minAvailable` | Minimum number/percentage of pods that should remain scheduled | `1` | +| `server.pdb.maxUnavailable` | Maximum number/percentage of pods that may be made unavailable | `""` | +| `server.nodeAffinityPreset.type` | Node affinity preset type. Ignored if `server.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `server.nodeAffinityPreset.key` | Node label key to match. Ignored if `server.affinity` is set | `""` | +| `server.nodeAffinityPreset.values` | Node label values to match. Ignored if `server.affinity` is set | `[]` | +| `server.affinity` | Affinity for Vault Server pods assignment | `{}` | +| `server.nodeSelector` | Node labels for Vault Server pods assignment | `{}` | +| `server.tolerations` | Tolerations for Vault Server pods assignment | `[]` | +| `server.updateStrategy.type` | Vault Server statefulset strategy type | `RollingUpdate` | +| `server.priorityClassName` | Vault Server pods' priorityClassName | `""` | +| `server.topologySpreadConstraints` | Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template | `[]` | +| `server.schedulerName` | Name of the k8s scheduler (other than default) for Vault Server pods | `""` | +| `server.terminationGracePeriodSeconds` | Seconds Redmine pod needs to terminate gracefully | `""` | +| `server.lifecycleHooks` | for the Vault Server container(s) to automate configuration before or after startup | `{}` | +| `server.extraEnvVars` | Array with extra environment variables to add to Vault Server nodes | `[]` | +| `server.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for Vault Server nodes | `""` | +| `server.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for Vault Server nodes | `""` | +| `server.extraVolumes` | Optionally specify extra list of additional volumes for the Vault Server pod(s) | `[]` | +| `server.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the Vault Server container(s) | `[]` | +| `server.sidecars` | Add additional sidecar containers to the Vault Server pod(s) | `[]` | +| `server.initContainers` | Add additional init containers to the Vault Server pod(s) | `[]` | + +### Vault Server Traffic Exposure Parameters + +| Name | Description | Value | +| ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | +| `server.service.general.type` | Vault Server service type | `ClusterIP` | +| `server.service.general.ports.http` | Vault Server service HTTP port | `8200` | +| `server.service.general.ports.internal` | Vault Server internal port | `8201` | +| `server.service.general.nodePorts.http` | Node port for HTTP | `""` | +| `server.service.general.nodePorts.internal` | Node port for HTTP | `""` | +| `server.service.general.clusterIP` | Vault Server service Cluster IP | `""` | +| `server.service.general.loadBalancerIP` | Vault Server service Load Balancer IP | `""` | +| `server.service.general.loadBalancerSourceRanges` | Vault Server service Load Balancer sources | `[]` | +| `server.service.general.externalTrafficPolicy` | Vault Server service external traffic policy | `Cluster` | +| `server.service.general.annotations` | Additional custom annotations for Vault Server service | `{}` | +| `server.service.general.extraPorts` | Extra ports to expose in Vault Server service (normally used with the `sidecars` value) | `[]` | +| `server.service.general.sessionAffinity` | Control where web requests go, to the same pod or round-robin | `None` | +| `server.service.general.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `server.service.active.type` | Vault Server service type | `ClusterIP` | +| `server.service.active.ports.http` | Vault Server service HTTP port | `8200` | +| `server.service.active.ports.internal` | Vault Server internal port | `8201` | +| `server.service.active.nodePorts.http` | Node port for HTTP | `""` | +| `server.service.active.nodePorts.internal` | Node port for HTTP | `""` | +| `server.service.active.clusterIP` | Vault Server service Cluster IP | `""` | +| `server.service.active.loadBalancerIP` | Vault Server service Load Balancer IP | `""` | +| `server.service.active.loadBalancerSourceRanges` | Vault Server service Load Balancer sources | `[]` | +| `server.service.active.externalTrafficPolicy` | Vault Server service external traffic policy | `Cluster` | +| `server.service.active.annotations` | Additional custom annotations for Vault Server service | `{}` | +| `server.service.active.extraPorts` | Extra ports to expose in Vault Server service (normally used with the `sidecars` value) | `[]` | +| `server.service.active.sessionAffinity` | Control where web requests go, to the same pod or round-robin | `None` | +| `server.service.active.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `server.ingress.enabled` | Enable ingress record generation for Vault | `false` | +| `server.ingress.pathType` | Ingress path type | `ImplementationSpecific` | +| `server.ingress.apiVersion` | Force Ingress API version (automatically detected if not set) | `""` | +| `server.ingress.hostname` | Default host for the ingress record | `vault.local` | +| `server.ingress.ingressClassName` | IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+) | `""` | +| `server.ingress.path` | Default path for the ingress record | `/` | +| `server.ingress.annotations` | Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. | `{}` | +| `server.ingress.tls` | Enable TLS configuration for the host defined at `client.ingress.hostname` parameter | `false` | +| `server.ingress.selfSigned` | Create a TLS secret for this ingress record using self-signed certificates generated by Helm | `false` | +| `server.ingress.extraHosts` | An array with additional hostname(s) to be covered with the ingress record | `[]` | +| `server.ingress.extraPaths` | An array with additional arbitrary paths that may need to be added to the ingress under the main host | `[]` | +| `server.ingress.extraTls` | TLS configuration for additional hostname(s) to be covered with this ingress record | `[]` | +| `server.ingress.secrets` | Custom TLS certificates as secrets | `[]` | +| `server.ingress.extraRules` | Additional rules to be covered with this ingress record | `[]` | + +### Vault Server RBAC Parameters + +| Name | Description | Value | +| ---------------------------------------------------- | ---------------------------------------------------------------- | ------ | +| `server.rbac.create` | Specifies whether RBAC resources should be created | `true` | +| `server.serviceAccount.create` | Specifies whether a ServiceAccount should be created | `true` | +| `server.serviceAccount.name` | The name of the ServiceAccount to use. | `""` | +| `server.serviceAccount.annotations` | Additional Service Account annotations (evaluated as a template) | `{}` | +| `server.serviceAccount.automountServiceAccountToken` | Automount service account token for the server service account | `true` | + +### Source Conttroller Persistence Parameters + +| Name | Description | Value | +| ---------------------------------- | --------------------------------------------------------------------------------------- | --------------------- | +| `server.persistence.enabled` | Enable persistence using Persistent Volume Claims | `true` | +| `server.persistence.mountPath` | Persistent Volume mount root path | `/bitnami/vault/data` | +| `server.persistence.storageClass` | Persistent Volume storage class | `""` | +| `server.persistence.accessModes` | Persistent Volume access modes | `[]` | +| `server.persistence.size` | Persistent Volume size | `10Gi` | +| `server.persistence.dataSource` | Custom PVC data source | `{}` | +| `server.persistence.annotations` | Annotations for the PVC | `{}` | +| `server.persistence.selector` | Selector to match an existing Persistent Volume (this value is evaluated as a template) | `{}` | +| `server.persistence.existingClaim` | The name of an existing PVC to use for persistence | `""` | + +### Vault Server Metrics Parameters + +| Name | Description | Value | +| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ------- | +| `server.metrics.enabled` | Enable the export of Prometheus metrics | `false` | +| `server.metrics.annotations` | Annotations for the server service in order to scrape metrics | `{}` | +| `server.metrics.serviceMonitor.enabled` | if `true`, creates a Prometheus Operator ServiceMonitor (also requires `metrics.enabled` to be `true`) | `false` | +| `server.metrics.serviceMonitor.namespace` | Namespace in which Prometheus is running | `""` | +| `server.metrics.serviceMonitor.annotations` | Additional custom annotations for the ServiceMonitor | `{}` | +| `server.metrics.serviceMonitor.labels` | Extra labels for the ServiceMonitor | `{}` | +| `server.metrics.serviceMonitor.jobLabel` | The name of the label on the target service to use as the job name in Prometheus | `""` | +| `server.metrics.serviceMonitor.honorLabels` | honorLabels chooses the metric's labels on collisions with target labels | `false` | +| `server.metrics.serviceMonitor.interval` | Interval at which metrics should be scraped. | `""` | +| `server.metrics.serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended | `""` | +| `server.metrics.serviceMonitor.metricRelabelings` | Specify additional relabeling of metrics | `[]` | +| `server.metrics.serviceMonitor.relabelings` | Specify general relabeling | `[]` | +| `server.metrics.serviceMonitor.selector` | Prometheus instance selector labels | `{}` | + +### Vault CSI Provider Parameters + +| Name | Description | Value | +| ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- | +| `csiProvider.enabled` | Enable Vault CSI Provider | `false` | +| `csiProvider.image.registry` | Vault CSI Provider image registry | `REGISTRY_NAME` | +| `csiProvider.image.repository` | Vault CSI Provider image repository | `REPOSITORY_NAME/vault-csi-provider` | +| `csiProvider.image.digest` | Vault CSI Provider image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag image tag (immutable tags are recommended) | `""` | +| `csiProvider.image.pullPolicy` | Vault CSI Provider image pull policy | `IfNotPresent` | +| `csiProvider.image.pullSecrets` | Vault CSI Provider image pull secrets | `[]` | +| `csiProvider.image.debug` | Enable Vault CSI Provider image debug mode | `false` | +| `csiProvider.config` | Vault CSI Provider configuration (evaluated as a template) | `""` | +| `csiProvider.existingConfigMap` | name of a ConfigMap with existing configuration for the CSI Provider | `""` | +| `csiProvider.secretStoreHostPath` | Path to the host CSI Provider folder | `/etc/kubernetes/secrets-store-csi-providers` | +| `csiProvider.hostAliases` | Vault CSI Provider pods host aliases | `[]` | +| `csiProvider.podLabels` | Extra labels for Vault CSI Provider pods | `{}` | +| `csiProvider.podAnnotations` | Annotations for Vault CSI Provider pods | `{}` | +| `csiProvider.podAffinityPreset` | Pod affinity preset. Ignored if `csiProvider.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `csiProvider.podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `csiProvider.affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `csiProvider.nodeAffinityPreset.type` | Node affinity preset type. Ignored if `csiProvider.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `csiProvider.nodeAffinityPreset.key` | Node label key to match. Ignored if `csiProvider.affinity` is set | `""` | +| `csiProvider.nodeAffinityPreset.values` | Node label values to match. Ignored if `csiProvider.affinity` is set | `[]` | +| `csiProvider.affinity` | Affinity for Vault CSI Provider pods assignment | `{}` | +| `csiProvider.nodeSelector` | Node labels for Vault CSI Provider pods assignment | `{}` | +| `csiProvider.tolerations` | Tolerations for Vault CSI Provider pods assignment | `[]` | +| `csiProvider.updateStrategy.type` | Vault CSI Provider statefulset strategy type | `RollingUpdate` | +| `csiProvider.priorityClassName` | Vault CSI Provider pods' priorityClassName | `""` | +| `csiProvider.topologySpreadConstraints` | Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template | `[]` | +| `csiProvider.schedulerName` | Name of the k8s scheduler (other than default) for Vault CSI Provider pods | `""` | +| `csiProvider.terminationGracePeriodSeconds` | Seconds Redmine pod needs to terminate gracefully | `""` | +| `csiProvider.extraVolumes` | Optionally specify extra list of additional volumes for the Vault CSI Provider pod(s) | `[]` | +| `csiProvider.sidecars` | Add additional sidecar containers to the Vault CSI Provider pod(s) | `[]` | +| `csiProvider.initContainers` | Add additional init containers to the Vault CSI Provider pod(s) | `[]` | +| `csiProvider.podSecurityContext.enabled` | Enabled CSI Provider pods' Security Context | `true` | +| `csiProvider.podSecurityContext.fsGroup` | Set CSI Provider pod's Security Context fsGroup | `1001` | +| `csiProvider.provider.containerPorts.health` | CSI Provider health container port | `8080` | +| `csiProvider.provider.livenessProbe.enabled` | Enable livenessProbe on CSI Provider container | `true` | +| `csiProvider.provider.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `5` | +| `csiProvider.provider.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `csiProvider.provider.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `csiProvider.provider.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `5` | +| `csiProvider.provider.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `csiProvider.provider.readinessProbe.enabled` | Enable readinessProbe on CSI Provider container | `true` | +| `csiProvider.provider.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `csiProvider.provider.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `csiProvider.provider.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` | +| `csiProvider.provider.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `5` | +| `csiProvider.provider.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `csiProvider.provider.startupProbe.enabled` | Enable startupProbe on CSI Provider container | `false` | +| `csiProvider.provider.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `5` | +| `csiProvider.provider.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `csiProvider.provider.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `csiProvider.provider.startupProbe.failureThreshold` | Failure threshold for startupProbe | `5` | +| `csiProvider.provider.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `csiProvider.provider.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `csiProvider.provider.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `csiProvider.provider.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `csiProvider.provider.resources.limits` | The resources limits for the CSI Provider container | `{}` | +| `csiProvider.provider.resources.requests` | The requested resources for the CSI Provider container | `{}` | +| `csiProvider.provider.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `csiProvider.provider.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `csiProvider.provider.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `csiProvider.provider.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `csiProvider.provider.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `csiProvider.provider.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `csiProvider.provider.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `csiProvider.provider.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `csiProvider.provider.command` | Override default container command (useful when using custom images) | `[]` | +| `csiProvider.provider.args` | Override default container args (useful when using custom images) | `[]` | +| `csiProvider.provider.lifecycleHooks` | for the CSI Provider container(s) to automate configuration before or after startup | `{}` | +| `csiProvider.provider.extraEnvVars` | Array with extra environment variables to add to CSI Provider nodes | `[]` | +| `csiProvider.provider.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for CSI Provider nodes | `""` | +| `csiProvider.provider.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for CSI Provider nodes | `""` | +| `csiProvider.provider.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the Vault CSI Provider container | `[]` | +| `csiProvider.agent.containerPorts.tcp` | CSI Provider Agent metrics container port | `8200` | +| `csiProvider.agent.livenessProbe.enabled` | Enable livenessProbe on CSI Provider Agent container | `true` | +| `csiProvider.agent.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `5` | +| `csiProvider.agent.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `csiProvider.agent.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `csiProvider.agent.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `5` | +| `csiProvider.agent.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `csiProvider.agent.readinessProbe.enabled` | Enable readinessProbe on CSI Provider Agent container | `true` | +| `csiProvider.agent.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `csiProvider.agent.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `csiProvider.agent.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` | +| `csiProvider.agent.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `5` | +| `csiProvider.agent.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `csiProvider.agent.startupProbe.enabled` | Enable startupProbe on CSI Provider Agent container | `false` | +| `csiProvider.agent.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `5` | +| `csiProvider.agent.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `csiProvider.agent.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `csiProvider.agent.startupProbe.failureThreshold` | Failure threshold for startupProbe | `5` | +| `csiProvider.agent.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `csiProvider.agent.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `csiProvider.agent.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `csiProvider.agent.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `csiProvider.agent.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `csiProvider.agent.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `csiProvider.agent.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `csiProvider.agent.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `csiProvider.agent.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `csiProvider.agent.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `csiProvider.agent.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `csiProvider.agent.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `csiProvider.agent.resources.limits` | The resources limits for the CSI Provider Agent container | `{}` | +| `csiProvider.agent.resources.requests` | The requested resources for the CSI Provider Agent container | `{}` | +| `csiProvider.agent.command` | Override default container command (useful when using custom images) | `[]` | +| `csiProvider.agent.args` | Override default container args (useful when using custom images) | `[]` | +| `csiProvider.agent.lifecycleHooks` | for the CSI Provider Agent container(s) to automate configuration before or after startup | `{}` | +| `csiProvider.agent.extraEnvVars` | Array with extra environment variables to add to CSI Provider Agent nodes | `[]` | +| `csiProvider.agent.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for CSI Provider Agent nodes | `""` | +| `csiProvider.agent.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for CSI Provider Agent nodes | `""` | +| `csiProvider.agent.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the CSI Provider container(s) | `[]` | + +### Vault CSI Provider RBAC Parameters + +| Name | Description | Value | +| --------------------------------------------------------- | ---------------------------------------------------------------- | ------ | +| `csiProvider.rbac.create` | Specifies whether RBAC resources should be created | `true` | +| `csiProvider.rbac.rules` | Custom RBAC rules to set | `[]` | +| `csiProvider.serviceAccount.create` | Specifies whether a ServiceAccount should be created | `true` | +| `csiProvider.serviceAccount.name` | The name of the ServiceAccount to use. | `""` | +| `csiProvider.serviceAccount.annotations` | Additional Service Account annotations (evaluated as a template) | `{}` | +| `csiProvider.serviceAccount.automountServiceAccountToken` | Automount service account token for the server service account | `true` | + +### Vault Kubernetes Injector Parameters + +| Name | Description | Value | +| ------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- | +| `injector.enabled` | Enable Vault Kubernetes Injector | `true` | +| `injector.image.registry` | Vault Kubernetes Injector image registry | `REGISTRY_NAME` | +| `injector.image.repository` | Vault Kubernetes Injector image repository | `REPOSITORY_NAME/vault-k8s` | +| `injector.image.digest` | Vault Kubernetes Injector image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag image tag (immutable tags are recommended) | `""` | +| `injector.image.pullPolicy` | Vault Kubernetes Injector image pull policy | `IfNotPresent` | +| `injector.image.pullSecrets` | Vault Kubernetes Injector image pull secrets | `[]` | +| `injector.image.debug` | Enable Vault Kubernetes Injector image debug mode | `false` | +| `injector.replicaCount` | Number of Vault Kubernetes Injector replicas to deploy | `1` | +| `injector.containerPorts.https` | Vault Kubernetes Injector metrics container port | `8080` | +| `injector.livenessProbe.enabled` | Enable livenessProbe on Vault Kubernetes Injector containers | `true` | +| `injector.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `5` | +| `injector.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `injector.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `injector.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `5` | +| `injector.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `injector.readinessProbe.enabled` | Enable readinessProbe on Vault Kubernetes Injector containers | `true` | +| `injector.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `injector.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `injector.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` | +| `injector.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `5` | +| `injector.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `injector.startupProbe.enabled` | Enable startupProbe on Vault Kubernetes Injector containers | `false` | +| `injector.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `5` | +| `injector.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `injector.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `injector.startupProbe.failureThreshold` | Failure threshold for startupProbe | `5` | +| `injector.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `injector.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `injector.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `injector.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `injector.resources.limits` | The resources limits for the Vault Kubernetes Injector containers | `{}` | +| `injector.resources.requests` | The requested resources for the Vault Kubernetes Injector containers | `{}` | +| `injector.podSecurityContext.enabled` | Enabled Vault Kubernetes Injector pods' Security Context | `true` | +| `injector.podSecurityContext.fsGroup` | Set Vault Kubernetes Injector pod's Security Context fsGroup | `1001` | +| `injector.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `injector.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `injector.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `injector.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `injector.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `injector.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `injector.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `injector.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `injector.command` | Override default container command (useful when using custom images) | `[]` | +| `injector.args` | Override default container args (useful when using custom images) | `[]` | +| `injector.hostAliases` | Vault Kubernetes Injector pods host aliases | `[]` | +| `injector.podLabels` | Extra labels for Vault Kubernetes Injector pods | `{}` | +| `injector.podAnnotations` | Annotations for Vault Kubernetes Injector pods | `{}` | +| `injector.podAffinityPreset` | Pod affinity preset. Ignored if `injector.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `injector.podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `injector.affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `injector.pdb.create` | Enable/disable a Pod Disruption Budget creation | `false` | +| `injector.pdb.minAvailable` | Minimum number/percentage of pods that should remain scheduled | `1` | +| `injector.pdb.maxUnavailable` | Maximum number/percentage of pods that may be made unavailable | `""` | +| `injector.autoscaling.enabled` | Enable autoscaling for injector | `false` | +| `injector.autoscaling.minReplicas` | Minimum number of injector replicas | `""` | +| `injector.autoscaling.maxReplicas` | Maximum number of injector replicas | `""` | +| `injector.autoscaling.targetCPU` | Target CPU utilization percentage | `""` | +| `injector.autoscaling.targetMemory` | Target Memory utilization percentage | `""` | +| `injector.nodeAffinityPreset.type` | Node affinity preset type. Ignored if `injector.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `injector.nodeAffinityPreset.key` | Node label key to match. Ignored if `injector.affinity` is set | `""` | +| `injector.nodeAffinityPreset.values` | Node label values to match. Ignored if `injector.affinity` is set | `[]` | +| `injector.affinity` | Affinity for Vault Kubernetes Injector pods assignment | `{}` | +| `injector.nodeSelector` | Node labels for Vault Kubernetes Injector pods assignment | `{}` | +| `injector.tolerations` | Tolerations for Vault Kubernetes Injector pods assignment | `[]` | +| `injector.updateStrategy.type` | Vault Kubernetes Injector statefulset strategy type | `RollingUpdate` | +| `injector.priorityClassName` | Vault Kubernetes Injector pods' priorityClassName | `""` | +| `injector.topologySpreadConstraints` | Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template | `[]` | +| `injector.schedulerName` | Name of the k8s scheduler (other than default) for Vault Kubernetes Injector pods | `""` | +| `injector.terminationGracePeriodSeconds` | Seconds Redmine pod needs to terminate gracefully | `""` | +| `injector.lifecycleHooks` | for the Vault Kubernetes Injector container(s) to automate configuration before or after startup | `{}` | +| `injector.extraEnvVars` | Array with extra environment variables to add to Vault Kubernetes Injector nodes | `[]` | +| `injector.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for Vault Kubernetes Injector nodes | `""` | +| `injector.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for Vault Kubernetes Injector nodes | `""` | +| `injector.extraVolumes` | Optionally specify extra list of additional volumes for the Vault Kubernetes Injector pod(s) | `[]` | +| `injector.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the Vault Kubernetes Injector container(s) | `[]` | +| `injector.sidecars` | Add additional sidecar containers to the Vault Kubernetes Injector pod(s) | `[]` | +| `injector.initContainers` | Add additional init containers to the Vault Kubernetes Injector pod(s) | `[]` | + +### Vault Kubernetes Injector Traffic Exposure Parameters + +| Name | Description | Value | +| ------------------------------------------- | ---------------------------------------------------------------------------------------------------- | ----------- | +| `injector.service.type` | Vault Kubernetes Injector service type | `ClusterIP` | +| `injector.service.ports.https` | Vault Kubernetes Injector service HTTPS port | `443` | +| `injector.service.nodePorts.https` | Node port for HTTPS | `""` | +| `injector.service.clusterIP` | Vault Kubernetes Injector service Cluster IP | `""` | +| `injector.service.loadBalancerIP` | Vault Kubernetes Injector service Load Balancer IP | `""` | +| `injector.service.loadBalancerSourceRanges` | Vault Kubernetes Injector service Load Balancer sources | `[]` | +| `injector.service.externalTrafficPolicy` | Vault Kubernetes Injector service external traffic policy | `Cluster` | +| `injector.service.annotations` | Additional custom annotations for Vault Kubernetes Injector service | `{}` | +| `injector.service.extraPorts` | Extra ports to expose in Vault Kubernetes Injector service (normally used with the `sidecars` value) | `[]` | +| `injector.service.sessionAffinity` | Control where web requests go, to the same pod or round-robin | `None` | +| `injector.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | + +### Vault Kubernetes Injector RBAC Parameters + +| Name | Description | Value | +| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------ | -------------------------- | +| `injector.rbac.create` | Specifies whether RBAC resources should be created | `true` | +| `injector.rbac.rules` | Custom RBAC rules to set | `[]` | +| `injector.serviceAccount.create` | Specifies whether a ServiceAccount should be created | `true` | +| `injector.serviceAccount.name` | The name of the ServiceAccount to use. | `""` | +| `injector.serviceAccount.annotations` | Additional Service Account annotations (evaluated as a template) | `{}` | +| `injector.serviceAccount.automountServiceAccountToken` | Automount service account token for the server service account | `true` | +| `volumePermissions.enabled` | Enable init container that changes the owner/group of the PV mount point to `runAsUser:fsGroup` | `false` | +| `volumePermissions.image.registry` | OS Shell + Utility image registry | `REGISTRY_NAME` | +| `volumePermissions.image.repository` | OS Shell + Utility image repository | `REPOSITORY_NAME/os-shell` | +| `volumePermissions.image.digest` | OS Shell + Utility image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `volumePermissions.image.pullPolicy` | OS Shell + Utility image pull policy | `IfNotPresent` | +| `volumePermissions.image.pullSecrets` | OS Shell + Utility image pull secrets | `[]` | +| `volumePermissions.resources.limits` | The resources limits for the init container | `{}` | +| `volumePermissions.resources.requests` | The requested resources for the init container | `{}` | +| `volumePermissions.containerSecurityContext.enabled` | Enable init container's Security Context | `true` | +| `volumePermissions.containerSecurityContext.runAsUser` | Set init container's Security Context runAsUser | `0` | + +The above parameters map to the env variables defined in [bitnami/vault](https://github.com/bitnami/containers/tree/main/bitnami/vault). For more information please refer to the [bitnami/vault](https://github.com/bitnami/containers/tree/main/bitnami/vault) image documentation. + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +helm install my-release \ + --set csiProvider.enabled=true \ + my-repo/vault +``` + +The above command enables the Vault CSI Provider deployment. + +> NOTE: Once this chart is deployed, it is not possible to change the application's access credentials, such as usernames or passwords, using Helm. To change these application credentials after deployment, delete any persistent volumes (PVs) used by the chart and re-deploy it, or use the application's built-in administrative tools if available. + +Alternatively, a YAML file that specifies the values for the above parameters can be provided while installing the chart. For example, + +```console +helm install my-release -f values.yaml my-repo/vault +``` + +> **Tip**: You can use the default [values.yaml](https://github.com/bitnami/charts/tree/main/bitnami/vault/values.yaml) + +## Configuration and installation details + +### [Rolling VS Immutable tags](https://docs.bitnami.com/tutorials/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. + +### Ingress + +This chart provides support for Ingress resources. If you have an ingress controller installed on your cluster, such as [nginx-ingress-controller](https://github.com/bitnami/charts/tree/main/bitnami/nginx-ingress-controller) or [contour](https://github.com/bitnami/charts/tree/main/bitnami/contour) you can utilize the ingress controller to serve your application. + +To enable Ingress integration, set `client.ingress.enabled` to `true`. The `client.ingress.hostname` property can be used to set the host name. The `client.ingress.tls` parameter can be used to add the TLS configuration for this host. It is also possible to have more than one host, with a separate TLS configuration for each host. [Learn more about configuring and using Ingress](https://docs.bitnami.com/kubernetes/apps/vault/configuration/configure-ingress/). + +### TLS secrets + +The chart also facilitates the creation of TLS secrets for use with the Ingress controller, with different options for certificate management. [Learn more about TLS secrets](https://docs.bitnami.com/kubernetes/apps/vault/administration/enable-tls-ingress/). + +## Persistence + +The [Bitnami vault](https://github.com/bitnami/containers/tree/main/bitnami/vault) image stores the vault data and configurations at the `/bitnami` 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. + +### Additional environment variables + +In case you want to add extra environment variables (useful for advanced operations like custom init scripts), you can use the `extraEnvVars` property inside the `server`, `csiProvider` and `injector` sections. + +```yaml +server: + extraEnvVars: + - name: LOG_LEVEL + value: error +``` + +Alternatively, you can use a ConfigMap or a Secret with the environment variables. To do so, use the `extraEnvVarsCM` or the `extraEnvVarsSecret` values inside the `server`, `csiProvider` and `injector` sections. + +### Sidecars + +If additional containers are needed in the same pod as vault (such as additional metrics or logging exporters), they can be defined using the `sidecars` parameter inside the `server`, `csiProvider` and `injector` sections. If these sidecars export extra ports, extra port definitions can be added using the `service.extraPorts` parameter. [Learn more about configuring and using sidecar containers](https://docs.bitnami.com/kubernetes/apps/vault/administration/configure-use-sidecars/). + +### Pod affinity + +This chart allows you to set your custom affinity using the `affinity` parameter. Find more information about Pod affinity in the [kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). + +As an alternative, use one of the preset configurations for pod affinity, pod anti-affinity, and node affinity available at the [bitnami/common](https://github.com/bitnami/charts/tree/main/bitnami/common#affinities) chart. To do so, set the `podAffinityPreset`, `podAntiAffinityPreset`, or `nodeAffinityPreset` parameters inside the `server`, `csiProvider` and `injector` sections. + +## Troubleshooting + +Find more information about how to deal with common errors related to Bitnami's Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues). + +## License + +Copyright © 2024 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/backing-services/vault/charts/common-2.13.3.tgz b/backing-services/vault/charts/common-2.13.3.tgz new file mode 100644 index 0000000..3fe4889 Binary files /dev/null and b/backing-services/vault/charts/common-2.13.3.tgz differ diff --git a/backing-services/vault/templates/NOTES.txt b/backing-services/vault/templates/NOTES.txt new file mode 100644 index 0000000..820b06a --- /dev/null +++ b/backing-services/vault/templates/NOTES.txt @@ -0,0 +1,51 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +** Please be patient while the chart is being deployed ** + +{{- if .Values.diagnosticMode.enabled }} +The chart has been deployed in diagnostic mode. All probes have been disabled and the command has been overwritten with: + + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 4 }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 4 }} + +Get the list of pods by executing: + + kubectl get pods --namespace {{ include "common.names.namespace" . | quote }} -l app.kubernetes.io/instance={{ .Release.Name }} + +Access the pod you want to debug by executing + + kubectl exec --namespace {{ include "common.names.namespace" . | quote }} -ti -- bash + +{{- else }} + +The following controllers have been deployed: + + {{- if .Values.server.enabled }} + - server + {{- end }} + {{- if .Values.csiProvider.enabled }} + - csi-provider + {{- end }} + {{- if .Values.injector.enabled }} + - injector + {{- end }} + +{{- end }} + +Check the status of the pods by running this command: + + kubectl get pods --namespace {{ include "common.names.namespace" . | quote }} -l app.kubernetes.io/instance={{ .Release.Name }} + +IMPORTANT: The chart is deploying a sealed Vault instance. The service will not be ready until the instance is unsealed. +This is a manual process that must be performed with maximum precaution. + +Read the upstream vault documentation for unsealing and initializing the instance: + + https://developer.hashicorp.com/vault/docs/platform/k8s/helm/run#initialize-and-unseal-vault + +{{- include "common.warnings.rollingTag" .Values.server.image }} +{{- include "common.warnings.rollingTag" .Values.injector.image }} +{{- include "common.warnings.rollingTag" .Values.csiProvider.image }} +{{- include "vault.validateValues" . }} diff --git a/backing-services/vault/templates/_helpers.tpl b/backing-services/vault/templates/_helpers.tpl new file mode 100644 index 0000000..5759ced --- /dev/null +++ b/backing-services/vault/templates/_helpers.tpl @@ -0,0 +1,159 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "vault.imagePullSecrets" -}} +{{- include "common.images.renderPullSecrets" (dict "images" (list .Values.server.image .Values.csiProvider.image .Values.injector.image .Values.volumePermissions.image ) "context" $) -}} +{{- end -}} + +{{/* +Return the proper Vault Server fullname +*/}} +{{- define "vault.server.fullname" -}} +{{- printf "%s-%s" (include "common.names.fullname" .) "server" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Return the proper Vault Server fullname (with namespace) +*/}} +{{- define "vault.server.fullname.namespace" -}} +{{- printf "%s-%s" (include "common.names.fullname.namespace" .) "server" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Return the proper Vault Server image name +*/}} +{{- define "vault.server.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.server.image "global" .Values.global) }} +{{- end -}} + +{{/* +Create the name of the service account to use (Vault Server) +*/}} +{{- define "vault.server.serviceAccountName" -}} +{{- if .Values.server.serviceAccount.create -}} + {{ default (include "vault.server.fullname" .) .Values.server.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.server.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Name of the server ConfigMap +*/}} +{{- define "vault.server.configmapName" -}} +{{- if .Values.server.existingConfigMap -}} + {{ include "common.tplvalues.render" (dict "value" .Values.server.existingConfigMap "context" $) }} +{{- else -}} + {{ include "vault.server.fullname" . }} +{{- end -}} +{{- end -}} + +{{/* +Return the proper Vault Kubernetes Injector fullname +*/}} +{{- define "vault.injector.fullname" -}} +{{- printf "%s-%s" (include "common.names.fullname" .) "injector" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Return the proper Vault Kubernetes Injector fullname (with namespace) +(removing image- prefix to avoid name length issues) +*/}} +{{- define "vault.injector.fullname.namespace" -}} +{{- printf "%s-%s" (include "common.names.fullname.namespace" .) "injector" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Return the proper Vault Kubernetes Injector image name +*/}} +{{- define "vault.injector.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.injector.image "global" .Values.global) }} +{{- end -}} + +{{/* +Create the name of the service account to use (Vault Kubernetes Injector) +*/}} +{{- define "vault.injector.serviceAccountName" -}} +{{- if .Values.injector.serviceAccount.create -}} + {{ default (include "vault.injector.fullname" .) .Values.injector.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.injector.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Return the proper Vault CSI Provider fullname +*/}} +{{- define "vault.csi-provider.fullname" -}} +{{- printf "%s-%s" (include "common.names.fullname" .) "csi-provider" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Return the proper Vault CSI Provider fullname (with namespace) +*/}} +{{- define "vault.csi-provider.fullname.namespace" -}} +{{- printf "%s-%s" (include "common.names.fullname.namespace" .) "csi-provider" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Return the proper Vault CSI Provider image name +*/}} +{{- define "vault.csi-provider.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.csiProvider.image "global" .Values.global) }} +{{- end -}} + +{{/* +Create the name of the service account to use (Vault CSI Provider) +*/}} +{{- define "vault.csi-provider.serviceAccountName" -}} +{{- if .Values.csiProvider.serviceAccount.create -}} + {{ default (include "vault.csi-provider.fullname" .) .Values.csiProvider.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.csiProvider.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Name of the server ConfigMap +*/}} +{{- define "vault.csi-provider.configmapName" -}} +{{- if .Values.csiProvider.existingConfigMap -}} + {{ include "common.tplvalues.render" (dict "value" .Values.csiProvider.existingConfigMap "context" $) }} +{{- else -}} + {{ include "vault.server.fullname" . }} +{{- end -}} +{{- end -}} + +{{/* +Return the proper image name (for the init container volume-permissions image) +*/}} +{{- define "vault.volumePermissions.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.volumePermissions.image "global" .Values.global) }} +{{- end -}} + +{{/* +Validate values for Vault. +*/}} +{{- define "vault.validateValues" -}} +{{- $messages := list -}} +{{- $messages := append $messages (include "vault.validateValues.controllers" .) -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message -}} +{{- end -}} +{{- end -}} + +{{/* +Function to validate the controller deployment +*/}} +{{- define "vault.validateValues.controllers" -}} +{{- if not (or .Values.server.enabled .Values.csiProvider.enabled .Values.injector.enabled) -}} +vault: Missing controllers. At least one controller should be enabled. +{{- end -}} +{{- end -}} diff --git a/backing-services/vault/templates/csi-provider/clusterrole.yaml b/backing-services/vault/templates/csi-provider/clusterrole.yaml new file mode 100644 index 0000000..23955b3 --- /dev/null +++ b/backing-services/vault/templates/csi-provider/clusterrole.yaml @@ -0,0 +1,29 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.csiProvider.enabled .Values.csiProvider.rbac.create }} +kind: ClusterRole +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ include "vault.csi-provider.fullname.namespace" . }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.csiProvider.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: csi-provider + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: + - apiGroups: + - "" + resources: + - serviceaccounts/token + verbs: + - create + {{- if .Values.csiProvider.rbac.rules }} + {{- include "common.tplvalues.render" ( dict "value" .Values.csiProvider.rbac.rules "context" $ ) | nindent 2 }} + {{- end }} +{{- end }} diff --git a/backing-services/vault/templates/csi-provider/configmap.yaml b/backing-services/vault/templates/csi-provider/configmap.yaml new file mode 100644 index 0000000..2851440 --- /dev/null +++ b/backing-services/vault/templates/csi-provider/configmap.yaml @@ -0,0 +1,23 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.csiProvider.enabled (not .Values.csiProvider.existingConfigMap) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "vault.csi-provider.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.csiProvider.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: csi-provider + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + config.hcl: | + {{- include "common.tplvalues.render" (dict "value" .Values.csiProvider.config "context" $) | nindent 4 }} +{{- end }} diff --git a/backing-services/vault/templates/csi-provider/daemonset.yaml b/backing-services/vault/templates/csi-provider/daemonset.yaml new file mode 100644 index 0000000..b7ae742 --- /dev/null +++ b/backing-services/vault/templates/csi-provider/daemonset.yaml @@ -0,0 +1,250 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.csiProvider.enabled }} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ template "vault.csi-provider.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.csiProvider.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: csi-provider + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.csiProvider.updateStrategy }} + updateStrategy: {{- toYaml .Values.csiProvider.updateStrategy | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.csiProvider.podLabels .Values.commonLabels $versionLabel ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: csi-provider + template: + metadata: + {{- if .Values.csiProvider.podAnnotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.csiProvider.podAnnotations "context" $) | nindent 8 }} + {{- end }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: csi-provider + spec: + serviceAccountName: {{ template "vault.csi-provider.serviceAccountName" . }} + {{- include "vault.imagePullSecrets" . | nindent 6 }} + {{- if .Values.csiProvider.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.csiProvider.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.csiProvider.affinity }} + affinity: {{- include "common.tplvalues.render" ( dict "value" .Values.csiProvider.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.csiProvider.podAffinityPreset "component" "csi-provider" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.csiProvider.podAntiAffinityPreset "component" "csi-provider" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.csiProvider.nodeAffinityPreset.type "key" .Values.csiProvider.nodeAffinityPreset.key "values" .Values.csiProvider.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.csiProvider.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" ( dict "value" .Values.csiProvider.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.csiProvider.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.csiProvider.tolerations "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.csiProvider.priorityClassName }} + priorityClassName: {{ .Values.csiProvider.priorityClassName | quote }} + {{- end }} + {{- if .Values.csiProvider.schedulerName }} + schedulerName: {{ .Values.csiProvider.schedulerName | quote }} + {{- end }} + {{- if .Values.csiProvider.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.csiProvider.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.csiProvider.podSecurityContext.enabled }} + securityContext: {{- omit .Values.csiProvider.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.csiProvider.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.csiProvider.terminationGracePeriodSeconds }} + {{- end }} + initContainers: + {{- if .Values.csiProvider.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.csiProvider.initContainers "context" $) | nindent 8 }} + {{- end }} + containers: + - name: csi-provider + image: {{ template "vault.csi-provider.image" . }} + imagePullPolicy: {{ .Values.csiProvider.image.pullPolicy }} + {{- if .Values.csiProvider.provider.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.csiProvider.provider.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.csiProvider.provider.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.csiProvider.provider.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.csiProvider.provider.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.csiProvider.provider.args "context" $) | nindent 12 }} + {{- else }} + args: + - --endpoint=/provider/vault.sock + - --hmac-secret-name={{ printf "%s-hmac-key" (include "vault.csi-provider.fullname" .) }} + - --debug={{ .Values.csiProvider.image.debug }} + {{- end }} + env: + - name: VAULT_ADDR + value: "unix:///var/run/vault/agent.sock" + {{- if .Values.csiProvider.provider.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.csiProvider.provider.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.csiProvider.provider.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.csiProvider.provider.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.csiProvider.provider.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.csiProvider.provider.extraEnvVarsSecret "context" $) }} + {{- end }} + {{- if .Values.csiProvider.provider.resources }} + resources: {{- toYaml .Values.csiProvider.provider.resources | nindent 12 }} + {{- end }} + ports: + - name: http-health + containerPort: {{ .Values.csiProvider.provider.containerPorts.health }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.csiProvider.provider.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.csiProvider.provider.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.csiProvider.provider.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.csiProvider.provider.livenessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: /health/ready + port: http-health + {{- end }} + {{- if .Values.csiProvider.provider.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.csiProvider.provider.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.csiProvider.provider.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.csiProvider.provider.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: /health/ready + port: http-health + {{- end }} + {{- if .Values.csiProvider.provider.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.csiProvider.provider.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.csiProvider.provider.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.csiProvider.provider.startupProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: /health/ready + port: http-health + {{- end }} + {{- end }} + {{- if .Values.csiProvider.provider.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.csiProvider.provider.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + volumeMounts: + - name: providervol + mountPath: "/provider" + - name: agent-unix-socket + mountPath: /var/run/vault + {{- if .Values.csiProvider.provider.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.csiProvider.provider.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + - name: agent + image: {{ template "vault.csi-provider.image" . }} + imagePullPolicy: {{ .Values.csiProvider.image.pullPolicy }} + {{- if .Values.csiProvider.agent.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.csiProvider.agent.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.csiProvider.agent.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.csiProvider.agent.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.csiProvider.agent.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.csiProvider.agent.args "context" $) | nindent 12 }} + {{- else }} + args: + - agent + - -config=/bitnami/vault/conf/config.hcl + {{- if .Values.csiProvider.image.debug }} + - -log-level=debug + {{- end }} + {{- end }} + env: + {{- if .Values.csiProvider.agent.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.csiProvider.agent.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.csiProvider.agent.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.csiProvider.agent.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.csiProvider.agent.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.csiProvider.agent.extraEnvVarsSecret "context" $) }} + {{- end }} + {{- if .Values.csiProvider.agent.resources }} + resources: {{- toYaml .Values.csiProvider.agent.resources | nindent 12 }} + {{- end }} + ports: + - name: tcp + containerPort: {{ .Values.csiProvider.agent.containerPorts.tcp }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.csiProvider.agent.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.csiProvider.agent.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.csiProvider.agent.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.csiProvider.agent.livenessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: tcp + {{- end }} + {{- if .Values.csiProvider.agent.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.csiProvider.agent.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.csiProvider.agent.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.csiProvider.agent.readinessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: tcp + {{- end }} + {{- if .Values.csiProvider.agent.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.csiProvider.agent.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.csiProvider.agent.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.csiProvider.agent.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: tcp + {{- end }} + {{- end }} + {{- if .Values.csiProvider.agent.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.csiProvider.agent.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + volumeMounts: + - name: config + mountPath: /bitnami/vault/config + - name: agent-unix-socket + mountPath: /var/run/vault + {{- if .Values.csiProvider.agent.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.csiProvider.agent.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.csiProvider.sidecars }} + {{- include "common.tplvalues.render" ( dict "value" .Values.csiProvider.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: providervol + hostPath: + path: {{ .Values.csiProvider.secretStoreHostPath }} + - name: config + configMap: + name: {{ include "vault.csi-provider.configmapName" . }} + - name: agent-unix-socket + emptyDir: + medium: Memory + - name: tmp + emptyDir: {} + {{- if .Values.csiProvider.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.csiProvider.extraVolumes "context" $) | nindent 8 }} + {{- end }} +{{- end }} diff --git a/backing-services/vault/templates/csi-provider/role.yaml b/backing-services/vault/templates/csi-provider/role.yaml new file mode 100644 index 0000000..fb10926 --- /dev/null +++ b/backing-services/vault/templates/csi-provider/role.yaml @@ -0,0 +1,29 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.csiProvider.enabled .Values.csiProvider.rbac.create }} +kind: Role +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ include "vault.csi-provider.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.csiProvider.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: csi-provider + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get"] + resourceNames: + - {{ include "vault.csi-provider.fullname" . }} + - apiGroups: [""] + resources: ["secrets"] + verbs: ["create"] +{{- end }} diff --git a/backing-services/vault/templates/csi-provider/rolebinding.yaml b/backing-services/vault/templates/csi-provider/rolebinding.yaml new file mode 100644 index 0000000..3ed52f0 --- /dev/null +++ b/backing-services/vault/templates/csi-provider/rolebinding.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.csiProvider.enabled .Values.csiProvider.rbac.create }} +kind: RoleBinding +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ include "vault.csi-provider.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.csiProvider.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: csi-provider + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "vault.csi-provider.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "vault.csi-provider.serviceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} +{{- end }} diff --git a/backing-services/vault/templates/csi-provider/service-account.yaml b/backing-services/vault/templates/csi-provider/service-account.yaml new file mode 100644 index 0000000..ef7b09b --- /dev/null +++ b/backing-services/vault/templates/csi-provider/service-account.yaml @@ -0,0 +1,19 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.csiProvider.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "vault.csi-provider.serviceAccountName" . }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.csiProvider.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + {{- if or .Values.csiProvider.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.csiProvider.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.csiProvider.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/backing-services/vault/templates/extra-list.yaml b/backing-services/vault/templates/extra-list.yaml new file mode 100644 index 0000000..2d35a58 --- /dev/null +++ b/backing-services/vault/templates/extra-list.yaml @@ -0,0 +1,9 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/backing-services/vault/templates/injector/clusterrolebinding.yaml b/backing-services/vault/templates/injector/clusterrolebinding.yaml new file mode 100644 index 0000000..b9d6185 --- /dev/null +++ b/backing-services/vault/templates/injector/clusterrolebinding.yaml @@ -0,0 +1,27 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.injector.enabled .Values.injector.rbac.create }} +kind: ClusterRoleBinding +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ include "vault.injector.fullname.namespace" . }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.injector.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: injector + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "vault.injector.fullname.namespace" . }} +subjects: + - kind: ServiceAccount + name: {{ template "vault.injector.serviceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} +{{- end }} diff --git a/backing-services/vault/templates/injector/clusterroles.yaml b/backing-services/vault/templates/injector/clusterroles.yaml new file mode 100644 index 0000000..f9e3ef1 --- /dev/null +++ b/backing-services/vault/templates/injector/clusterroles.yaml @@ -0,0 +1,30 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.injector.enabled .Values.injector.rbac.create }} +kind: ClusterRole +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ include "vault.injector.fullname.namespace" . }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.injector.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: injector + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: + - apiGroups: ["admissionregistration.k8s.io"] + resources: ["mutatingwebhookconfigurations"] + verbs: + - "get" + - "list" + - "watch" + - "patch" + {{- if .Values.injector.rbac.rules }} + {{- include "common.tplvalues.render" ( dict "value" .Values.injector.rbac.rules "context" $ ) | nindent 2 }} + {{- end }} +{{- end }} diff --git a/backing-services/vault/templates/injector/deployment.yaml b/backing-services/vault/templates/injector/deployment.yaml new file mode 100644 index 0000000..b22b269 --- /dev/null +++ b/backing-services/vault/templates/injector/deployment.yaml @@ -0,0 +1,183 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.injector.enabled }} +apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} +kind: Deployment +metadata: + name: {{ template "vault.injector.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.injector.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: injector + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if not .Values.injector.autoscaling.enabled }} + replicas: {{ .Values.injector.replicaCount }} + {{- end }} + {{- if .Values.injector.updateStrategy }} + strategy: {{- toYaml .Values.injector.updateStrategy | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.injector.podLabels .Values.commonLabels $versionLabel ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: injector + template: + metadata: + {{- if .Values.injector.podAnnotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.injector.podAnnotations "context" $) | nindent 8 }} + {{- end }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: injector + spec: + serviceAccountName: {{ template "vault.injector.serviceAccountName" . }} + {{- include "vault.imagePullSecrets" . | nindent 6 }} + {{- if .Values.injector.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.injector.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.injector.affinity }} + affinity: {{- include "common.tplvalues.render" ( dict "value" .Values.injector.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.injector.podAffinityPreset "component" "injector" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.injector.podAntiAffinityPreset "component" "injector" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.injector.nodeAffinityPreset.type "key" .Values.injector.nodeAffinityPreset.key "values" .Values.injector.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.injector.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" ( dict "value" .Values.injector.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.injector.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.injector.tolerations "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.injector.priorityClassName }} + priorityClassName: {{ .Values.injector.priorityClassName | quote }} + {{- end }} + {{- if .Values.injector.schedulerName }} + schedulerName: {{ .Values.injector.schedulerName | quote }} + {{- end }} + {{- if .Values.injector.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.injector.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.injector.podSecurityContext.enabled }} + securityContext: {{- omit .Values.injector.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.injector.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.injector.terminationGracePeriodSeconds }} + {{- end }} + {{- if .Values.injector.initContainers }} + initContainers: + {{- include "common.tplvalues.render" (dict "value" .Values.injector.initContainers "context" $) | nindent 8 }} + {{- end }} + containers: + - name: sidecar-injector + image: {{ template "vault.injector.image" . }} + imagePullPolicy: {{ .Values.injector.image.pullPolicy }} + {{- if .Values.injector.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.injector.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.injector.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.injector.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.injector.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.injector.args "context" $) | nindent 12 }} + {{- else }} + args: + - agent-inject + - 2>&1 + {{- if .Values.injector.image.debug }} + - -log-level=debug + {{- end }} + {{- end }} + env: + - name: AGENT_INJECT_LISTEN + value: :{{ .Values.injector.containerPorts.https }} + - name: AGENT_INJECT_VAULT_ADDR + value: http://{{ include "vault.server.fullname" . }}:{{ .Values.server.service.general.ports.http }} + - name: AGENT_INJECT_VAULT_AUTH_PATH + value: auth/kubernetes + - name: AGENT_INJECT_VAULT_IMAGE + value: {{ include "vault.server.image" . | quote }} + - name: AGENT_INJECT_TLS_AUTO + value: {{ include "vault.injector.fullname.namespace" . | quote }} + {{- $host := include "vault.injector.fullname" . }} + {{- $ns := include "common.names.namespace" . }} + - name: AGENT_INJECT_TLS_AUTO_HOSTS + value: {{ $host }},{{ printf "%s.%s" $host $ns }},{{ printf "%s.%s.svc" $host $ns }} + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + {{- if .Values.injector.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.injector.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.injector.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.injector.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.injector.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.injector.extraEnvVarsSecret "context" $) }} + {{- end }} + {{- if .Values.injector.resources }} + resources: {{- toYaml .Values.injector.resources | nindent 12 }} + {{- end }} + ports: + - name: https + containerPort: {{ .Values.injector.containerPorts.https }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.injector.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.injector.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.injector.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.injector.livenessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: /health/ready + port: https + scheme: HTTPS + {{- end }} + {{- if .Values.injector.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.injector.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.injector.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.injector.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: /health/ready + port: https + scheme: HTTPS + {{- end }} + {{- if .Values.injector.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.injector.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.injector.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.injector.startupProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: /health/ready + port: https + scheme: HTTPS + {{- end }} + {{- end }} + {{- if .Values.injector.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.injector.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + volumeMounts: + {{- if .Values.injector.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.injector.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.injector.sidecars }} + {{- include "common.tplvalues.render" ( dict "value" .Values.injector.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + {{- if .Values.injector.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.injector.extraVolumes "context" $) | nindent 8 }} + {{- end }} +{{- end }} diff --git a/backing-services/vault/templates/injector/hpa.yaml b/backing-services/vault/templates/injector/hpa.yaml new file mode 100644 index 0000000..5c95903 --- /dev/null +++ b/backing-services/vault/templates/injector/hpa.yaml @@ -0,0 +1,50 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.injector.autoscaling.enabled }} +apiVersion: {{ include "common.capabilities.hpa.apiVersion" ( dict "context" $ ) }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ template "vault.injector.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.injector.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + scaleTargetRef: + apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} + kind: Deployment + name: {{ template "vault.injector.fullname" . }} + minReplicas: {{ .Values.injector.autoscaling.minReplicas }} + maxReplicas: {{ .Values.injector.autoscaling.maxReplicas }} + metrics: + {{- if .Values.injector.autoscaling.targetCPU }} + - type: Resource + resource: + name: cpu + {{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .) }} + targetAverageUtilization: {{ .Values.injector.autoscaling.targetCPU }} + {{- else }} + target: + type: Utilization + averageUtilization: {{ .Values.injector.autoscaling.targetCPU }} + {{- end }} + {{- end }} + {{- if .Values.injector.autoscaling.targetMemory }} + - type: Resource + resource: + name: memory + {{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .) }} + targetAverageUtilization: {{ .Values.injector.autoscaling.targetMemory }} + {{- else }} + target: + type: Utilization + averageUtilization: {{ .Values.injector.autoscaling.targetMemory }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/vault/templates/injector/mutating-webhook.yaml b/backing-services/vault/templates/injector/mutating-webhook.yaml new file mode 100644 index 0000000..4e4e6da --- /dev/null +++ b/backing-services/vault/templates/injector/mutating-webhook.yaml @@ -0,0 +1,43 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.injector.enabled }} +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: {{ include "vault.injector.fullname.namespace" . }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.injector.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: injector + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +webhooks: + - name: vault.hashicorp.com + failurePolicy: Ignore + matchPolicy: Exact + sideEffects: None + timeoutSeconds: 30 + admissionReviewVersions: ["v1", "v1beta1"] + clientConfig: + service: + name: {{ include "vault.injector.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + path: "/mutate" + caBundle: "" + rules: + - operations: ["CREATE", "UPDATE"] + apiGroups: [""] + apiVersions: ["v1"] + resources: ["pods"] + objectSelector: + matchExpressions: + - key: app.kubernetes.io/component + operator: NotIn + values: + - injector +{{- end }} diff --git a/backing-services/vault/templates/injector/pdb.yaml b/backing-services/vault/templates/injector/pdb.yaml new file mode 100644 index 0000000..475f15e --- /dev/null +++ b/backing-services/vault/templates/injector/pdb.yaml @@ -0,0 +1,32 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.injector.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ template "vault.injector.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.injector.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: injector + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.injector.pdb.minAvailable }} + minAvailable: {{ .Values.injector.pdb.minAvailable }} + {{- end }} + {{- if .Values.injector.pdb.maxUnavailable }} + maxUnavailable: {{ .Values.injector.pdb.maxUnavailable }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.injector.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: injector +{{- end }} diff --git a/backing-services/vault/templates/injector/role.yaml b/backing-services/vault/templates/injector/role.yaml new file mode 100644 index 0000000..9926c3c --- /dev/null +++ b/backing-services/vault/templates/injector/role.yaml @@ -0,0 +1,59 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.injector.enabled .Values.injector.rbac.create }} +kind: Role +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ printf "%s-leader-election" (include "vault.injector.fullname.namespace" .) | trunc 63 | trimSuffix "-" }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.injector.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: injector + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - "" + resources: + - configmaps/status + verbs: + - get + - update + - patch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - apiGroups: + - "coordination.k8s.io" + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +{{- end }} diff --git a/backing-services/vault/templates/injector/rolebinding.yaml b/backing-services/vault/templates/injector/rolebinding.yaml new file mode 100644 index 0000000..45de949 --- /dev/null +++ b/backing-services/vault/templates/injector/rolebinding.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.injector.enabled .Values.injector.rbac.create }} +kind: RoleBinding +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ printf "%s-leader-election" (include "vault.injector.fullname.namespace" .) | trunc 63 | trimSuffix "-" }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.injector.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: injector + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ printf "%s-leader-election" (include "vault.injector.fullname.namespace" .) | trunc 63 | trimSuffix "-" }} +subjects: + - kind: ServiceAccount + name: {{ template "vault.injector.serviceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} +{{- end }} diff --git a/backing-services/vault/templates/injector/service-account.yaml b/backing-services/vault/templates/injector/service-account.yaml new file mode 100644 index 0000000..0ecb377 --- /dev/null +++ b/backing-services/vault/templates/injector/service-account.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.injector.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "vault.injector.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.injector.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + {{- if or .Values.injector.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.injector.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.injector.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/backing-services/vault/templates/injector/service.yaml b/backing-services/vault/templates/injector/service.yaml new file mode 100644 index 0000000..7d576e7 --- /dev/null +++ b/backing-services/vault/templates/injector/service.yaml @@ -0,0 +1,58 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.injector.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "vault.injector.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.injector.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: injector + {{- if or .Values.injector.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.injector.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.injector.service.type }} + {{- if and .Values.injector.service.clusterIP (eq .Values.injector.service.type "ClusterIP") }} + clusterIP: {{ .Values.injector.service.clusterIP }} + {{- end }} + {{- if .Values.injector.service.sessionAffinity }} + sessionAffinity: {{ .Values.injector.service.sessionAffinity }} + {{- end }} + {{- if .Values.injector.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.injector.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + {{- if or (eq .Values.injector.service.type "LoadBalancer") (eq .Values.injector.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.injector.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.injector.service.type "LoadBalancer") (not (empty .Values.injector.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ .Values.injector.service.loadBalancerSourceRanges }} + {{- end }} + {{- if and (eq .Values.injector.service.type "LoadBalancer") (not (empty .Values.injector.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.injector.service.loadBalancerIP }} + {{- end }} + ports: + - name: https + port: {{ .Values.injector.service.ports.https }} + protocol: TCP + {{- if and (or (eq .Values.injector.service.type "NodePort") (eq .Values.injector.service.type "LoadBalancer")) (not (empty .Values.injector.service.nodePorts.https)) }} + nodePort: {{ .Values.injector.service.nodePorts.https }} + {{- else if eq .Values.injector.service.type "ClusterIP" }} + nodePort: null + {{- end }} + targetPort: https + {{- if .Values.injector.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.injector.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.injector.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: injector +{{- end }} diff --git a/backing-services/vault/templates/server/active-service.yaml b/backing-services/vault/templates/server/active-service.yaml new file mode 100644 index 0000000..d82a5f6 --- /dev/null +++ b/backing-services/vault/templates/server/active-service.yaml @@ -0,0 +1,72 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.server.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-active" (include "vault.server.fullname" .) | trunc 63 | trimSuffix "-" }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: server + {{- if or .Values.server.service.active.annotations .Values.commonAnnotations }} + annotations: + {{- if or .Values.server.service.active.annotations .Values.commonAnnotations (and .Values.server.metrics.enabled .Values.server.metrics.annotations) }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.server.service.active.annotations .Values.commonAnnotations ) "context" . ) }} + {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} + {{- if and .Values.server.metrics.enabled .Values.server.metrics.annotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.server.metrics.annotations "context" $) | nindent 4 }} + {{- end }} + {{- end }} +spec: + type: {{ .Values.server.service.active.type }} + {{- if and .Values.server.service.active.clusterIP (eq .Values.server.service.active.type "ClusterIP") }} + clusterIP: {{ .Values.server.service.active.clusterIP }} + {{- end }} + {{- if .Values.server.service.active.sessionAffinity }} + sessionAffinity: {{ .Values.server.service.active.sessionAffinity }} + {{- end }} + {{- if .Values.server.service.active.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.server.service.active.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + {{- if or (eq .Values.server.service.active.type "LoadBalancer") (eq .Values.server.service.active.type "NodePort") }} + externalTrafficPolicy: {{ .Values.server.service.active.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.server.service.active.type "LoadBalancer") (not (empty .Values.server.service.active.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ .Values.server.service.active.loadBalancerSourceRanges }} + {{- end }} + {{- if and (eq .Values.server.service.active.type "LoadBalancer") (not (empty .Values.server.service.active.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.server.service.active.loadBalancerIP }} + {{- end }} + ports: + - name: http + port: {{ .Values.server.service.active.ports.http }} + protocol: TCP + {{- if and (or (eq .Values.server.service.active.type "NodePort") (eq .Values.server.service.active.type "LoadBalancer")) (not (empty .Values.server.service.active.nodePorts.http)) }} + nodePort: {{ .Values.server.service.active.nodePorts.http }} + {{- else if eq .Values.server.service.active.type "ClusterIP" }} + nodePort: null + {{- end }} + targetPort: http + - name: https-internal + port: {{ .Values.server.service.active.ports.internal }} + protocol: TCP + {{- if and (or (eq .Values.server.service.active.type "NodePort") (eq .Values.server.service.active.type "LoadBalancer")) (not (empty .Values.server.service.active.nodePorts.internal)) }} + nodePort: {{ .Values.server.service.active.nodePorts.internal }} + {{- else if eq .Values.server.service.active.type "ClusterIP" }} + nodePort: null + {{- end }} + targetPort: https-internal + {{- if .Values.server.service.active.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.service.active.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.injector.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: server + app.kubernetes.io/part-of: vault + vault-active: "true" +{{- end }} diff --git a/backing-services/vault/templates/server/clusterrolebinding.yaml b/backing-services/vault/templates/server/clusterrolebinding.yaml new file mode 100644 index 0000000..effec54 --- /dev/null +++ b/backing-services/vault/templates/server/clusterrolebinding.yaml @@ -0,0 +1,25 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.server.enabled .Values.server.rbac.create }} +kind: ClusterRoleBinding +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ include "vault.server.fullname.namespace" . }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: server + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:auth-delegator +subjects: + - kind: ServiceAccount + name: {{ template "vault.server.serviceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} +{{- end }} diff --git a/backing-services/vault/templates/server/configmap.yaml b/backing-services/vault/templates/server/configmap.yaml new file mode 100644 index 0000000..8392c1f --- /dev/null +++ b/backing-services/vault/templates/server/configmap.yaml @@ -0,0 +1,21 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.server.enabled (not .Values.server.existingConfigMap) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "vault.server.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: server + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + config.hcl: | + {{- include "common.tplvalues.render" (dict "value" .Values.server.config "context" $) | nindent 4 }} +{{- end }} diff --git a/backing-services/vault/templates/server/ingress.yaml b/backing-services/vault/templates/server/ingress.yaml new file mode 100644 index 0000000..728be42 --- /dev/null +++ b/backing-services/vault/templates/server/ingress.yaml @@ -0,0 +1,61 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.server.ingress.enabled }} +apiVersion: {{ include "common.capabilities.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ template "vault.server.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: server + {{- if or .Values.server.ingress.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.server.ingress.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.server.ingress.ingressClassName (eq "true" (include "common.ingress.supportsIngressClassname" .)) }} + ingressClassName: {{ .Values.server.ingress.ingressClassName | quote }} + {{- end }} + rules: + {{- if .Values.server.ingress.hostname }} + - host: {{ .Values.server.ingress.hostname }} + http: + paths: + {{- if .Values.server.ingress.extraPaths }} + {{- toYaml .Values.server.ingress.extraPaths | nindent 10 }} + {{- end }} + - path: {{ .Values.server.ingress.path }} + {{- if eq "true" (include "common.ingress.supportsPathType" .) }} + pathType: {{ .Values.server.ingress.pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (printf "%s-active" (include "vault.server.fullname" .) | trunc 63 | trimSuffix "-") "servicePort" "http" "context" $) | nindent 14 }} + {{- end }} + {{- range .Values.server.ingress.extraHosts }} + - host: {{ .name | quote }} + http: + paths: + - path: {{ default "/" .path }} + {{- if eq "true" (include "common.ingress.supportsPathType" $) }} + pathType: {{ default "ImplementationSpecific" .pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (printf "%s-active" (include "vault.server.fullname" $) | trunc 63 | trimSuffix "-") "servicePort" "http" "context" $) | nindent 14 }} + {{- end }} + {{- if .Values.server.ingress.extraRules }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.ingress.extraRules "context" $) | nindent 4 }} + {{- end }} + {{- if or (and .Values.server.ingress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.server.ingress.annotations )) .Values.server.ingress.selfSigned)) .Values.server.ingress.extraTls }} + tls: + {{- if and .Values.server.ingress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.server.ingress.annotations )) .Values.server.ingress.selfSigned) }} + - hosts: + - {{ .Values.server.ingress.hostname | quote }} + secretName: {{ printf "%s-tls" .Values.server.ingress.hostname }} + {{- end }} + {{- if .Values.server.ingress.extraTls }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.ingress.extraTls "context" $) | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/vault/templates/server/pdb.yaml b/backing-services/vault/templates/server/pdb.yaml new file mode 100644 index 0000000..5cd4f69 --- /dev/null +++ b/backing-services/vault/templates/server/pdb.yaml @@ -0,0 +1,30 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.server.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ template "vault.server.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: server + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.server.pdb.minAvailable }} + minAvailable: {{ .Values.server.pdb.minAvailable }} + {{- end }} + {{- if .Values.server.pdb.maxUnavailable }} + maxUnavailable: {{ .Values.server.pdb.maxUnavailable }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.server.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: server +{{- end }} diff --git a/backing-services/vault/templates/server/rolebinding.yaml b/backing-services/vault/templates/server/rolebinding.yaml new file mode 100644 index 0000000..48afe83 --- /dev/null +++ b/backing-services/vault/templates/server/rolebinding.yaml @@ -0,0 +1,46 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.server.enabled .Values.server.rbac.create }} +kind: RoleBinding +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ printf "%s-leader-election" (include "vault.server.fullname" .) | trunc 63 | trimSuffix "-" }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: server + namespace: {{ include "common.names.namespace" . | quote }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ printf "%s-leader-election" (include "vault.server.fullname" .) | trunc 63 | trimSuffix "-" }} +subjects: + - kind: ServiceAccount + name: {{ template "vault.server.serviceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} +--- +kind: RoleBinding +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ printf "%s-discovery" (include "vault.server.fullname" .) | trunc 63 | trimSuffix "-" }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: server + namespace: {{ include "common.names.namespace" . | quote }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ printf "%s-discovery" (include "vault.server.fullname" .) | trunc 63 | trimSuffix "-" }} +subjects: + - kind: ServiceAccount + name: {{ template "vault.server.serviceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} +{{- end }} diff --git a/backing-services/vault/templates/server/roles.yaml b/backing-services/vault/templates/server/roles.yaml new file mode 100644 index 0000000..04e27eb --- /dev/null +++ b/backing-services/vault/templates/server/roles.yaml @@ -0,0 +1,73 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.server.enabled .Values.server.rbac.create }} +kind: Role +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ printf "%s-leader-election" (include "vault.server.fullname" .) | trunc 63 | trimSuffix "-" }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: server + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - "" + resources: + - configmaps/status + verbs: + - get + - update + - patch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - apiGroups: + - "coordination.k8s.io" + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +--- +kind: Role +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ printf "%s-discovery" (include "vault.server.fullname" .) | trunc 63 | trimSuffix "-" }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: server + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: + - apiGroups: [""] + resources: ["pods"] + verbs: ["get", "watch", "list", "update", "patch"] +{{- end }} diff --git a/backing-services/vault/templates/server/service-account.yaml b/backing-services/vault/templates/server/service-account.yaml new file mode 100644 index 0000000..f1ddce5 --- /dev/null +++ b/backing-services/vault/templates/server/service-account.yaml @@ -0,0 +1,18 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.server.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "vault.server.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.server.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.server.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.server.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/backing-services/vault/templates/server/service-headless.yaml b/backing-services/vault/templates/server/service-headless.yaml new file mode 100644 index 0000000..4c40323 --- /dev/null +++ b/backing-services/vault/templates/server/service-headless.yaml @@ -0,0 +1,34 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.server.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-headless" (include "vault.server.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: server + {{- if or .Values.server.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.server.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + publishNotReadyAddresses: true + ports: + - name: http + port: {{ .Values.server.service.general.ports.http }} + targetPort: http + - name: https-internal + port: {{ .Values.server.service.general.ports.internal }} + targetPort: https-internal + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.server.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: server +{{- end }} diff --git a/backing-services/vault/templates/server/service.yaml b/backing-services/vault/templates/server/service.yaml new file mode 100644 index 0000000..2ad4803 --- /dev/null +++ b/backing-services/vault/templates/server/service.yaml @@ -0,0 +1,65 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.server.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "vault.server.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: server + {{- if or .Values.server.service.general.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.server.service.general.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.server.service.general.type }} + {{- if and .Values.server.service.general.clusterIP (eq .Values.server.service.general.type "ClusterIP") }} + clusterIP: {{ .Values.server.service.general.clusterIP }} + {{- end }} + {{- if .Values.server.service.general.sessionAffinity }} + sessionAffinity: {{ .Values.server.service.general.sessionAffinity }} + {{- end }} + {{- if .Values.server.service.general.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.server.service.general.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + {{- if or (eq .Values.server.service.general.type "LoadBalancer") (eq .Values.server.service.general.type "NodePort") }} + externalTrafficPolicy: {{ .Values.server.service.general.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.server.service.general.type "LoadBalancer") (not (empty .Values.server.service.general.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ .Values.server.service.general.loadBalancerSourceRanges }} + {{- end }} + {{- if and (eq .Values.server.service.general.type "LoadBalancer") (not (empty .Values.server.service.general.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.server.service.general.loadBalancerIP }} + {{- end }} + ports: + - name: http + port: {{ .Values.server.service.general.ports.http }} + protocol: TCP + {{- if and (or (eq .Values.server.service.general.type "NodePort") (eq .Values.server.service.general.type "LoadBalancer")) (not (empty .Values.server.service.general.nodePorts.http)) }} + nodePort: {{ .Values.server.service.general.nodePorts.http }} + {{- else if eq .Values.server.service.general.type "ClusterIP" }} + nodePort: null + {{- end }} + targetPort: http + - name: https-internal + port: {{ .Values.server.service.general.ports.internal }} + protocol: TCP + {{- if and (or (eq .Values.server.service.general.type "NodePort") (eq .Values.server.service.general.type "LoadBalancer")) (not (empty .Values.server.service.general.nodePorts.internal)) }} + nodePort: {{ .Values.server.service.general.nodePorts.internal }} + {{- else if eq .Values.server.service.general.type "ClusterIP" }} + nodePort: null + {{- end }} + targetPort: https-internal + {{- if .Values.server.service.general.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.service.general.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.server.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: server +{{- end }} diff --git a/backing-services/vault/templates/server/servicemonitor.yaml b/backing-services/vault/templates/server/servicemonitor.yaml new file mode 100644 index 0000000..949cd92 --- /dev/null +++ b/backing-services/vault/templates/server/servicemonitor.yaml @@ -0,0 +1,50 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.server.metrics.enabled .Values.server.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "vault.server.fullname" . }} + namespace: {{ default (include "common.names.namespace" .) .Values.server.metrics.serviceMonitor.namespace | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.server.metrics.serviceMonitor.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: server + {{- if or .Values.server.metrics.serviceMonitor.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.server.metrics.serviceMonitor.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + jobLabel: {{ .Values.server.metrics.serviceMonitor.jobLabel | quote }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: server + {{- if .Values.server.metrics.serviceMonitor.selector }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.metrics.serviceMonitor.selector "context" $) | nindent 6 }} + {{- end }} + endpoints: + - port: http-metrics + path: "/metrics" + {{- if .Values.server.metrics.serviceMonitor.interval }} + interval: {{ .Values.server.metrics.serviceMonitor.interval }} + {{- end }} + {{- if .Values.server.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.server.metrics.serviceMonitor.scrapeTimeout }} + {{- end }} + {{- if .Values.server.metrics.serviceMonitor.honorLabels }} + honorLabels: {{ .Values.server.metrics.serviceMonitor.honorLabels }} + {{- end }} + {{- if .Values.server.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.server.metrics.serviceMonitor.metricRelabelings "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.server.metrics.serviceMonitor.relabelings }} + relabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.server.metrics.serviceMonitor.relabelings "context" $) | nindent 8 }} + {{- end }} + namespaceSelector: + matchNames: + - {{ include "common.names.namespace" . | quote }} +{{- end }} diff --git a/backing-services/vault/templates/server/statefulset.yaml b/backing-services/vault/templates/server/statefulset.yaml new file mode 100644 index 0000000..da278a5 --- /dev/null +++ b/backing-services/vault/templates/server/statefulset.yaml @@ -0,0 +1,271 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.server.enabled }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ template "vault.server.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: server + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.server.replicaCount }} + serviceName: {{ printf "%s-headless" (include "vault.server.fullname" .) }} + podManagementPolicy: {{ .Values.server.podManagementPolicy }} + {{- if .Values.server.updateStrategy }} + updateStrategy: {{- toYaml .Values.server.updateStrategy | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.server.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: server + template: + metadata: + {{- if .Values.server.podAnnotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.server.podAnnotations "context" $) | nindent 8 }} + {{- end }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: server + spec: + serviceAccountName: {{ template "vault.server.serviceAccountName" . }} + {{- include "vault.imagePullSecrets" . | nindent 6 }} + {{- if .Values.server.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.server.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.server.affinity }} + affinity: {{- include "common.tplvalues.render" ( dict "value" .Values.server.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.server.podAffinityPreset "component" "server" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.server.podAntiAffinityPreset "component" "server" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.server.nodeAffinityPreset.type "key" .Values.server.nodeAffinityPreset.key "values" .Values.server.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.server.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" ( dict "value" .Values.server.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.server.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.server.tolerations "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.server.priorityClassName }} + priorityClassName: {{ .Values.server.priorityClassName | quote }} + {{- end }} + {{- if .Values.server.schedulerName }} + schedulerName: {{ .Values.server.schedulerName | quote }} + {{- end }} + {{- if .Values.server.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.server.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.server.podSecurityContext.enabled }} + securityContext: {{- omit .Values.server.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.server.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.server.terminationGracePeriodSeconds }} + {{- end }} + initContainers: + {{- if and .Values.volumePermissions.enabled .Values.server.containerSecurityContext.enabled }} + - name: volume-permissions + image: {{ include "vault.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - sh + - -c + - | + mkdir -p {{ .Values.server.persistence.mountPath }} + find {{ .Values.server.persistence.mountPath }} -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | xargs --no-run-if-empty chown -R {{ .Values.server.containerSecurityContext.runAsUser }}:{{ .Values.server.podSecurityContext.fsGroup }} + {{- if .Values.volumePermissions.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.volumePermissions.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + volumeMounts: + - name: data + mountPath: {{ .Values.server.persistence.mountPath }} + {{- end }} + {{- if .Values.server.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.initContainers "context" $) | nindent 8 }} + {{- end }} + containers: + - name: server + image: {{ template "vault.server.image" . }} + imagePullPolicy: {{ .Values.server.image.pullPolicy }} + {{- if .Values.server.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.server.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.server.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.server.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.server.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.server.args "context" $) | nindent 12 }} + {{- else }} + args: + - server + - -config=/bitnami/vault/config/config.hcl + {{- if .Values.server.image.debug }} + - -log-level=debug + {{- end }} + {{- end }} + env: + - name: HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: VAULT_K8S_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: VAULT_K8S_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: VAULT_ADDR + value: {{ printf "http://127.0.0.1:%v" .Values.server.containerPorts.http | quote }} + - name: VAULT_API_ADDR + value: {{ printf "http://$(POD_IP):%v" .Values.server.containerPorts.http | quote }} + - name: HOSTNAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: VAULT_CLUSTER_ADDR + value: {{ printf "https://$(HOSTNAME).%s-headless:%v" ( include "vault.server.fullname" . ) .Values.server.containerPorts.internal | quote }} + - name: HOME + value: "/bitnami/vault/home" + {{- if .Values.server.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.server.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.server.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.server.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.server.extraEnvVarsSecret "context" $) }} + {{- end }} + {{- if .Values.server.resources }} + resources: {{- toYaml .Values.server.resources | nindent 12 }} + {{- end }} + ports: + - name: http + containerPort: {{ .Values.server.containerPorts.http }} + - name: https-internal + containerPort: {{ .Values.server.containerPorts.internal }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.server.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.server.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.server.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.server.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - vault + - status + - -tls-skip-verify + {{- end }} + {{- if .Values.server.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.server.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.server.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.server.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - vault + - status + - -tls-skip-verify + {{- end }} + {{- if .Values.server.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.server.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.server.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.server.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - vault + - status + - -tls-skip-verify + {{- end }} + {{- end }} + {{- if .Values.server.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.server.lifecycleHooks "context" $) | nindent 12 }} + {{- else }} + lifecycle: + # From upstream Vault helm chart: + # Vault container doesn't receive SIGTERM from Kubernetes + # and after the grace period ends, Kube sends SIGKILL. This + # causes issues with graceful shutdowns such as deregistering itself + # from Consul (zombie services). + preStop: + exec: + command: [ + "/bin/sh", "-ec", + # Adding a sleep here to give the pod eviction a + # chance to propagate, so requests will not be made + # to this pod while it's terminating + "sleep 5 && kill -SIGTERM $(pidof vault)", + ] + {{- end }} + volumeMounts: + - name: data + mountPath: {{ .Values.server.persistence.mountPath }} + - name: config + mountPath: /bitnami/vault/config + - name: home + mountPath: /bitnami/vault/home + {{- if .Values.server.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.server.sidecars }} + {{- include "common.tplvalues.render" ( dict "value" .Values.server.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: config + configMap: + name: {{ include "vault.server.configmapName" . }} + - name: home + emptyDir: {} + {{- if .Values.server.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.extraVolumes "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.server.persistence.enabled (not .Values.server.persistence.existingClaim) }} + volumeClaimTemplates: + - metadata: + name: data + annotations: + {{- if .Values.server.persistence.annotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.server.persistence.annotations "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.commonLabels }} + labels: {{- include "common.tplvalues.render" (dict "value" .Values.commonLabels "context" $) | nindent 10 }} + {{- end }} + spec: + {{- if .Values.server.persistence.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.server.persistence.dataSource "context" $) | nindent 4 }} + {{- end }} + accessModes: + {{- range .Values.server.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.server.persistence.size | quote }} + {{- include "common.storage.class" (dict "persistence" .Values.server.persistence "global" .Values.global) | nindent 8 }} + {{- if .Values.server.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.server.persistence.selector "context" $) | nindent 10 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/vault/templates/server/tls-secret.yaml b/backing-services/vault/templates/server/tls-secret.yaml new file mode 100644 index 0000000..8f20b1f --- /dev/null +++ b/backing-services/vault/templates/server/tls-secret.yaml @@ -0,0 +1,48 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.server.ingress.enabled }} +{{- if .Values.server.ingress.secrets }} +{{- range .Values.server.ingress.secrets }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .name }} + namespace: {{ include "common.names.namespace" $ | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $.Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: server + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ .certificate | b64enc }} + tls.key: {{ .key | b64enc }} +--- +{{- end }} +{{- end }} +{{- if and .Values.server.ingress.tls .Values.server.ingress.selfSigned }} +{{- $secretName := printf "%s-tls" .Values.server.ingress.hostname }} +{{- $ca := genCA "server-ca" 365 }} +{{- $cert := genSignedCert .Values.server.ingress.hostname nil (list .Values.server.ingress.hostname) 365 $ca }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: vault + app.kubernetes.io/component: server + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.crt" "defaultValue" $cert.Cert "context" $) }} + tls.key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.key" "defaultValue" $cert.Key "context" $) }} + ca.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }} +{{- end }} +{{- end }} diff --git a/backing-services/vault/values.yaml b/backing-services/vault/values.yaml new file mode 100644 index 0000000..cb27c19 --- /dev/null +++ b/backing-services/vault/values.yaml @@ -0,0 +1,1584 @@ +# Copyright VMware, Inc. +# SPDX-License-Identifier: APACHE-2.0 + +## @section Global parameters +## 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, imagePullSecrets and storageClass +## + +## @param global.imageRegistry Global Docker image registry +## @param global.imagePullSecrets Global Docker registry secret names as an array +## @param global.storageClass Global StorageClass for Persistent Volume(s) +## +global: + imageRegistry: "" + ## E.g. + ## imagePullSecrets: + ## - myRegistryKeySecretName + ## + imagePullSecrets: [] + storageClass: "" + +## @section Common parameters +## + +## @param kubeVersion Override Kubernetes version +## +kubeVersion: "" +## @param nameOverride String to partially override common.names.name +## +nameOverride: "" +## @param fullnameOverride String to fully override common.names.fullname +## +fullnameOverride: "" +## @param namespaceOverride String to fully override common.names.namespace +## +namespaceOverride: "" +## @param commonLabels Labels to add to all deployed objects +## +commonLabels: {} +## @param commonAnnotations Annotations to add to all deployed objects +## +commonAnnotations: {} +## @param clusterDomain Kubernetes cluster domain name +## +clusterDomain: cluster.local +## @param extraDeploy Array of extra objects to deploy with the release +## +extraDeploy: [] + +## Enable diagnostic mode in the deployment +## +diagnosticMode: + ## @param diagnosticMode.enabled Enable diagnostic mode (all probes will be disabled and the command will be overridden) + ## + enabled: false + ## @param diagnosticMode.command Command to override all containers in the deployment + ## + command: + - sleep + ## @param diagnosticMode.args Args to override all containers in the deployment + ## + args: + - infinity + + +## @section Vault Server Parameters +## +server: + ## @param server.enabled Enable Vault Server + ## + enabled: true + ## Bitnami Vault Server image + ## ref: https://hub.docker.com/r/bitnami/vault/tags/ + ## @param server.image.registry [default: REGISTRY_NAME] Vault Server image registry + ## @param server.image.repository [default: REPOSITORY_NAME/vault] Vault Server image repository + ## @skip server.image.tag Vault Server image tag (immutable tags are recommended) + ## @param server.image.digest Vault Server image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag image tag (immutable tags are recommended) + ## @param server.image.pullPolicy Vault Server image pull policy + ## @param server.image.pullSecrets Vault Server image pull secrets + ## @param server.image.debug Enable Vault Server image debug mode + ## + image: + registry: docker.io + repository: bitnami/vault + tag: 1.15.4-debian-11-r0 + digest: "" + ## 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Enable debug mode + ## + debug: false + ## @param server.replicaCount Number of Vault Server replicas to deploy + ## + replicaCount: 1 + ## @param server.podManagementPolicy Pod management policy + ## Should be initialized one by one when building the replicaset for the first time + ## + podManagementPolicy: Parallel + ## @param server.containerPorts.http Vault Server http container port + ## @param server.containerPorts.internal Vault Server internal (HTTPS) container port + ## + containerPorts: + http: 8200 + internal: 8201 + ## Configure extra options for Vault Server containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param server.livenessProbe.enabled Enable livenessProbe on Vault Server containers + ## @param server.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param server.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param server.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param server.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param server.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + # As the user needs to manually unseal the server, we don't want Vault to restart + enabled: false + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + successThreshold: 1 + ## @param server.readinessProbe.enabled Enable readinessProbe on Vault Server containers + ## @param server.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param server.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param server.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param server.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param server.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + successThreshold: 1 + ## @param server.startupProbe.enabled Enable startupProbe on Vault Server containers + ## @param server.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param server.startupProbe.periodSeconds Period seconds for startupProbe + ## @param server.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param server.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param server.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + successThreshold: 1 + ## @param server.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param server.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param server.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## Vault Server resource requests and limits + ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## @param server.resources.limits The resources limits for the Vault Server containers + ## @param server.resources.requests The requested resources for the Vault Server containers + ## + resources: + limits: {} + requests: {} + ## Configure Pods Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param server.podSecurityContext.enabled Enabled Vault Server pods' Security Context + ## @param server.podSecurityContext.fsGroup Set Vault Server pod's Security Context fsGroup + ## + podSecurityContext: + enabled: true + fsGroup: 1001 + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param server.containerSecurityContext.enabled Enabled containers' Security Context + ## @param server.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param server.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param server.containerSecurityContext.privileged Set container's Security Context privileged + ## @param server.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param server.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param server.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param server.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + + ## @param server.command Override default container command (useful when using custom images) + ## + command: [] + ## @param server.args Override default container args (useful when using custom images) + ## + args: [] + ## @param server.hostAliases Vault Server pods host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param server.config [string] Vault server configuration (evaluated as a template) + ## + config: | + disable_mlock = true + ui = true + listener "tcp" { + tls_disable = 1 + address = "[::]:{{ .Values.server.containerPorts.http }}" + cluster_address = "[::]:{{ .Values.server.containerPorts.internal }}" + {{- if .Values.server.metrics.enabled }} + # Enable unauthenticated metrics access (necessary for Prometheus Operator) + telemetry { + unauthenticated_metrics_access = "true" + } + {{- end }} + } + storage "raft" { + path = "{{ .Values.server.persistence.mountPath }}" + } + + service_registration "kubernetes" {} + + ## @param server.existingConfigMap name of a ConfigMap with existing configuration for the server + ## + existingConfigMap: "" + + ## @param server.podLabels Extra labels for Vault Server pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param server.podAnnotations Annotations for Vault Server pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param server.podAffinityPreset Pod affinity preset. Ignored if `server.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param server.podAntiAffinityPreset Pod anti-affinity preset. Ignored if `server.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Pod Disruption Budget configuration + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb + ## @param server.pdb.create Enable/disable a Pod Disruption Budget creation + ## @param server.pdb.minAvailable Minimum number/percentage of pods that should remain scheduled + ## @param server.pdb.maxUnavailable Maximum number/percentage of pods that may be made unavailable + ## + pdb: + create: false + minAvailable: 1 + maxUnavailable: "" + ## Node server.affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param server.nodeAffinityPreset.type Node affinity preset type. Ignored if `server.affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param server.nodeAffinityPreset.key Node label key to match. Ignored if `server.affinity` is set + ## + key: "" + ## @param server.nodeAffinityPreset.values Node label values to match. Ignored if `server.affinity` is set + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param server.affinity Affinity for Vault Server pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## NOTE: `server.podAffinityPreset`, `server.podAntiAffinityPreset`, and `server.nodeAffinityPreset` will be ignored when it's set + ## + affinity: {} + ## @param server.nodeSelector Node labels for Vault Server pods assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + ## @param server.tolerations Tolerations for Vault Server pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param server.updateStrategy.type Vault Server statefulset strategy type + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## + updateStrategy: + ## StrategyType + ## Can be set to RollingUpdate or OnDelete + ## + type: RollingUpdate + + ## @param server.priorityClassName Vault Server pods' priorityClassName + ## + priorityClassName: "" + ## @param server.topologySpreadConstraints Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#spread-constraints-for-pods + ## + topologySpreadConstraints: [] + ## @param server.schedulerName Name of the k8s scheduler (other than default) for Vault Server pods + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param server.terminationGracePeriodSeconds Seconds Redmine pod needs to terminate gracefully + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods + ## + terminationGracePeriodSeconds: "" + ## @param server.lifecycleHooks for the Vault Server container(s) to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param server.extraEnvVars Array with extra environment variables to add to Vault Server nodes + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param server.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for Vault Server nodes + ## + extraEnvVarsCM: "" + ## @param server.extraEnvVarsSecret Name of existing Secret containing extra env vars for Vault Server nodes + ## + extraEnvVarsSecret: "" + ## @param server.extraVolumes Optionally specify extra list of additional volumes for the Vault Server pod(s) + ## + extraVolumes: [] + ## @param server.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the Vault Server container(s) + ## + extraVolumeMounts: [] + ## @param server.sidecars Add additional sidecar containers to the Vault Server pod(s) + ## e.g: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param server.initContainers Add additional init containers to the Vault Server pod(s) + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + ## e.g: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## command: ['sh', '-c', 'echo "hello world"'] + ## + initContainers: [] + + ## @section Vault Server Traffic Exposure Parameters + ## + service: + general: + ## @param server.service.general.type Vault Server service type + ## + type: ClusterIP + ## @param server.service.general.ports.http Vault Server service HTTP port + ## @param server.service.general.ports.internal Vault Server internal port + ## + ports: + http: 8200 + internal: 8201 + ## Node ports to expose + ## @param server.service.general.nodePorts.http Node port for HTTP + ## @param server.service.general.nodePorts.internal Node port for HTTP + ## NOTE: choose port between <30000-32767> + ## + nodePorts: + http: "" + internal: "" + ## @param server.service.general.clusterIP Vault Server service Cluster IP + ## e.g.: + ## clusterIP: None + ## + clusterIP: "" + ## @param server.service.general.loadBalancerIP Vault Server service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerIP: "" + ## @param server.service.general.loadBalancerSourceRanges Vault Server service Load Balancer sources + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param server.service.general.externalTrafficPolicy Vault Server service external traffic policy + ## ref http://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-web-source-ip + ## + externalTrafficPolicy: Cluster + ## @param server.service.general.annotations Additional custom annotations for Vault Server service + ## + annotations: {} + ## @param server.service.general.extraPorts Extra ports to expose in Vault Server service (normally used with the `sidecars` value) + ## + extraPorts: [] + ## @param server.service.general.sessionAffinity Control where web requests go, to the same pod or round-robin + ## Values: WebIP or None + ## ref: https://kubernetes.io/docs/user-guide/services/ + ## + sessionAffinity: None + ## @param server.service.general.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## webIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + active: + ## @param server.service.active.type Vault Server service type + ## + type: ClusterIP + ## @param server.service.active.ports.http Vault Server service HTTP port + ## @param server.service.active.ports.internal Vault Server internal port + ## + ports: + http: 8200 + internal: 8201 + ## Node ports to expose + ## @param server.service.active.nodePorts.http Node port for HTTP + ## @param server.service.active.nodePorts.internal Node port for HTTP + ## NOTE: choose port between <30000-32767> + ## + nodePorts: + http: "" + internal: "" + ## @param server.service.active.clusterIP Vault Server service Cluster IP + ## e.g.: + ## clusterIP: None + ## + clusterIP: "" + ## @param server.service.active.loadBalancerIP Vault Server service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerIP: "" + ## @param server.service.active.loadBalancerSourceRanges Vault Server service Load Balancer sources + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param server.service.active.externalTrafficPolicy Vault Server service external traffic policy + ## ref http://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-web-source-ip + ## + externalTrafficPolicy: Cluster + ## @param server.service.active.annotations Additional custom annotations for Vault Server service + ## + annotations: {} + ## @param server.service.active.extraPorts Extra ports to expose in Vault Server service (normally used with the `sidecars` value) + ## + extraPorts: [] + ## @param server.service.active.sessionAffinity Control where web requests go, to the same pod or round-robin + ## Values: WebIP or None + ## ref: https://kubernetes.io/docs/user-guide/services/ + ## + sessionAffinity: None + ## @param server.service.active.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## webIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + + ## ref: http://kubernetes.io/docs/user-guide/ingress/ + ## + ingress: + ## @param server.ingress.enabled Enable ingress record generation for Vault + ## + enabled: false + ## @param server.ingress.pathType Ingress path type + ## + pathType: ImplementationSpecific + ## @param server.ingress.apiVersion Force Ingress API version (automatically detected if not set) + ## + apiVersion: "" + ## @param server.ingress.hostname Default host for the ingress record + ## + hostname: vault.local + ## @param server.ingress.ingressClassName IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+) + ## This is supported in Kubernetes 1.18+ and required if you have more than one IngressClass marked as the default for your cluster . + ## ref: https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/ + ## + ingressClassName: "" + ## @param server.ingress.path Default path for the ingress record + ## NOTE: You may need to set this to '/*' in order to use this with ALB ingress controllers + ## + path: / + ## @param server.ingress.annotations Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. + ## Use this parameter to set the required annotations for cert-manager, see + ## ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations + ## e.g: + ## annotations: + ## kubernetes.io/ingress.class: nginx + ## cert-manager.io/cluster-issuer: cluster-issuer-name + ## + annotations: {} + ## @param server.ingress.tls Enable TLS configuration for the host defined at `client.ingress.hostname` parameter + ## TLS certificates will be retrieved from a TLS secret with name: `{{- printf "%s-tls" .Values.ingress.hostname }}` + ## You can: + ## - Use the `client.ingress.secrets` parameter to create this TLS secret + ## - Rely on cert-manager to create it by setting the corresponding annotations + ## - Rely on Helm to create self-signed certificates by setting `client.ingress.selfSigned=true` + ## + tls: false + ## @param server.ingress.selfSigned Create a TLS secret for this ingress record using self-signed certificates generated by Helm + ## + selfSigned: false + ## @param server.ingress.extraHosts An array with additional hostname(s) to be covered with the ingress record + ## e.g: + ## extraHosts: + ## - name: vault.local + ## path: / + ## + extraHosts: [] + ## @param server.ingress.extraPaths An array with additional arbitrary paths that may need to be added to the ingress under the main host + ## e.g: + ## extraPaths: + ## - path: /* + ## backend: + ## serviceName: ssl-redirect + ## servicePort: use-annotation + ## + extraPaths: [] + ## @param server.ingress.extraTls TLS configuration for additional hostname(s) to be covered with this ingress record + ## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#tls + ## e.g: + ## extraTls: + ## - hosts: + ## - vault.local + ## secretName: vault.local-tls + ## + extraTls: [] + ## @param server.ingress.secrets Custom TLS certificates as secrets + ## NOTE: 'key' and 'certificate' are expected in PEM format + ## NOTE: 'name' should line up with a 'secretName' set further up + ## If it is not set and you're using cert-manager, this is unneeded, as it will create a secret for you with valid certificates + ## If it is not set and you're NOT using cert-manager either, self-signed certificates will be created valid for 365 days + ## It is also possible to create and manage the certificates outside of this helm chart + ## Please see README.md for more information + ## e.g: + ## secrets: + ## - name: vault.local-tls + ## key: |- + ## -----BEGIN RSA PRIVATE KEY----- + ## ... + ## -----END RSA PRIVATE KEY----- + ## certificate: |- + ## -----BEGIN CERTIFICATE----- + ## ... + ## -----END CERTIFICATE----- + ## + secrets: [] + ## @param server.ingress.extraRules Additional rules to be covered with this ingress record + ## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-rules + ## e.g: + ## extraRules: + ## - host: example.local + ## http: + ## path: / + ## backend: + ## service: + ## name: example-svc + ## port: + ## name: http + ## + extraRules: [] + + + + ## @section Vault Server RBAC Parameters + ## + + ## RBAC configuration + ## + rbac: + ## @param server.rbac.create Specifies whether RBAC resources should be created + ## + create: true + + ## ServiceAccount configuration + ## + serviceAccount: + ## @param server.serviceAccount.create Specifies whether a ServiceAccount should be created + ## + create: true + ## @param server.serviceAccount.name The name of the ServiceAccount to use. + ## If not set and create is true, a name is generated using the common.names.fullname template + ## + name: "" + ## @param server.serviceAccount.annotations Additional Service Account annotations (evaluated as a template) + ## + annotations: {} + ## @param server.serviceAccount.automountServiceAccountToken Automount service account token for the server service account + ## + automountServiceAccountToken: true + + ## @section Source Conttroller Persistence Parameters + ## ref: https://kubernetes.io/docs/user-guide/persistent-volumes/ + ## + persistence: + ## @param server.persistence.enabled Enable persistence using Persistent Volume Claims + ## + enabled: true + ## @param server.persistence.mountPath Persistent Volume mount root path + ## + mountPath: /bitnami/vault/data + ## @param server.persistence.storageClass 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 + ## + storageClass: "" + ## @param server.persistence.accessModes [array] Persistent Volume access modes + ## + accessModes: + - ReadWriteOnce + ## @param server.persistence.size Persistent Volume size + ## + size: 10Gi + ## @param server.persistence.dataSource Custom PVC data source + ## + dataSource: {} + ## @param server.persistence.annotations Annotations for the PVC + ## + annotations: {} + ## @param server.persistence.selector Selector to match an existing Persistent Volume (this value is evaluated as a template) + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## @param server.persistence.existingClaim The name of an existing PVC to use for persistence + ## + existingClaim: "" + + + ## @section Vault Server Metrics Parameters + ## + + ## Prometheus metrics + ## + metrics: + ## @param server.metrics.enabled Enable the export of Prometheus metrics + ## + enabled: false + ## @param server.metrics.annotations [object] Annotations for the server service in order to scrape metrics + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "{{ .Values.server.service.general.ports.http }}" + ## Prometheus Operator ServiceMonitor configuration + ## + serviceMonitor: + ## @param server.metrics.serviceMonitor.enabled if `true`, creates a Prometheus Operator ServiceMonitor (also requires `metrics.enabled` to be `true`) + ## + enabled: false + ## @param server.metrics.serviceMonitor.namespace Namespace in which Prometheus is running + ## + namespace: "" + ## @param server.metrics.serviceMonitor.annotations Additional custom annotations for the ServiceMonitor + ## + annotations: {} + ## @param server.metrics.serviceMonitor.labels Extra labels for the ServiceMonitor + ## + labels: {} + ## @param server.metrics.serviceMonitor.jobLabel The name of the label on the target service to use as the job name in Prometheus + ## + jobLabel: "" + ## @param server.metrics.serviceMonitor.honorLabels honorLabels chooses the metric's labels on collisions with target labels + ## + honorLabels: false + ## @param server.metrics.serviceMonitor.interval Interval at which metrics should be scraped. + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint + ## e.g: + ## interval: 10s + ## + interval: "" + ## @param server.metrics.serviceMonitor.scrapeTimeout Timeout after which the scrape is ended + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint + ## e.g: + ## scrapeTimeout: 10s + ## + scrapeTimeout: "" + ## @param server.metrics.serviceMonitor.metricRelabelings Specify additional relabeling of metrics + ## + metricRelabelings: [] + ## @param server.metrics.serviceMonitor.relabelings Specify general relabeling + ## + relabelings: [] + ## @param server.metrics.serviceMonitor.selector Prometheus instance selector labels + ## ref: https://github.com/bitnami/charts/tree/main/bitnami/prometheus-operator#prometheus-configuration + ## selector: + ## prometheus: my-prometheus + ## + selector: {} + + +## @section Vault CSI Provider Parameters +## +csiProvider: + ## @param csiProvider.enabled Enable Vault CSI Provider + ## (NOTE: This is disabled in upstream Vault chart because it requires plugins in the K8s cluster) + ## + enabled: false + ## Bitnami Vault CSI Provider image + ## ref: https://hub.docker.com/r/bitnami/vault-csi-provider/tags/ + ## @param csiProvider.image.registry [default: REGISTRY_NAME] Vault CSI Provider image registry + ## @param csiProvider.image.repository [default: REPOSITORY_NAME/vault-csi-provider] Vault CSI Provider image repository + ## @skip csiProvider.image.tag Vault CSI Provider image tag (immutable tags are recommended) + ## @param csiProvider.image.digest Vault CSI Provider image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag image tag (immutable tags are recommended) + ## @param csiProvider.image.pullPolicy Vault CSI Provider image pull policy + ## @param csiProvider.image.pullSecrets Vault CSI Provider image pull secrets + ## @param csiProvider.image.debug Enable Vault CSI Provider image debug mode + ## + image: + registry: docker.io + repository: bitnami/vault-csi-provider + tag: 1.4.1-debian-11-r3 + digest: "" + ## 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Enable debug mode + ## + debug: false + + ## @param csiProvider.config [string] Vault CSI Provider configuration (evaluated as a template) + ## + config: | + vault { + "address" = "http://{{ include "vault.server.fullname" . }}:{{ .Values.server.service.general.ports.http }} + } + + cache {} + + listener "unix" { + address = "/var/run/vault/agent.sock" + tls_disable = true + } + + ## @param csiProvider.existingConfigMap name of a ConfigMap with existing configuration for the CSI Provider + ## + existingConfigMap: "" + + ## @param csiProvider.secretStoreHostPath Path to the host CSI Provider folder + ## + secretStoreHostPath: "/etc/kubernetes/secrets-store-csi-providers" + + ## @param csiProvider.hostAliases Vault CSI Provider pods host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param csiProvider.podLabels Extra labels for Vault CSI Provider pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param csiProvider.podAnnotations Annotations for Vault CSI Provider pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param csiProvider.podAffinityPreset Pod affinity preset. Ignored if `csiProvider.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param csiProvider.podAntiAffinityPreset Pod anti-affinity preset. Ignored if `csiProvider.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Node csiProvider.affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param csiProvider.nodeAffinityPreset.type Node affinity preset type. Ignored if `csiProvider.affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param csiProvider.nodeAffinityPreset.key Node label key to match. Ignored if `csiProvider.affinity` is set + ## + key: "" + ## @param csiProvider.nodeAffinityPreset.values Node label values to match. Ignored if `csiProvider.affinity` is set + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param csiProvider.affinity Affinity for Vault CSI Provider pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## NOTE: `csiProvider.podAffinityPreset`, `csiProvider.podAntiAffinityPreset`, and `csiProvider.nodeAffinityPreset` will be ignored when it's set + ## + affinity: {} + ## @param csiProvider.nodeSelector Node labels for Vault CSI Provider pods assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + ## @param csiProvider.tolerations Tolerations for Vault CSI Provider pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param csiProvider.updateStrategy.type Vault CSI Provider statefulset strategy type + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## + updateStrategy: + ## StrategyType + ## Can be set to RollingUpdate or OnDelete + ## + type: RollingUpdate + + ## @param csiProvider.priorityClassName Vault CSI Provider pods' priorityClassName + ## + priorityClassName: "" + ## @param csiProvider.topologySpreadConstraints Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#spread-constraints-for-pods + ## + topologySpreadConstraints: [] + ## @param csiProvider.schedulerName Name of the k8s scheduler (other than default) for Vault CSI Provider pods + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param csiProvider.terminationGracePeriodSeconds Seconds Redmine pod needs to terminate gracefully + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods + ## + terminationGracePeriodSeconds: "" + ## @param csiProvider.extraVolumes Optionally specify extra list of additional volumes for the Vault CSI Provider pod(s) + ## + extraVolumes: [] + ## @param csiProvider.sidecars Add additional sidecar containers to the Vault CSI Provider pod(s) + ## e.g: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param csiProvider.initContainers Add additional init containers to the Vault CSI Provider pod(s) + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + ## e.g: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## command: ['sh', '-c', 'echo "hello world"'] + ## + initContainers: [] + + ## Configure Pods Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param csiProvider.podSecurityContext.enabled Enabled CSI Provider pods' Security Context + ## @param csiProvider.podSecurityContext.fsGroup Set CSI Provider pod's Security Context fsGroup + ## + podSecurityContext: + enabled: true + fsGroup: 1001 + + provider: + ## @param csiProvider.provider.containerPorts.health CSI Provider health container port + ## + containerPorts: + health: 8080 + ## Configure extra options for CSI Provider container' liveness and readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param csiProvider.provider.livenessProbe.enabled Enable livenessProbe on CSI Provider container + ## @param csiProvider.provider.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param csiProvider.provider.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param csiProvider.provider.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param csiProvider.provider.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param csiProvider.provider.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + successThreshold: 1 + ## @param csiProvider.provider.readinessProbe.enabled Enable readinessProbe on CSI Provider container + ## @param csiProvider.provider.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param csiProvider.provider.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param csiProvider.provider.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param csiProvider.provider.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param csiProvider.provider.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + successThreshold: 1 + ## @param csiProvider.provider.startupProbe.enabled Enable startupProbe on CSI Provider container + ## @param csiProvider.provider.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param csiProvider.provider.startupProbe.periodSeconds Period seconds for startupProbe + ## @param csiProvider.provider.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param csiProvider.provider.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param csiProvider.provider.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + successThreshold: 1 + ## @param csiProvider.provider.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param csiProvider.provider.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param csiProvider.provider.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## CSI Provider resource requests and limits + ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## @param csiProvider.provider.resources.limits The resources limits for the CSI Provider container + ## @param csiProvider.provider.resources.requests The requested resources for the CSI Provider container + ## + resources: + limits: {} + requests: {} + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param csiProvider.provider.containerSecurityContext.enabled Enabled containers' Security Context + ## @param csiProvider.provider.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param csiProvider.provider.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param csiProvider.provider.containerSecurityContext.privileged Set container's Security Context privileged + ## @param csiProvider.provider.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param csiProvider.provider.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param csiProvider.provider.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param csiProvider.provider.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + + ## @param csiProvider.provider.command Override default container command (useful when using custom images) + ## + command: [] + ## @param csiProvider.provider.args Override default container args (useful when using custom images) + ## + args: [] + + ## @param csiProvider.provider.lifecycleHooks for the CSI Provider container(s) to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param csiProvider.provider.extraEnvVars Array with extra environment variables to add to CSI Provider nodes + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param csiProvider.provider.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for CSI Provider nodes + ## + extraEnvVarsCM: "" + ## @param csiProvider.provider.extraEnvVarsSecret Name of existing Secret containing extra env vars for CSI Provider nodes + ## + extraEnvVarsSecret: "" + + ## @param csiProvider.provider.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the Vault CSI Provider container + ## + extraVolumeMounts: [] + + agent: + ## @param csiProvider.agent.containerPorts.tcp CSI Provider Agent metrics container port + ## + containerPorts: + tcp: 8200 + ## Configure extra options for CSI Provider Agent container' liveness and readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param csiProvider.agent.livenessProbe.enabled Enable livenessProbe on CSI Provider Agent container + ## @param csiProvider.agent.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param csiProvider.agent.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param csiProvider.agent.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param csiProvider.agent.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param csiProvider.agent.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + successThreshold: 1 + ## @param csiProvider.agent.readinessProbe.enabled Enable readinessProbe on CSI Provider Agent container + ## @param csiProvider.agent.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param csiProvider.agent.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param csiProvider.agent.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param csiProvider.agent.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param csiProvider.agent.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + successThreshold: 1 + ## @param csiProvider.agent.startupProbe.enabled Enable startupProbe on CSI Provider Agent container + ## @param csiProvider.agent.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param csiProvider.agent.startupProbe.periodSeconds Period seconds for startupProbe + ## @param csiProvider.agent.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param csiProvider.agent.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param csiProvider.agent.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + successThreshold: 1 + ## @param csiProvider.agent.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param csiProvider.agent.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param csiProvider.agent.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param csiProvider.agent.containerSecurityContext.enabled Enabled containers' Security Context + ## @param csiProvider.agent.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param csiProvider.agent.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param csiProvider.agent.containerSecurityContext.privileged Set container's Security Context privileged + ## @param csiProvider.agent.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param csiProvider.agent.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param csiProvider.agent.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param csiProvider.agent.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## CSI Provider Agent resource requests and limits + ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## @param csiProvider.agent.resources.limits The resources limits for the CSI Provider Agent container + ## @param csiProvider.agent.resources.requests The requested resources for the CSI Provider Agent container + ## + resources: + limits: {} + requests: {} + + ## @param csiProvider.agent.command Override default container command (useful when using custom images) + ## + command: [] + ## @param csiProvider.agent.args Override default container args (useful when using custom images) + ## + args: [] + + ## @param csiProvider.agent.lifecycleHooks for the CSI Provider Agent container(s) to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param csiProvider.agent.extraEnvVars Array with extra environment variables to add to CSI Provider Agent nodes + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param csiProvider.agent.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for CSI Provider Agent nodes + ## + extraEnvVarsCM: "" + ## @param csiProvider.agent.extraEnvVarsSecret Name of existing Secret containing extra env vars for CSI Provider Agent nodes + ## + extraEnvVarsSecret: "" + + ## @param csiProvider.agent.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the CSI Provider container(s) + ## + extraVolumeMounts: [] + + ## @section Vault CSI Provider RBAC Parameters + ## + + ## RBAC configuration + ## + rbac: + ## @param csiProvider.rbac.create Specifies whether RBAC resources should be created + ## + create: true + ## @param csiProvider.rbac.rules Custom RBAC rules to set + ## e.g: + ## rules: + ## - apiGroups: + ## - "" + ## resources: + ## - pods + ## verbs: + ## - get + ## - list + ## + rules: [] + + ## ServiceAccount configuration + ## + serviceAccount: + ## @param csiProvider.serviceAccount.create Specifies whether a ServiceAccount should be created + ## + create: true + ## @param csiProvider.serviceAccount.name The name of the ServiceAccount to use. + ## If not set and create is true, a name is generated using the common.names.fullname template + ## + name: "" + ## @param csiProvider.serviceAccount.annotations Additional Service Account annotations (evaluated as a template) + ## + annotations: {} + ## @param csiProvider.serviceAccount.automountServiceAccountToken Automount service account token for the server service account + ## + automountServiceAccountToken: true + + +## @section Vault Kubernetes Injector Parameters +## +injector: + ## @param injector.enabled Enable Vault Kubernetes Injector + ## + enabled: true + ## Bitnami Vault Kubernetes Injector image + ## ref: https://hub.docker.com/r/bitnami/vault-k8s/tags/ + ## @param injector.image.registry [default: REGISTRY_NAME] Vault Kubernetes Injector image registry + ## @param injector.image.repository [default: REPOSITORY_NAME/vault-k8s] Vault Kubernetes Injector image repository + ## @skip injector.image.tag Vault Kubernetes Injector image tag (immutable tags are recommended) + ## @param injector.image.digest Vault Kubernetes Injector image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag image tag (immutable tags are recommended) + ## @param injector.image.pullPolicy Vault Kubernetes Injector image pull policy + ## @param injector.image.pullSecrets Vault Kubernetes Injector image pull secrets + ## @param injector.image.debug Enable Vault Kubernetes Injector image debug mode + ## + image: + registry: docker.io + repository: bitnami/vault-k8s + tag: 1.3.1-debian-11-r3 + digest: "" + ## 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Enable debug mode + ## + debug: false + ## @param injector.replicaCount Number of Vault Kubernetes Injector replicas to deploy + ## + replicaCount: 1 + ## @param injector.containerPorts.https Vault Kubernetes Injector metrics container port + ## + containerPorts: + https: 8080 + ## Configure extra options for Vault Kubernetes Injector containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param injector.livenessProbe.enabled Enable livenessProbe on Vault Kubernetes Injector containers + ## @param injector.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param injector.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param injector.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param injector.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param injector.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + successThreshold: 1 + ## @param injector.readinessProbe.enabled Enable readinessProbe on Vault Kubernetes Injector containers + ## @param injector.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param injector.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param injector.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param injector.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param injector.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + successThreshold: 1 + ## @param injector.startupProbe.enabled Enable startupProbe on Vault Kubernetes Injector containers + ## @param injector.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param injector.startupProbe.periodSeconds Period seconds for startupProbe + ## @param injector.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param injector.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param injector.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + successThreshold: 1 + ## @param injector.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param injector.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param injector.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## Vault Kubernetes Injector resource requests and limits + ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## @param injector.resources.limits The resources limits for the Vault Kubernetes Injector containers + ## @param injector.resources.requests The requested resources for the Vault Kubernetes Injector containers + ## + resources: + limits: {} + requests: {} + ## Configure Pods Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param injector.podSecurityContext.enabled Enabled Vault Kubernetes Injector pods' Security Context + ## @param injector.podSecurityContext.fsGroup Set Vault Kubernetes Injector pod's Security Context fsGroup + ## + podSecurityContext: + enabled: true + fsGroup: 1001 + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param injector.containerSecurityContext.enabled Enabled containers' Security Context + ## @param injector.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param injector.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param injector.containerSecurityContext.privileged Set container's Security Context privileged + ## @param injector.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param injector.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param injector.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param injector.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + + ## @param injector.command Override default container command (useful when using custom images) + ## + command: [] + ## @param injector.args Override default container args (useful when using custom images) + ## + args: [] + ## @param injector.hostAliases Vault Kubernetes Injector pods host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param injector.podLabels Extra labels for Vault Kubernetes Injector pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param injector.podAnnotations Annotations for Vault Kubernetes Injector pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param injector.podAffinityPreset Pod affinity preset. Ignored if `injector.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param injector.podAntiAffinityPreset Pod anti-affinity preset. Ignored if `injector.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Pod Disruption Budget configuration + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb + ## @param injector.pdb.create Enable/disable a Pod Disruption Budget creation + ## @param injector.pdb.minAvailable Minimum number/percentage of pods that should remain scheduled + ## @param injector.pdb.maxUnavailable Maximum number/percentage of pods that may be made unavailable + ## + pdb: + create: false + minAvailable: 1 + maxUnavailable: "" + ## Autoscaling configuration + ## ref: https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/ + ## @param injector.autoscaling.enabled Enable autoscaling for injector + ## @param injector.autoscaling.minReplicas Minimum number of injector replicas + ## @param injector.autoscaling.maxReplicas Maximum number of injector replicas + ## @param injector.autoscaling.targetCPU Target CPU utilization percentage + ## @param injector.autoscaling.targetMemory Target Memory utilization percentage + ## + autoscaling: + enabled: false + minReplicas: "" + maxReplicas: "" + targetCPU: "" + targetMemory: "" + ## Node injector.affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param injector.nodeAffinityPreset.type Node affinity preset type. Ignored if `injector.affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param injector.nodeAffinityPreset.key Node label key to match. Ignored if `injector.affinity` is set + ## + key: "" + ## @param injector.nodeAffinityPreset.values Node label values to match. Ignored if `injector.affinity` is set + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param injector.affinity Affinity for Vault Kubernetes Injector pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## NOTE: `injector.podAffinityPreset`, `injector.podAntiAffinityPreset`, and `injector.nodeAffinityPreset` will be ignored when it's set + ## + affinity: {} + ## @param injector.nodeSelector Node labels for Vault Kubernetes Injector pods assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + ## @param injector.tolerations Tolerations for Vault Kubernetes Injector pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param injector.updateStrategy.type Vault Kubernetes Injector statefulset strategy type + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## + updateStrategy: + ## StrategyType + ## Can be set to RollingUpdate or OnDelete + ## + type: RollingUpdate + + ## @param injector.priorityClassName Vault Kubernetes Injector pods' priorityClassName + ## + priorityClassName: "" + ## @param injector.topologySpreadConstraints Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#spread-constraints-for-pods + ## + topologySpreadConstraints: [] + ## @param injector.schedulerName Name of the k8s scheduler (other than default) for Vault Kubernetes Injector pods + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param injector.terminationGracePeriodSeconds Seconds Redmine pod needs to terminate gracefully + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods + ## + terminationGracePeriodSeconds: "" + ## @param injector.lifecycleHooks for the Vault Kubernetes Injector container(s) to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param injector.extraEnvVars Array with extra environment variables to add to Vault Kubernetes Injector nodes + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param injector.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for Vault Kubernetes Injector nodes + ## + extraEnvVarsCM: "" + ## @param injector.extraEnvVarsSecret Name of existing Secret containing extra env vars for Vault Kubernetes Injector nodes + ## + extraEnvVarsSecret: "" + ## @param injector.extraVolumes Optionally specify extra list of additional volumes for the Vault Kubernetes Injector pod(s) + ## + extraVolumes: [] + ## @param injector.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the Vault Kubernetes Injector container(s) + ## + extraVolumeMounts: [] + ## @param injector.sidecars Add additional sidecar containers to the Vault Kubernetes Injector pod(s) + ## e.g: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param injector.initContainers Add additional init containers to the Vault Kubernetes Injector pod(s) + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + ## e.g: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## command: ['sh', '-c', 'echo "hello world"'] + ## + initContainers: [] + + ## @section Vault Kubernetes Injector Traffic Exposure Parameters + ## + service: + ## @param injector.service.type Vault Kubernetes Injector service type + ## + type: ClusterIP + ## @param injector.service.ports.https Vault Kubernetes Injector service HTTPS port + ## + ports: + https: 443 + ## Node ports to expose + ## @param injector.service.nodePorts.https Node port for HTTPS + ## NOTE: choose port between <30000-32767> + ## + nodePorts: + https: "" + ## @param injector.service.clusterIP Vault Kubernetes Injector service Cluster IP + ## e.g.: + ## clusterIP: None + ## + clusterIP: "" + ## @param injector.service.loadBalancerIP Vault Kubernetes Injector service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerIP: "" + ## @param injector.service.loadBalancerSourceRanges Vault Kubernetes Injector service Load Balancer sources + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param injector.service.externalTrafficPolicy Vault Kubernetes Injector service external traffic policy + ## ref http://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-web-source-ip + ## + externalTrafficPolicy: Cluster + ## @param injector.service.annotations Additional custom annotations for Vault Kubernetes Injector service + ## + annotations: {} + ## @param injector.service.extraPorts Extra ports to expose in Vault Kubernetes Injector service (normally used with the `sidecars` value) + ## + extraPorts: [] + ## @param injector.service.sessionAffinity Control where web requests go, to the same pod or round-robin + ## Values: WebIP or None + ## ref: https://kubernetes.io/docs/user-guide/services/ + ## + sessionAffinity: None + ## @param injector.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## webIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + + + ## @section Vault Kubernetes Injector RBAC Parameters + ## + + ## RBAC configuration + ## + rbac: + ## @param injector.rbac.create Specifies whether RBAC resources should be created + ## + create: true + ## @param injector.rbac.rules Custom RBAC rules to set + ## e.g: + ## rules: + ## - apiGroups: + ## - "" + ## resources: + ## - pods + ## verbs: + ## - get + ## - list + ## + rules: [] + + ## ServiceAccount configuration + ## + serviceAccount: + ## @param injector.serviceAccount.create Specifies whether a ServiceAccount should be created + ## + create: true + ## @param injector.serviceAccount.name The name of the ServiceAccount to use. + ## If not set and create is true, a name is generated using the common.names.fullname template + ## + name: "" + ## @param injector.serviceAccount.annotations Additional Service Account annotations (evaluated as a template) + ## + annotations: {} + ## @param injector.serviceAccount.automountServiceAccountToken Automount service account token for the server service account + ## + automountServiceAccountToken: true + +## 'volumePermissions' init container parameters +## Changes the owner and group of the persistent volume mount point to runAsUser:fsGroup values +## based on the podSecurityContext/containerSecurityContext parameters +## +volumePermissions: + ## @param volumePermissions.enabled Enable init container that changes the owner/group of the PV mount point to `runAsUser:fsGroup` + ## + enabled: false + ## OS Shell + Utility image + ## ref: https://hub.docker.com/r/bitnami/os-shell/tags/ + ## @param volumePermissions.image.registry [default: REGISTRY_NAME] OS Shell + Utility image registry + ## @param volumePermissions.image.repository [default: REPOSITORY_NAME/os-shell] OS Shell + Utility image repository + ## @skip volumePermissions.image.tag OS Shell + Utility image tag (immutable tags are recommended) + ## @param volumePermissions.image.digest OS Shell + Utility image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param volumePermissions.image.pullPolicy OS Shell + Utility image pull policy + ## @param volumePermissions.image.pullSecrets OS Shell + Utility image pull secrets + ## + image: + registry: docker.io + repository: bitnami/os-shell + tag: 11-debian-11-r92 + digest: "" + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Init container's resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param volumePermissions.resources.limits The resources limits for the init container + ## @param volumePermissions.resources.requests The requested resources for the init container + ## + resources: + limits: {} + requests: {} + ## Init container Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param volumePermissions.containerSecurityContext.enabled Enable init container's Security Context + ## @param volumePermissions.containerSecurityContext.runAsUser Set init container's Security Context runAsUser + ## + containerSecurityContext: + enabled: true + runAsUser: 0 diff --git a/backing-services/vcluster/.helmignore b/backing-services/vcluster/.helmignore new file mode 100644 index 0000000..b6a3eb5 --- /dev/null +++ b/backing-services/vcluster/.helmignore @@ -0,0 +1,24 @@ +# 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/backing-services/vcluster/Chart.yaml b/backing-services/vcluster/Chart.yaml new file mode 100644 index 0000000..bdb349e --- /dev/null +++ b/backing-services/vcluster/Chart.yaml @@ -0,0 +1,26 @@ +apiVersion: v2 +appVersion: 0.21.1 +description: vcluster - Virtual Kubernetes Clusters +home: https://vcluster.com +icon: https://static.loft.sh/branding/logos/vcluster/vertical/vcluster_vertical.svg +keywords: +- developer +- development +- sharing +- share +- multi-tenancy +- tenancy +- cluster +- space +- namespace +- vcluster +- vclusters +maintainers: +- email: info@loft.sh + name: Loft Labs, Inc. + url: https://twitter.com/loft_sh +name: vcluster +sources: +- https://github.com/loft-sh/vcluster +type: application +version: 0.21.1 diff --git a/backing-services/vcluster/README.md b/backing-services/vcluster/README.md new file mode 100644 index 0000000..826388e --- /dev/null +++ b/backing-services/vcluster/README.md @@ -0,0 +1,64 @@ + +# vcluster + +## **[GitHub](https://github.com/loft-sh/vcluster)** • **[Website](https://www.vcluster.com)** • **[Quickstart](https://www.vcluster.com/docs/getting-started/setup)** • **[Documentation](https://www.vcluster.com/docs/what-are-virtual-clusters)** • **[Blog](https://loft.sh/blog)** • **[Twitter](https://twitter.com/loft_sh)** • **[Slack](https://slack.loft.sh/)** + +Create fully functional virtual Kubernetes clusters - Each vcluster runs inside a namespace of the underlying k8s cluster. It's cheaper than creating separate full-blown clusters and it offers better multi-tenancy and isolation than regular namespaces. + +## Prerequisites + +- Kubernetes 1.18+ +- Helm 3.10.0+ + +## Get Helm Repository Info + +```bash +helm repo add loft-sh https://charts.loft.sh +helm repo update +``` + +See [helm repo](https://helm.sh/docs/helm/helm_repo/) for command documentation. + +## Install Helm Chart + +```bash +helm upgrade [RELEASE_NAME] loft-sh/vcluster -n [RELEASE_NAMESPACE] --create-namespace --install +``` + +See [vcluster docs](https://vcluster.com/docs) for configuration options. + +See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation. + +## Connect to the vcluster + +In order to connect to the installed vcluster, please install [vcluster cli](https://www.vcluster.com/docs/getting-started/setup) and run: + +```bash +vcluster connect [RELEASE_NAME] -n [RELEASE_NAMESPACE] +``` + +## Uninstall Helm Chart + +```bash +helm uninstall [RELEASE_NAME] +``` + +This removes all the Kubernetes components associated with the chart and deletes the release. + +See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command documentation. + +### Why Virtual Kubernetes Clusters? + +- **Cluster Scoped Resources**: much more powerful than simple namespaces (virtual clusters allow users to use CRDs, namespaces, cluster roles etc.) +- **Ease of Use**: usable in any Kubernetes cluster and created in seconds either via a single command or [cluster-api](https://github.com/loft-sh/cluster-api-provider-vcluster) +- **Cost Efficient**: much cheaper and efficient than "real" clusters (single pod and shared resources just like for namespaces) +- **Lightweight**: built upon the ultra-fast k3s distribution with minimal overhead per virtual cluster (other distributions work as well) +- **Strict isolation**: complete separate Kubernetes control plane and access point for each vcluster while still being able to share certain services of the underlying host cluster +- **Cluster Wide Permissions**: allow users to install apps which require cluster-wide permissions while being limited to actually just one namespace within the host cluster +- **Great for Testing**: allow you to test different Kubernetes versions inside a single host cluster which may have a different version than the virtual clusters + +Learn more on [www.vcluster.com](https://vcluster.com). + +![vcluster Intro](https://github.com/loft-sh/vcluster/raw/main/docs/static/media/vcluster-comparison.png) + +Learn more in the [documentation](https://vcluster.com/docs/what-are-virtual-clusters). diff --git a/backing-services/vcluster/repo.yaml b/backing-services/vcluster/repo.yaml new file mode 100644 index 0000000..d6c0e26 --- /dev/null +++ b/backing-services/vcluster/repo.yaml @@ -0,0 +1,4 @@ +mirrors: + "45.159.150.146:4158": + endpoint: + - http://45.159.150.146:4158 diff --git a/backing-services/vcluster/schoobus-onsite.values.yaml b/backing-services/vcluster/schoobus-onsite.values.yaml new file mode 100644 index 0000000..616aa92 --- /dev/null +++ b/backing-services/vcluster/schoobus-onsite.values.yaml @@ -0,0 +1,6 @@ +controlPlane: + advanced: + defaultImageRegistry: 45.159.150.146:4158 + distro: + k8s: + version: v1.31.1 diff --git a/backing-services/vcluster/templates/_backingstore.tpl b/backing-services/vcluster/templates/_backingstore.tpl new file mode 100644 index 0000000..d4c1235 --- /dev/null +++ b/backing-services/vcluster/templates/_backingstore.tpl @@ -0,0 +1,33 @@ +{{/* + is deploy etcd enabled? +*/}} +{{- define "vcluster.database.embedded.enabled" -}} +{{- $backingStores := 0 -}} +{{- if .Values.controlPlane.backingStore.etcd.embedded.enabled -}} +{{- $backingStores = add1 $backingStores -}} +{{- end -}} +{{- if .Values.controlPlane.backingStore.etcd.deploy.enabled -}} +{{- $backingStores = add1 $backingStores -}} +{{- end -}} +{{- if .Values.controlPlane.backingStore.database.embedded.enabled -}} +{{- $backingStores = add1 $backingStores -}} +{{- end -}} +{{- if .Values.controlPlane.backingStore.database.external.enabled -}} +{{- $backingStores = add1 $backingStores -}} +{{- end -}} +{{- if gt $backingStores 1 -}} +{{- fail "you can only enable one backingStore at the same time" -}} +{{- else if or (eq $backingStores 0) .Values.controlPlane.backingStore.database.embedded.enabled -}} +{{- true -}} +{{- end -}} +{{- end -}} + +{{/* + migrate from deployed etcd? +*/}} +{{- define "vcluster.etcd.embedded.migrate" -}} +{{- if and .Values.controlPlane.backingStore.etcd.embedded.enabled .Values.controlPlane.backingStore.etcd.embedded.migrateFromDeployedEtcd -}} +{{- true -}} +{{- end -}} +{{- end -}} + diff --git a/backing-services/vcluster/templates/_coredns.tpl b/backing-services/vcluster/templates/_coredns.tpl new file mode 100644 index 0000000..8ecd7c0 --- /dev/null +++ b/backing-services/vcluster/templates/_coredns.tpl @@ -0,0 +1,52 @@ +{{/* + Define a common coredns config +*/}} +{{- define "vcluster.corefile" -}} +Corefile: |- + {{- if .Values.controlPlane.coredns.overwriteConfig }} +{{ .Values.controlPlane.coredns.overwriteConfig | indent 8 }} + {{- else }} + .:1053 { + errors + health + ready + {{- if and .Values.controlPlane.coredns.embedded .Values.networking.resolveDNS }} + vcluster + {{- end }} + {{- if .Values.networking.advanced.proxyKubelets.byHostname }} + rewrite name regex .*\.nodes\.vcluster\.com kubernetes.default.svc.cluster.local + {{- end }} + kubernetes cluster.local in-addr.arpa ip6.arpa { + {{- if .Values.controlPlane.coredns.embedded }} + kubeconfig /data/vcluster/admin.conf + {{- end }} + pods insecure + {{- if .Values.networking.advanced.fallbackHostCluster }} + fallthrough cluster.local in-addr.arpa ip6.arpa + {{- else }} + fallthrough in-addr.arpa ip6.arpa + {{- end }} + } + hosts /etc/NodeHosts { + ttl 60 + reload 15s + fallthrough + } + prometheus :9153 + {{- if .Values.networking.advanced.fallbackHostCluster }} + forward . {{`{{.HOST_CLUSTER_DNS}}`}} + {{- else if .Values.policies.networkPolicy.enabled }} + forward . /etc/resolv.conf {{ .Values.policies.networkPolicy.fallbackDns }} { + policy sequential + } + {{- else }} + forward . /etc/resolv.conf + {{- end }} + cache 30 + loop + loadbalance + } + + import /etc/coredns/custom/*.server + {{- end }} +{{- end -}} diff --git a/backing-services/vcluster/templates/_distro.tpl b/backing-services/vcluster/templates/_distro.tpl new file mode 100644 index 0000000..ea4a5da --- /dev/null +++ b/backing-services/vcluster/templates/_distro.tpl @@ -0,0 +1,33 @@ +{{- define "vcluster.distro.env" -}} +{{- if and (eq (include "vcluster.distro" .) "k3s") .Values.controlPlane.distro.k3s.env -}} +{{ toYaml .Values.controlPlane.distro.k3s.env }} +{{- else if and (eq (include "vcluster.distro" .) "k8s") .Values.controlPlane.distro.k8s.env -}} +{{ toYaml .Values.controlPlane.distro.k8s.env }} +{{- else if and (eq (include "vcluster.distro" .) "k0s") .Values.controlPlane.distro.k0s.env -}} +{{ toYaml .Values.controlPlane.distro.k0s.env }} +{{- end -}} +{{- end -}} + +{{/* + vCluster Distro +*/}} +{{- define "vcluster.distro" -}} +{{- $distros := 0 -}} +{{- if .Values.controlPlane.distro.k3s.enabled -}} +k3s +{{- $distros = add1 $distros -}} +{{- end -}} +{{- if .Values.controlPlane.distro.k0s.enabled -}} +k0s +{{- $distros = add1 $distros -}} +{{- end -}} +{{- if .Values.controlPlane.distro.k8s.enabled -}} +k8s +{{- $distros = add1 $distros -}} +{{- end -}} +{{- if eq $distros 0 -}} +k8s +{{- else if gt $distros 1 -}} +{{- fail "you can only enable one distro at the same time" -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/vcluster/templates/_helper.tpl b/backing-services/vcluster/templates/_helper.tpl new file mode 100644 index 0000000..680bbbb --- /dev/null +++ b/backing-services/vcluster/templates/_helper.tpl @@ -0,0 +1,17 @@ +{{- define "vcluster.controlPlane.image" -}} +{{- $tag := .Chart.Version -}} +{{- if .Values.controlPlane.statefulSet.image.tag -}} +{{- $tag = .Values.controlPlane.statefulSet.image.tag -}} +{{- end -}} +{{- include "vcluster.image" (dict "defaultImageRegistry" .Values.controlPlane.advanced.defaultImageRegistry "tag" $tag "registry" .Values.controlPlane.statefulSet.image.registry "repository" .Values.controlPlane.statefulSet.image.repository) -}} +{{- end -}} + +{{- define "vcluster.image" -}} +{{- if .defaultImageRegistry -}} +{{ .defaultImageRegistry }}/{{ .repository }}:{{ .tag }} +{{- else if .registry -}} +{{ .registry }}/{{ .repository }}:{{ .tag }} +{{- else -}} +{{ .repository }}:{{ .tag }} +{{- end -}} +{{- end -}} diff --git a/backing-services/vcluster/templates/_init-containers.tpl b/backing-services/vcluster/templates/_init-containers.tpl new file mode 100644 index 0000000..edf4550 --- /dev/null +++ b/backing-services/vcluster/templates/_init-containers.tpl @@ -0,0 +1,307 @@ +{{- define "vcluster.initContainers" -}} +{{- if eq (include "vcluster.distro" .) "k3s" -}} +{{ include "vcluster.k3s.initContainers" . }} +{{- else if eq (include "vcluster.distro" .) "k8s" -}} +{{ include "vcluster.k8s.initContainers" . }} +{{- else if eq (include "vcluster.distro" .) "k0s" -}} +{{ include "vcluster.k0s.initContainers" . }} +{{- end -}} +{{- end -}} + +{{- define "vcluster.k8s.capabilities.version" -}} +{{/* We need to workaround here for unit tests because Capabilities.KubeVersion.Version is not supported, so we use .Chart.Version */}} +{{- if hasPrefix "test-" .Chart.Version -}} +{{- regexFind "^v[0-9]+\\.[0-9]+\\.[0-9]+" (trimPrefix "test-" .Chart.Version) -}} +{{- else -}} +{{- regexFind "^v[0-9]+\\.[0-9]+\\.[0-9]+" .Capabilities.KubeVersion.Version -}} +{{- end -}} +{{- end -}} + +{{/* Bump $defaultTag value whenever k8s version is bumped */}} +{{- define "vcluster.k8s.controllerManager.image.tag" -}} +{{- $defaultTag := "v1.31.1" -}} +{{- if and (not (empty .Values.controlPlane.distro.k8s.version)) (eq .Values.controlPlane.distro.k8s.controllerManager.image.tag $defaultTag) -}} +{{ .Values.controlPlane.distro.k8s.version }} +{{- else -}} +{{- if not (eq .Values.controlPlane.distro.k8s.controllerManager.image.tag $defaultTag) -}} +{{ .Values.controlPlane.distro.k8s.controllerManager.image.tag }} +{{- else if not (empty (include "vcluster.k8s.capabilities.version" .)) -}} +{{ include "vcluster.k8s.capabilities.version" . }} +{{- else -}} +{{ .Values.controlPlane.distro.k8s.controllerManager.image.tag }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* Bump $defaultTag value whenever k8s version is bumped */}} +{{- define "vcluster.k8s.apiServer.image.tag" -}} +{{- $defaultTag := "v1.31.1" -}} +{{- if and (not (empty .Values.controlPlane.distro.k8s.version)) (eq .Values.controlPlane.distro.k8s.apiServer.image.tag $defaultTag) -}} +{{ .Values.controlPlane.distro.k8s.version}} +{{- else -}} +{{- if not (eq .Values.controlPlane.distro.k8s.apiServer.image.tag $defaultTag) -}} +{{ .Values.controlPlane.distro.k8s.apiServer.image.tag }} +{{- else if not (empty (include "vcluster.k8s.capabilities.version" .)) -}} +{{ include "vcluster.k8s.capabilities.version" . }} +{{- else -}} +{{ .Values.controlPlane.distro.k8s.apiServer.image.tag }} +{{- end -}} +{{- end -}} +{{- end -}} + + +{{/* Bump $defaultTag value whenever k8s version is bumped */}} +{{- define "vcluster.k8s.scheduler.image.tag" -}} +{{- $defaultTag := "v1.31.1" -}} +{{- if and (not (empty .Values.controlPlane.distro.k8s.version)) (eq .Values.controlPlane.distro.k8s.scheduler.image.tag $defaultTag) -}} +{{ .Values.controlPlane.distro.k8s.version}} +{{- else -}} +{{- if not (eq .Values.controlPlane.distro.k8s.scheduler.image.tag $defaultTag) -}} +{{ .Values.controlPlane.distro.k8s.scheduler.image.tag }} +{{- else if not (empty (include "vcluster.k8s.capabilities.version" .)) -}} +{{ include "vcluster.k8s.capabilities.version" . }} +{{- else -}} +{{ .Values.controlPlane.distro.k8s.scheduler.image.tag }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{- define "vcluster.k8s.initContainers" -}} +{{- include "vcluster.oldPlugins.initContainers" . }} +{{- include "vcluster.plugins.initContainers" . }} +# this is needed because the k8s containers are distroless and thus we don't have any +# way of copying the binaries otherwise +- name: vcluster-copy + image: {{ include "vcluster.controlPlane.image" . | quote }} + volumeMounts: + - mountPath: /binaries + name: binaries + command: + - /bin/sh + args: + - -c + - "cp /vcluster /binaries/vcluster" + {{- if .Values.controlPlane.statefulSet.imagePullPolicy }} + imagePullPolicy: {{ .Values.controlPlane.statefulSet.imagePullPolicy }} + {{- end }} + securityContext: +{{ toYaml .Values.controlPlane.distro.k8s.securityContext | indent 4 }} + resources: +{{ toYaml .Values.controlPlane.distro.k8s.resources | indent 4 }} +{{- if .Values.controlPlane.distro.k8s.controllerManager.enabled }} +- name: kube-controller-manager + image: "{{ include "vcluster.image" (dict "defaultImageRegistry" .Values.controlPlane.advanced.defaultImageRegistry "registry" .Values.controlPlane.distro.k8s.controllerManager.image.registry "repository" .Values.controlPlane.distro.k8s.controllerManager.image.repository "tag" (include "vcluster.k8s.controllerManager.image.tag" .)) }}" + volumeMounts: + - mountPath: /binaries + name: binaries + command: + - /binaries/vcluster + args: + - cp + - /usr/local/bin/kube-controller-manager + - /binaries/kube-controller-manager + {{- if .Values.controlPlane.distro.k8s.controllerManager.imagePullPolicy }} + imagePullPolicy: {{ .Values.controlPlane.distro.k8s.controllerManager.imagePullPolicy }} + {{- end }} + securityContext: +{{ toYaml .Values.controlPlane.distro.k8s.securityContext | indent 4 }} + resources: +{{ toYaml .Values.controlPlane.distro.k8s.resources | indent 4 }} +{{- end }} +{{- if .Values.controlPlane.advanced.virtualScheduler.enabled }} +- name: kube-scheduler-manager + image: "{{ include "vcluster.image" (dict "defaultImageRegistry" .Values.controlPlane.advanced.defaultImageRegistry "registry" .Values.controlPlane.distro.k8s.scheduler.image.registry "repository" .Values.controlPlane.distro.k8s.scheduler.image.repository "tag" (include "vcluster.k8s.scheduler.image.tag" .)) }}" + volumeMounts: + - mountPath: /binaries + name: binaries + command: + - /binaries/vcluster + args: + - cp + - /usr/local/bin/kube-scheduler + - /binaries/kube-scheduler + {{- if .Values.controlPlane.distro.k8s.scheduler.imagePullPolicy }} + imagePullPolicy: {{ .Values.controlPlane.distro.k8s.scheduler.imagePullPolicy }} + {{- end }} + securityContext: +{{ toYaml .Values.controlPlane.distro.k8s.securityContext | indent 4 }} + resources: +{{ toYaml .Values.controlPlane.distro.k8s.resources | indent 4 }} +{{- end }} +{{- if .Values.controlPlane.distro.k8s.apiServer.enabled }} +- name: kube-apiserver + image: "{{ include "vcluster.image" (dict "defaultImageRegistry" .Values.controlPlane.advanced.defaultImageRegistry "registry" .Values.controlPlane.distro.k8s.apiServer.image.registry "repository" .Values.controlPlane.distro.k8s.apiServer.image.repository "tag" (include "vcluster.k8s.apiServer.image.tag" .)) }}" + volumeMounts: + - mountPath: /binaries + name: binaries + command: + - /binaries/vcluster + args: + - cp + - /usr/local/bin/kube-apiserver + - /binaries/kube-apiserver + {{- if .Values.controlPlane.distro.k8s.apiServer.imagePullPolicy }} + imagePullPolicy: {{ .Values.controlPlane.distro.k8s.apiServer.imagePullPolicy }} + {{- end }} + securityContext: +{{ toYaml .Values.controlPlane.distro.k8s.securityContext | indent 4 }} + resources: +{{ toYaml .Values.controlPlane.distro.k8s.resources | indent 4 }} +{{- end }} +{{- end -}} + +{{- define "vcluster.k3s.initContainers" -}} +{{- include "vcluster.oldPlugins.initContainers" . }} +{{- include "vcluster.plugins.initContainers" . }} +- name: vcluster + image: "{{ include "vcluster.image" (dict "defaultImageRegistry" .Values.controlPlane.advanced.defaultImageRegistry "registry" .Values.controlPlane.distro.k3s.image.registry "repository" .Values.controlPlane.distro.k3s.image.repository "tag" .Values.controlPlane.distro.k3s.image.tag) }}" + command: + - /bin/sh + args: + - -c + - "cp /bin/k3s /binaries/k3s" + {{- if .Values.controlPlane.distro.k3s.imagePullPolicy }} + imagePullPolicy: {{ .Values.controlPlane.distro.k3s.imagePullPolicy }} + {{- end }} + securityContext: +{{ toYaml .Values.controlPlane.distro.k3s.securityContext | indent 4 }} + volumeMounts: + - name: binaries + mountPath: /binaries + resources: +{{ toYaml .Values.controlPlane.distro.k3s.resources | indent 4 }} +{{- end -}} + +{{- define "vcluster.k0s.initContainers" -}} +{{- include "vcluster.oldPlugins.initContainers" . }} +{{- include "vcluster.plugins.initContainers" . }} +- name: vcluster + image: "{{ include "vcluster.image" (dict "defaultImageRegistry" .Values.controlPlane.advanced.defaultImageRegistry "registry" .Values.controlPlane.distro.k0s.image.registry "repository" .Values.controlPlane.distro.k0s.image.repository "tag" .Values.controlPlane.distro.k0s.image.tag) }}" + command: + - /bin/sh + args: + - -c + - "cp /usr/local/bin/k0s /binaries/k0s" + {{- if .Values.controlPlane.distro.k0s.imagePullPolicy }} + imagePullPolicy: {{ .Values.controlPlane.distro.k0s.imagePullPolicy }} + {{- end }} + securityContext: +{{ toYaml .Values.controlPlane.distro.k0s.securityContext | indent 4 }} + volumeMounts: + - name: binaries + mountPath: /binaries + resources: +{{ toYaml .Values.controlPlane.distro.k0s.resources | indent 4 }} +{{- end -}} + +{{/* + Plugin init container definition +*/}} +{{- define "vcluster.plugins.initContainers" -}} +{{- range $key, $container := .Values.plugins }} +{{- if not $container.image }} +{{- continue }} +{{- end }} +- {{- if $.Values.controlPlane.advanced.defaultImageRegistry }} + image: {{ $.Values.controlPlane.advanced.defaultImageRegistry }}/{{ $container.image }} + {{- else }} + image: {{ $container.image }} + {{- end }} + {{- if $container.name }} + name: {{ $container.name | quote }} + {{- else }} + name: {{ $key | quote }} + {{- end }} + {{- if $container.imagePullPolicy }} + imagePullPolicy: {{ $container.imagePullPolicy }} + {{- end }} + {{- if or $container.command $container.args }} + {{- if $container.command }} + command: + {{- range $commandIndex, $command := $container.command }} + - {{ $command | quote }} + {{- end }} + {{- end }} + {{- if $container.args }} + args: + {{- range $argIndex, $arg := $container.args }} + - {{ $arg | quote }} + {{- end }} + {{- end }} + {{- else }} + command: ["sh"] + args: ["-c", "cp -r /plugin /plugins/{{ $key }}"] + {{- end }} + {{- if $container.securityContext }} + securityContext: +{{ toYaml $container.securityContext | indent 4 }} + {{- end }} + {{- if $container.volumeMounts }} + volumeMounts: +{{ toYaml $container.volumeMounts | indent 4 }} + {{- else }} + volumeMounts: + - mountPath: /plugins + name: plugins + {{- end }} + {{- if $container.resources }} + resources: +{{ toYaml $container.resources | indent 4 }} + {{- end }} +{{- end }} +{{- end -}} + +{{/* + Old Plugin init container definition +*/}} +{{- define "vcluster.oldPlugins.initContainers" -}} +{{- range $key, $container := .Values.plugin }} +{{- if or (ne $container.version "v2") (not $container.image) -}} +{{- continue -}} +{{- end -}} +- {{- if $.Values.controlPlane.advanced.defaultImageRegistry }} + image: {{ $.Values.controlPlane.advanced.defaultImageRegistry }}/{{ $container.image }} + {{- else }} + image: {{ $container.image }} + {{- end }} + {{- if $container.name }} + name: {{ $container.name | quote }} + {{- else }} + name: {{ $key | quote }} + {{- end }} + {{- if $container.imagePullPolicy }} + imagePullPolicy: {{ $container.imagePullPolicy }} + {{- end }} + {{- if or $container.command $container.args }} + {{- if $container.command }} + command: + {{- range $commandIndex, $command := $container.command }} + - {{ $command | quote }} + {{- end }} + {{- end }} + {{- if $container.args }} + args: + {{- range $argIndex, $arg := $container.args }} + - {{ $arg | quote }} + {{- end }} + {{- end }} + {{- else }} + command: ["sh"] + args: ["-c", "cp -r /plugin /plugins/{{ $key }}"] + {{- end }} + securityContext: +{{ toYaml $container.securityContext | indent 4 }} + {{- if $container.volumeMounts }} + volumeMounts: +{{ toYaml $container.volumeMounts | indent 4 }} + {{- else }} + volumeMounts: + - mountPath: /plugins + name: plugins + {{- end }} + {{- if $container.resources }} + resources: +{{ toYaml $container.resources | indent 4 }} + {{- end }} +{{- end }} +{{- end -}} diff --git a/backing-services/vcluster/templates/_persistence.tpl b/backing-services/vcluster/templates/_persistence.tpl new file mode 100644 index 0000000..ed65f03 --- /dev/null +++ b/backing-services/vcluster/templates/_persistence.tpl @@ -0,0 +1,41 @@ +{{/* + ControlPlane Kind +*/}} +{{- define "vcluster.kind" -}} +{{ if or (include "vcluster.persistence.volumeClaim.enabled" .) .Values.controlPlane.backingStore.etcd.embedded.enabled }}StatefulSet{{ else }}Deployment{{ end }} +{{- end -}} + +{{/* + StatefulSet Persistence Options +*/}} +{{- define "vcluster.persistence" -}} +{{- if .Values.controlPlane.statefulSet.persistence.volumeClaimTemplates }} +volumeClaimTemplates: +{{ toYaml .Values.controlPlane.statefulSet.persistence.volumeClaimTemplates | indent 2 }} +{{- else if include "vcluster.persistence.volumeClaim.enabled" . }} +volumeClaimTemplates: +- metadata: + name: data + spec: + accessModes: {{ .Values.controlPlane.statefulSet.persistence.volumeClaim.accessModes }} + {{- if .Values.controlPlane.statefulSet.persistence.volumeClaim.storageClass }} + storageClassName: {{ .Values.controlPlane.statefulSet.persistence.volumeClaim.storageClass }} + {{- end }} + resources: + requests: + storage: {{ .Values.controlPlane.statefulSet.persistence.volumeClaim.size }} +{{- end }} +{{- end -}} + +{{/* + is persistence enabled? +*/}} +{{- define "vcluster.persistence.volumeClaim.enabled" -}} +{{- if .Values.controlPlane.statefulSet.persistence.volumeClaimTemplates -}} +{{- true -}} +{{- else if eq (toString .Values.controlPlane.statefulSet.persistence.volumeClaim.enabled) "true" -}} +{{- true -}} +{{- else if and (eq (toString .Values.controlPlane.statefulSet.persistence.volumeClaim.enabled) "auto") (or (include "vcluster.database.embedded.enabled" .) .Values.controlPlane.backingStore.etcd.embedded.enabled) -}} +{{- true -}} +{{- end -}} +{{- end -}} diff --git a/backing-services/vcluster/templates/_plugin.tpl b/backing-services/vcluster/templates/_plugin.tpl new file mode 100644 index 0000000..c5dc668 --- /dev/null +++ b/backing-services/vcluster/templates/_plugin.tpl @@ -0,0 +1,126 @@ +{{/* + Plugin volume mount definition +*/}} +{{- define "vcluster.plugins.volumeMounts" -}} +{{- $pluginFound := false -}} +{{- range $key, $container := .Values.plugin }} +{{- if or (ne $container.version "v2") (not $container.image) }} +{{- continue }} +{{- end }} +{{ $pluginFound = true }} +- mountPath: /plugins + name: plugins +{{- break }} +{{- end }} +{{- if eq $pluginFound false }} +{{- range $key, $container := .Values.plugins }} +{{- if not $container.image }} +{{- continue }} +{{- end }} +- mountPath: /plugins + name: plugins +{{- break }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* + Plugin volume definition +*/}} +{{- define "vcluster.plugins.volumes" -}} +{{- $pluginFound := false -}} +{{- range $key, $container := .Values.plugin }} +{{- if or (ne $container.version "v2") (not $container.image) }} +{{- continue }} +{{- end }} +{{ $pluginFound = true }} +- name: plugins + emptyDir: {} +{{- break }} +{{- end }} +{{- if eq $pluginFound false }} +{{- range $key, $container := .Values.plugins }} +{{- if not $container.image }} +{{- continue }} +{{- end }} +- name: plugins + emptyDir: {} +{{- break }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* + Sidecar container definition for the legacy syncer parts +*/}} +{{- define "vcluster.legacyPlugins.containers" -}} +{{- $counter := -1 -}} +{{- range $key, $container := .Values.plugin }} +{{- if eq $container.version "v2" }} +{{ continue }} +{{- end }} +{{- $counter = add1 $counter }} +- {{- if $.Values.controlPlane.advanced.defaultImageRegistry }} + image: {{ $.Values.controlPlane.advanced.defaultImageRegistry }}/{{ $container.image }} + {{- else }} + image: {{ $container.image }} + {{- end }} + {{- if $container.name }} + name: {{ $container.name | quote }} + {{- else }} + name: {{ $key | quote }} + {{- end }} + {{- if $container.imagePullPolicy }} + imagePullPolicy: {{ $container.imagePullPolicy }} + {{- end }} + {{- if $container.workingDir }} + workingDir: {{ $container.workingDir }} + {{- end }} + {{- if $container.command }} + command: + {{- range $commandIndex, $command := $container.command }} + - {{ $command | quote }} + {{- end }} + {{- end }} + {{- if $container.args }} + args: + {{- range $argIndex, $arg := $container.args }} + - {{ $arg | quote }} + {{- end }} + {{- end }} + {{- if $container.terminationMessagePath }} + terminationMessagePath: {{ $container.terminationMessagePath }} + {{- end }} + {{- if $container.terminationMessagePolicy }} + terminationMessagePolicy: {{ $container.terminationMessagePolicy }} + {{- end }} + env: + - name: VCLUSTER_PLUGIN_ADDRESS + value: "localhost:{{ add 14000 $counter }}" + - name: VCLUSTER_PLUGIN_NAME + value: "{{ $key }}" + {{- if $container.env }} +{{ toYaml $container.env | indent 4 }} + {{- end }} + envFrom: +{{ toYaml $container.envFrom | indent 4 }} + securityContext: +{{ toYaml $container.securityContext | indent 4 }} + lifecycle: +{{ toYaml $container.lifecycle | indent 4 }} + livenessProbe: +{{ toYaml $container.livenessProbe | indent 4 }} + readinessProbe: +{{ toYaml $container.readinessProbe | indent 4 }} + startupProbe: +{{ toYaml $container.startupProbe | indent 4 }} + volumeDevices: +{{ toYaml $container.volumeDevices | indent 4 }} + volumeMounts: +{{ toYaml $container.volumeMounts | indent 4 }} + {{- if $container.resources }} + resources: +{{ toYaml $container.resources | indent 4 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backing-services/vcluster/templates/_rbac.tpl b/backing-services/vcluster/templates/_rbac.tpl new file mode 100644 index 0000000..09ef522 --- /dev/null +++ b/backing-services/vcluster/templates/_rbac.tpl @@ -0,0 +1,214 @@ +{{- define "vcluster.clusterRoleName" -}} +{{- printf "vc-%s-v-%s" .Release.Name .Release.Namespace | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- define "vcluster.clusterRoleNameMultinamespace" -}} +{{- printf "vc-mn-%s-v-%s" .Release.Name .Release.Namespace | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* + Whether to create a cluster role or not +*/}} +{{- define "vcluster.createClusterRole" -}} +{{- if eq (toString .Values.rbac.clusterRole.enabled) "true" -}} +{{- true -}} +{{- else if eq (toString .Values.rbac.clusterRole.enabled) "auto" -}} +{{- if or + .Values.rbac.clusterRole.overwriteRules + (not (empty (include "vcluster.rbac.clusterRoleExtraRules" . ))) + (not (empty (include "vcluster.plugin.clusterRoleExtraRules" . ))) + (not (empty (include "vcluster.generic.clusterRoleExtraRules" . ))) + .Values.networking.replicateServices.fromHost + .Values.pro + .Values.sync.toHost.storageClasses.enabled + .Values.experimental.isolatedControlPlane.enabled + .Values.sync.toHost.persistentVolumes.enabled + .Values.sync.toHost.priorityClasses.enabled + .Values.sync.fromHost.priorityClasses.enabled + .Values.sync.toHost.volumeSnapshotContents.enabled + .Values.sync.fromHost.volumeSnapshotClasses.enabled + .Values.controlPlane.advanced.virtualScheduler.enabled + .Values.sync.fromHost.ingressClasses.enabled + .Values.sync.fromHost.runtimeClasses.enabled + (eq (toString .Values.sync.fromHost.storageClasses.enabled) "true") + (eq (toString .Values.sync.fromHost.csiNodes.enabled) "true") + (eq (toString .Values.sync.fromHost.csiDrivers.enabled) "true") + (eq (toString .Values.sync.fromHost.csiStorageCapacities.enabled) "true") + .Values.sync.fromHost.nodes.enabled + .Values.sync.toHost.customResources + .Values.sync.fromHost.customResources + .Values.integrations.kubeVirt.enabled + .Values.integrations.externalSecrets.enabled + (and .Values.integrations.metricsServer.enabled .Values.integrations.metricsServer.nodes) + .Values.experimental.multiNamespaceMode.enabled -}} +{{- true -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* + Role rules defined on global level +*/}} +{{- define "vcluster.rbac.roleExtraRules" -}} +{{- if .Values.rbac.role.extraRules }} +{{- range $ruleIndex, $rule := .Values.rbac.role.extraRules }} +- {{ toJson $rule }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* + Role rules defined by plugins +*/}} +{{- define "vcluster.plugin.roleExtraRules" -}} +{{- range $key, $container := .Values.plugin }} +{{- if $container.rbac }} +{{- if $container.rbac.role }} +{{- if $container.rbac.role.extraRules }} +{{- range $ruleIndex, $rule := $container.rbac.role.extraRules }} +- {{ toJson $rule }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} +{{- range $key, $container := .Values.plugins }} +{{- if $container.rbac }} +{{- if $container.rbac.role }} +{{- if $container.rbac.role.extraRules }} +{{- range $ruleIndex, $rule := $container.rbac.role.extraRules }} +- {{ toJson $rule }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* + Cluster role rules defined by plugins +*/}} +{{- define "vcluster.plugin.clusterRoleExtraRules" -}} +{{- range $key, $container := .Values.plugin }} +{{- if $container.rbac }} +{{- if $container.rbac.clusterRole }} +{{- if $container.rbac.clusterRole.extraRules }} +{{- range $ruleIndex, $rule := $container.rbac.clusterRole.extraRules }} +- {{ toJson $rule }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} +{{- range $key, $container := .Values.plugins }} +{{- if $container.rbac }} +{{- if $container.rbac.clusterRole }} +{{- if $container.rbac.clusterRole.extraRules }} +{{- range $ruleIndex, $rule := $container.rbac.clusterRole.extraRules }} +- {{ toJson $rule }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* + Role rules defined in generic syncer +*/}} +{{- define "vcluster.generic.roleExtraRules" -}} +{{- if .Values.experimental.genericSync.role }} +{{- if .Values.experimental.genericSync.role.extraRules }} +{{- range $ruleIndex, $rule := .Values.experimental.genericSync.role.extraRules }} +- {{ toJson $rule }} +{{- end }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* + Role rules defined in generic syncer +*/}} +{{- define "vcluster.customResources.roleExtraRules" -}} +{{- if .Values.sync.toHost.customResources }} +{{- range $crdName, $rule := .Values.sync.toHost.customResources }} +{{- if $rule.enabled }} +- resources: [ "{{ (splitn "." 2 $crdName)._0 }}" ] + apiGroups: [ "{{ (splitn "." 2 $crdName)._1 }}" ] + verbs: ["create", "delete", "patch", "update", "get", "list", "watch"] +{{- end }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* + Cluster role rules defined in generic syncer +*/}} +{{- define "vcluster.customResources.clusterRoleExtraRules" -}} +{{- if .Values.sync.fromHost.customResources }} +{{- range $crdName, $rule := .Values.sync.fromHost.customResources }} +{{- if $rule.enabled }} +- resources: [ "{{ (splitn "." 2 $crdName)._0 }}" ] + apiGroups: [ "{{ (splitn "." 2 $crdName)._1 }}" ] + verbs: ["get", "list", "watch"] +{{- end }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* + Cluster role rules defined in generic syncer +*/}} +{{- define "vcluster.generic.clusterRoleExtraRules" -}} +{{- if .Values.experimental.genericSync.clusterRole }} +{{- if .Values.experimental.genericSync.clusterRole.extraRules }} +{{- range $ruleIndex, $rule := .Values.experimental.genericSync.clusterRole.extraRules }} +- {{ toJson $rule }} +{{- end }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* + Cluster Role rules defined on global level +*/}} +{{- define "vcluster.rbac.clusterRoleExtraRules" -}} +{{- if .Values.rbac.clusterRole.extraRules }} +{{- range $ruleIndex, $rule := .Values.rbac.clusterRole.extraRules }} +- {{ toJson $rule }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* + Whether to create a role and role binding to access the platform API key secret +*/}} +{{- define "vcluster.rbac.createPlatformSecretRole" -}} +{{- $createRBAC := dig "platform" "apiKey" "createRBAC" true .Values.external -}} +{{- if and $createRBAC (ne (include "vcluster.rbac.platformSecretNamespace" .) .Release.Namespace) }} +{{- true -}} +{{- end }} +{{- end -}} + +{{/* + Namespace containing the vCluster platform secret +*/}} +{{- define "vcluster.rbac.platformSecretNamespace" -}} +{{- dig "platform" "apiKey" "namespace" .Release.Namespace .Values.external | default .Release.Namespace -}} +{{- end -}} + +{{/* + Name specifies the secret name containing the vCluster platform licenses and tokens +*/}} +{{- define "vcluster.rbac.platformSecretName" -}} +{{- dig "platform" "apiKey" "secretName" "vcluster-platform-api-key" .Values.external | quote -}} +{{- end -}} + +{{- define "vcluster.rbac.platformRoleName" -}} +{{- printf "vc-%s-v-%s-platform-role" .Release.Name .Release.Namespace | trunc 63 | trimSuffix "-" -}} +{{- end -}} + + +{{- define "vcluster.rbac.platformRoleBindingName" -}} +{{- printf "vc-%s-v-%s-platform-role-binding" .Release.Name .Release.Namespace | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/backing-services/vcluster/templates/clusterrole.yaml b/backing-services/vcluster/templates/clusterrole.yaml new file mode 100644 index 0000000..13ef709 --- /dev/null +++ b/backing-services/vcluster/templates/clusterrole.yaml @@ -0,0 +1,137 @@ +{{- if (include "vcluster.createClusterRole" . ) -}} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "vcluster.clusterRoleName" . }} + labels: + app: vcluster + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" + {{- if .Values.controlPlane.advanced.globalMetadata.annotations }} + annotations: +{{ toYaml .Values.controlPlane.advanced.globalMetadata.annotations | indent 4 }} + {{- end }} +rules: + {{- if .Values.rbac.clusterRole.overwriteRules }} +{{ toYaml .Values.rbac.clusterRole.overwriteRules | indent 2 }} + {{- else }} + {{- if .Values.pro }} + - apiGroups: ["cluster.loft.sh", "storage.loft.sh"] + resources: ["features", "virtualclusters"] + verbs: ["get", "list", "watch"] + - apiGroups: ["management.loft.sh"] + resources: ["virtualclusterinstances"] + verbs: ["get"] + {{- end }} + {{- if or .Values.pro .Values.sync.fromHost.nodes.enabled }} + - apiGroups: [""] + resources: ["pods", "nodes", "nodes/status", "nodes/metrics", "nodes/stats", "nodes/proxy"] + verbs: ["get", "watch", "list"] + {{- end }} + {{- if .Values.experimental.isolatedControlPlane.enabled }} + - apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "watch", "list"] + {{- end }} + {{- if and .Values.sync.fromHost.nodes.enabled .Values.sync.fromHost.nodes.syncBackChanges }} + - apiGroups: [""] + resources: ["nodes", "nodes/status"] + verbs: ["update", "patch"] + {{- end }} + {{- if .Values.controlPlane.advanced.virtualScheduler.enabled }} + - apiGroups: ["storage.k8s.io"] + resources: ["storageclasses", "csinodes", "csidrivers", "csistoragecapacities"] + verbs: ["get", "watch", "list"] + {{- end }} + {{- if eq (toString .Values.sync.fromHost.storageClasses.enabled) "true" }} + - apiGroups: ["storage.k8s.io"] + resources: ["storageclasses"] + verbs: ["get", "watch", "list"] + {{- end }} + {{- if eq (toString .Values.sync.fromHost.csiNodes.enabled) "true" }} + - apiGroups: ["storage.k8s.io"] + resources: ["csinodes"] + verbs: ["get", "watch", "list"] + {{- end }} + {{- if eq (toString .Values.sync.fromHost.csiDrivers.enabled) "true" }} + - apiGroups: ["storage.k8s.io"] + resources: ["csidrivers"] + verbs: ["get", "watch", "list"] + {{- end }} + {{- if eq (toString .Values.sync.fromHost.csiStorageCapacities.enabled) "true" }} + - apiGroups: ["storage.k8s.io"] + resources: ["csistoragecapacities"] + verbs: ["get", "watch", "list"] + {{- end }} + {{- if .Values.sync.toHost.persistentVolumes.enabled }} + - apiGroups: [""] + resources: ["persistentvolumes"] + verbs: ["create", "delete", "patch", "update", "get", "watch", "list"] + {{- end }} + {{- if .Values.sync.fromHost.ingressClasses.enabled }} + - apiGroups: ["networking.k8s.io"] + resources: ["ingressclasses"] + verbs: ["get", "watch", "list"] + {{- end }} + {{- if .Values.sync.fromHost.runtimeClasses.enabled }} + - apiGroups: ["nodes.k8s.io"] + resources: ["runtimeclasses"] + verbs: ["get", "watch", "list"] + {{- end }} + {{- if .Values.sync.toHost.storageClasses.enabled }} + - apiGroups: ["storage.k8s.io"] + resources: ["storageclasses"] + verbs: ["create", "delete", "patch", "update", "get", "watch", "list"] + {{- end }} + {{- if or .Values.sync.toHost.priorityClasses.enabled .Values.sync.fromHost.priorityClasses.enabled }} + - apiGroups: ["scheduling.k8s.io"] + resources: ["priorityclasses"] + verbs: ["create", "delete", "patch", "update", "get", "list", "watch"] + {{- end }} + {{- if .Values.sync.fromHost.volumeSnapshotClasses.enabled }} + - apiGroups: ["snapshot.storage.k8s.io"] + resources: ["volumesnapshotclasses"] + verbs: ["get", "list", "watch"] + {{- end }} + {{- if .Values.sync.toHost.volumeSnapshotContents.enabled }} + - apiGroups: ["snapshot.storage.k8s.io"] + resources: ["volumesnapshotcontents"] + verbs: ["create", "delete", "patch", "update", "get", "list", "watch"] + {{- end }} + {{- if .Values.networking.replicateServices.fromHost }} + - apiGroups: [""] + resources: ["services", "endpoints"] + verbs: ["get", "watch", "list"] + {{- end }} + {{- if .Values.experimental.multiNamespaceMode.enabled }} + - apiGroups: [""] + resources: ["namespaces", "serviceaccounts"] + verbs: ["create", "delete", "patch", "update", "get", "watch", "list"] + {{- end }} + {{- if (and .Values.integrations.metricsServer.enabled .Values.integrations.metricsServer.nodes) }} + - apiGroups: ["metrics.k8s.io"] + resources: ["nodes"] + verbs: ["get", "list"] + {{- end }} + {{- if or (and .Values.integrations.kubeVirt.enabled .Values.integrations.kubeVirt.webhook.enabled) (and .Values.integrations.externalSecrets.enabled .Values.integrations.externalSecrets.webhook.enabled ) }} + - apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations", "mutatingwebhookconfigurations"] + verbs: ["get", "list", "watch"] + {{- end }} + {{- if or .Values.integrations.kubeVirt.enabled .Values.integrations.externalSecrets.enabled .Values.sync.toHost.customResources .Values.sync.fromHost.customResources }} + - apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch"] + {{- end }} + {{- if and .Values.integrations.externalSecrets.enabled .Values.integrations.externalSecrets.sync.clusterStores.enabled }} + - apiGroups: ["external-secrets.io"] + resources: ["clustersecretstores"] + verbs: ["get", "list", "watch"] + {{- end }} + {{- include "vcluster.customResources.clusterRoleExtraRules" . | indent 2 }} + {{- include "vcluster.plugin.clusterRoleExtraRules" . | indent 2 }} + {{- include "vcluster.generic.clusterRoleExtraRules" . | indent 2 }} + {{- include "vcluster.rbac.clusterRoleExtraRules" . | indent 2 }} + {{- end }} +{{- end }} diff --git a/backing-services/vcluster/templates/clusterrolebinding.yaml b/backing-services/vcluster/templates/clusterrolebinding.yaml new file mode 100644 index 0000000..a1166ea --- /dev/null +++ b/backing-services/vcluster/templates/clusterrolebinding.yaml @@ -0,0 +1,27 @@ +{{- if (include "vcluster.createClusterRole" . ) -}} +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "vcluster.clusterRoleName" . }} + labels: + app: vcluster + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" + {{- if .Values.controlPlane.advanced.globalMetadata.annotations }} + annotations: +{{ toYaml .Values.controlPlane.advanced.globalMetadata.annotations | indent 4 }} + {{- end }} +subjects: + - kind: ServiceAccount + {{- if .Values.controlPlane.advanced.serviceAccount.name }} + name: {{ .Values.controlPlane.advanced.serviceAccount.name }} + {{- else }} + name: vc-{{ .Release.Name }} + {{- end }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: {{ template "vcluster.clusterRoleName" . }} + apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/backing-services/vcluster/templates/config-secret.yaml b/backing-services/vcluster/templates/config-secret.yaml new file mode 100644 index 0000000..eb8170e --- /dev/null +++ b/backing-services/vcluster/templates/config-secret.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Secret +metadata: + name: "vc-config-{{ .Release.Name }}" + namespace: {{ .Release.Namespace }} + labels: + app: vcluster + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" + {{- if .Values.controlPlane.advanced.globalMetadata.annotations }} + annotations: +{{ toYaml .Values.controlPlane.advanced.globalMetadata.annotations | indent 4 }} + {{- end }} +type: Opaque +data: + config.yaml: {{ .Values | toYaml | b64enc | quote }} diff --git a/backing-services/vcluster/templates/coredns-configmap.yaml b/backing-services/vcluster/templates/coredns-configmap.yaml new file mode 100644 index 0000000..b39d546 --- /dev/null +++ b/backing-services/vcluster/templates/coredns-configmap.yaml @@ -0,0 +1,288 @@ +{{- if and .Values.controlPlane.coredns.enabled (not .Values.experimental.isolatedControlPlane.headless) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: vc-coredns-{{ .Release.Name }} + namespace: {{ .Release.Namespace }} + {{- if .Values.controlPlane.advanced.globalMetadata.annotations }} + annotations: +{{ toYaml .Values.controlPlane.advanced.globalMetadata.annotations | indent 4 }} + {{- end }} +data: +{{- if .Values.controlPlane.coredns.overwriteManifests }} + coredns.yaml: |- +{{ .Values.controlPlane.coredns.overwriteManifests | indent 4 }} +{{- else if .Values.controlPlane.coredns.embedded }} +{{ include "vcluster.corefile" . | indent 2 }} + coredns.yaml: |- + apiVersion: v1 + kind: ConfigMap + metadata: + name: coredns + namespace: kube-system + data: + NodeHosts: "" + --- + apiVersion: v1 + kind: Service + metadata: + name: kube-dns + namespace: kube-system + annotations: + prometheus.io/port: "9153" + prometheus.io/scrape: "true" + {{- if .Values.controlPlane.coredns.service.annotations }} +{{ toYaml .Values.controlPlane.coredns.service.annotations | indent 8 }} + {{- end }} + labels: + k8s-app: kube-dns + kubernetes.io/cluster-service: "true" + kubernetes.io/name: "CoreDNS" + {{- if .Values.controlPlane.coredns.service.labels }} +{{ toYaml .Values.controlPlane.coredns.service.labels | indent 8 }} + {{- end }} + spec: +{{ toYaml .Values.controlPlane.coredns.service.spec | indent 6 }} + {{- if not .Values.controlPlane.coredns.service.spec.ports }} + ports: + - name: dns + port: 53 + targetPort: 1053 + protocol: UDP + - name: dns-tcp + port: 53 + targetPort: 1053 + protocol: TCP + - name: metrics + port: 9153 + protocol: TCP + {{- end }} +{{- else }} + coredns.yaml: |- + apiVersion: v1 + kind: ServiceAccount + metadata: + name: coredns + namespace: kube-system + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRole + metadata: + labels: + kubernetes.io/bootstrapping: rbac-defaults + name: system:coredns + rules: + - apiGroups: + - "" + resources: + - endpoints + - services + - pods + - namespaces + verbs: + - list + - watch + - apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - list + - watch + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRoleBinding + metadata: + annotations: + rbac.authorization.kubernetes.io/autoupdate: "true" + labels: + kubernetes.io/bootstrapping: rbac-defaults + name: system:coredns + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:coredns + subjects: + - kind: ServiceAccount + name: coredns + namespace: kube-system + --- + apiVersion: v1 + kind: ConfigMap + metadata: + name: coredns + namespace: kube-system + data: +{{ include "vcluster.corefile" . | indent 6 }} + NodeHosts: "" + --- + apiVersion: apps/v1 + kind: Deployment + metadata: + name: coredns + namespace: kube-system + {{- if .Values.controlPlane.coredns.deployment.annotations }} + annotations: +{{ toYaml .Values.controlPlane.coredns.deployment.annotations | indent 8 }} + {{- end }} + labels: + k8s-app: kube-dns + kubernetes.io/name: "CoreDNS" + {{- if .Values.controlPlane.coredns.deployment.labels }} +{{ toYaml .Values.controlPlane.coredns.deployment.labels | indent 8 }} + {{- end }} + spec: + replicas: {{ .Values.controlPlane.coredns.deployment.replicas }} + strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + selector: + matchLabels: + k8s-app: kube-dns + template: + metadata: + {{- if .Values.controlPlane.coredns.deployment.pods.annotations }} + annotations: +{{ toYaml .Values.controlPlane.coredns.deployment.pods.annotations | indent 12 }} + {{- end }} + labels: + k8s-app: kube-dns + {{- if .Values.controlPlane.coredns.deployment.pods.labels }} +{{ toYaml .Values.controlPlane.coredns.deployment.pods.labels | indent 12 }} + {{- end }} + spec: + priorityClassName: {{ .Values.controlPlane.coredns.priorityClassName | quote }} + serviceAccountName: coredns + nodeSelector: + kubernetes.io/os: linux + {{- if .Values.controlPlane.coredns.deployment.nodeSelector }} +{{ toYaml .Values.controlPlane.coredns.deployment.nodeSelector | indent 12 }} + {{- end }} + {{- if .Values.controlPlane.coredns.deployment.affinity }} + affinity: +{{ toYaml .Values.controlPlane.coredns.deployment.affinity | indent 12 }} + {{- end }} + {{- if .Values.controlPlane.coredns.deployment.tolerations }} + tolerations: +{{ toYaml .Values.controlPlane.coredns.deployment.tolerations | indent 12 }} + {{- end }} + {{- if .Values.controlPlane.coredns.deployment.topologySpreadConstraints }} + topologySpreadConstraints: +{{ toYaml .Values.controlPlane.coredns.deployment.topologySpreadConstraints | indent 12 }} + {{- end }} + {{- if .Values.policies.podSecurityStandard }} + securityContext: + seccompProfile: + type: RuntimeDefault + {{- end }} + containers: + - name: coredns + {{- if .Values.controlPlane.coredns.deployment.image }} + {{- if .Values.controlPlane.advanced.defaultImageRegistry }} + image: {{ .Values.controlPlane.advanced.defaultImageRegistry }}/{{ .Values.controlPlane.coredns.deployment.image }} + {{- else }} + image: {{ .Values.controlPlane.coredns.deployment.image }} + {{- end }} + {{- else }} + image: {{`{{.IMAGE}}`}} + {{- end }} + imagePullPolicy: IfNotPresent + {{- if .Values.controlPlane.coredns.deployment.resources }} + resources: +{{ toYaml .Values.controlPlane.coredns.deployment.resources | indent 16 }} + {{- end }} + args: [ "-conf", "/etc/coredns/Corefile" ] + volumeMounts: + - name: config-volume + mountPath: /etc/coredns + readOnly: true + - name: custom-config-volume + mountPath: /etc/coredns/custom + readOnly: true + securityContext: + runAsNonRoot: true + runAsUser: {{`{{.RUN_AS_USER}}`}} + runAsGroup: {{`{{.RUN_AS_GROUP}}`}} + allowPrivilegeEscalation: false + capabilities: + add: + - NET_BIND_SERVICE + drop: + - ALL + readOnlyRootFilesystem: true + livenessProbe: + httpGet: + path: /health + port: 8080 + scheme: HTTP + initialDelaySeconds: 60 + periodSeconds: 10 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /ready + port: 8181 + scheme: HTTP + initialDelaySeconds: 0 + periodSeconds: 2 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 3 + dnsPolicy: Default + volumes: + - name: config-volume + configMap: + name: coredns + items: + - key: Corefile + path: Corefile + - key: NodeHosts + path: NodeHosts + - name: custom-config-volume + configMap: + name: coredns-custom + optional: true + --- + apiVersion: v1 + kind: Service + metadata: + name: kube-dns + namespace: kube-system + annotations: + prometheus.io/port: "9153" + prometheus.io/scrape: "true" + {{- if .Values.controlPlane.coredns.service.annotations }} +{{ toYaml .Values.controlPlane.coredns.service.annotations | indent 8 }} + {{- end }} + labels: + k8s-app: kube-dns + kubernetes.io/cluster-service: "true" + kubernetes.io/name: "CoreDNS" + {{- if .Values.controlPlane.coredns.service.labels }} +{{ toYaml .Values.controlPlane.coredns.service.labels | indent 8 }} + {{- end }} + spec: +{{ toYaml .Values.controlPlane.coredns.service.spec | indent 6 }} + {{- if not .Values.controlPlane.coredns.service.spec.selector }} + selector: + k8s-app: kube-dns + {{- end }} + {{- if not .Values.controlPlane.coredns.service.spec.ports }} + ports: + - name: dns + port: 53 + targetPort: 1053 + protocol: UDP + - name: dns-tcp + port: 53 + targetPort: 1053 + protocol: TCP + - name: metrics + port: 9153 + protocol: TCP + {{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/vcluster/templates/etcd-headless-service.yaml b/backing-services/vcluster/templates/etcd-headless-service.yaml new file mode 100644 index 0000000..f10bb63 --- /dev/null +++ b/backing-services/vcluster/templates/etcd-headless-service.yaml @@ -0,0 +1,36 @@ +{{- if not .Values.experimental.isolatedControlPlane.headless }} +{{- if or .Values.controlPlane.backingStore.etcd.deploy.enabled (include "vcluster.etcd.embedded.migrate" .) }} +{{- if .Values.controlPlane.backingStore.etcd.deploy.headlessService.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }}-etcd-headless + namespace: {{ .Release.Namespace }} + labels: + app: vcluster-etcd + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" + {{- $annotations := merge dict .Values.controlPlane.advanced.globalMetadata.annotations .Values.controlPlane.backingStore.etcd.deploy.headlessService.annotations }} + {{- if $annotations }} + annotations: +{{ toYaml $annotations | indent 4 }} + {{- end }} +spec: + publishNotReadyAddresses: true + ports: + - name: etcd + port: 2379 + targetPort: 2379 + protocol: TCP + - name: peer + port: 2380 + targetPort: 2380 + protocol: TCP + clusterIP: None + selector: + app: vcluster-etcd + release: "{{ .Release.Name }}" +{{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/vcluster/templates/etcd-service.yaml b/backing-services/vcluster/templates/etcd-service.yaml new file mode 100644 index 0000000..f61ed51 --- /dev/null +++ b/backing-services/vcluster/templates/etcd-service.yaml @@ -0,0 +1,35 @@ +{{- if not .Values.experimental.isolatedControlPlane.headless }} +{{- if or .Values.controlPlane.backingStore.etcd.deploy.enabled (include "vcluster.etcd.embedded.migrate" .) }} +{{- if .Values.controlPlane.backingStore.etcd.deploy.service.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }}-etcd + namespace: {{ .Release.Namespace }} + labels: + app: vcluster-etcd + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" + {{- $annotations := merge dict .Values.controlPlane.advanced.globalMetadata.annotations .Values.controlPlane.backingStore.etcd.deploy.service.annotations }} + {{- if $annotations }} + annotations: +{{ toYaml $annotations | indent 4 }} + {{- end }} +spec: + type: ClusterIP + ports: + - name: etcd + port: 2379 + targetPort: 2379 + protocol: TCP + - name: peer + port: 2380 + targetPort: 2380 + protocol: TCP + selector: + app: vcluster-etcd + release: {{ .Release.Name }} +{{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/vcluster/templates/etcd-statefulset.yaml b/backing-services/vcluster/templates/etcd-statefulset.yaml new file mode 100644 index 0000000..379b9a4 --- /dev/null +++ b/backing-services/vcluster/templates/etcd-statefulset.yaml @@ -0,0 +1,213 @@ +{{- if not .Values.experimental.isolatedControlPlane.headless }} +{{- if or .Values.controlPlane.backingStore.etcd.deploy.enabled (include "vcluster.etcd.embedded.migrate" .) }} +{{- if .Values.controlPlane.backingStore.etcd.deploy.statefulSet.enabled }} +{{- $externalEtcd := .Values.controlPlane.backingStore.etcd.deploy.statefulSet }} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ .Release.Name }}-etcd + namespace: {{ .Release.Namespace }} + labels: + app: vcluster-etcd + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" +{{- if $externalEtcd.labels }} +{{ toYaml $externalEtcd.labels | indent 4 }} +{{- end }} + {{- $annotations := merge dict .Values.controlPlane.advanced.globalMetadata.annotations $externalEtcd.annotations }} + {{- if $annotations }} + annotations: +{{ toYaml $annotations | indent 4 }} + {{- end }} +spec: + replicas: {{ $externalEtcd.highAvailability.replicas }} + podManagementPolicy: {{ $externalEtcd.scheduling.podManagementPolicy }} + serviceName: {{ .Release.Name }}-etcd-headless + {{- if eq $externalEtcd.persistence.volumeClaim.retentionPolicy "Delete" }} + {{- if ge (int .Capabilities.KubeVersion.Minor) 27 }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ $externalEtcd.persistence.volumeClaim.retentionPolicy }} + {{- end }} + {{- end }} + selector: + matchLabels: + app: vcluster-etcd + release: {{ .Release.Name }} + {{- if $externalEtcd.persistence.volumeClaimTemplates }} + volumeClaimTemplates: +{{ toYaml $externalEtcd.persistence.volumeClaimTemplates | indent 4 }} + {{- else if $externalEtcd.persistence.volumeClaim.enabled }} + volumeClaimTemplates: + - metadata: + name: data + spec: + accessModes: {{ $externalEtcd.persistence.volumeClaim.accessModes }} + {{- if $externalEtcd.persistence.volumeClaim.storageClass }} + storageClassName: {{ $externalEtcd.persistence.volumeClaim.storageClass }} + {{- end }} + resources: + requests: + storage: {{ $externalEtcd.persistence.volumeClaim.size }} + {{- end }} + template: + metadata: + {{- if $externalEtcd.pods.annotations }} + annotations: +{{ toYaml $externalEtcd.pods.annotations | indent 8 }} + {{- end }} + labels: + app: vcluster-etcd + release: {{ .Release.Name }} + {{- range $k, $v := $externalEtcd.pods.labels }} + {{ $k }}: {{ $v | quote }} + {{- end }} + spec: + terminationGracePeriodSeconds: 10 + {{- if $externalEtcd.scheduling.affinity }} + affinity: +{{ toYaml $externalEtcd.scheduling.affinity | indent 8 }} + {{- else }} + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + # if possible avoid scheduling more than one pod on one node + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - vcluster-etcd + - key: release + operator: In + values: + - {{ .Release.Name }} + topologyKey: "kubernetes.io/hostname" + # if possible avoid scheduling pod onto node that is in the same zone as one or more vcluster pods are running + - weight: 50 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - vcluster-etcd + - key: release + operator: In + values: + - {{ .Release.Name }} + topologyKey: topology.kubernetes.io/zone + {{- end }} + {{- if $externalEtcd.scheduling.topologySpreadConstraints }} + topologySpreadConstraints: +{{ toYaml $externalEtcd.scheduling.topologySpreadConstraints | indent 8 }} + {{- end }} + nodeSelector: +{{ toYaml $externalEtcd.scheduling.nodeSelector | indent 8 }} + tolerations: +{{ toYaml $externalEtcd.scheduling.tolerations | indent 8 }} + automountServiceAccountToken: false + {{- if .Values.controlPlane.advanced.serviceAccount.name }} + serviceAccountName: {{ .Values.controlPlane.advanced.serviceAccount.name }} + {{- else }} + serviceAccountName: vc-{{ .Release.Name }} + {{- end }} + volumes: + - name: certs + secret: + secretName: {{ .Release.Name }}-certs + {{- if $externalEtcd.persistence.addVolumes }} +{{ toYaml $externalEtcd.persistence.addVolumes | indent 8 }} + {{- end }} + {{- if not $externalEtcd.persistence.volumeClaim.enabled }} + - name: data + emptyDir: {} + {{- end }} + {{- if $externalEtcd.scheduling.priorityClassName }} + priorityClassName: {{ $externalEtcd.scheduling.priorityClassName }} + {{- end }} + {{- if $externalEtcd.security.podSecurityContext }} + securityContext: +{{ toYaml $externalEtcd.security.podSecurityContext | indent 8 }} + {{- end }} + enableServiceLinks: {{ .Values.controlPlane.backingStore.etcd.deploy.statefulSet.enableServiceLinks }} + containers: + - name: etcd + image: '{{ include "vcluster.image" (dict "defaultImageRegistry" .Values.controlPlane.advanced.defaultImageRegistry "registry" $externalEtcd.image.registry "repository" $externalEtcd.image.repository "tag" $externalEtcd.image.tag) }}' + command: + - etcd + - '--cert-file=/run/config/pki/etcd-server.crt' + - '--client-cert-auth=true' + - '--data-dir=/var/lib/etcd' + - '--advertise-client-urls=https://$(NAME).{{ .Release.Name }}-etcd-headless.{{ .Release.Namespace }}:2379' + - '--initial-advertise-peer-urls=https://$(NAME).{{ .Release.Name }}-etcd-headless.{{ .Release.Namespace }}:2380' + {{- $releaseName := .Release.Name -}} + {{- $releaseNamespace := .Release.Namespace }} + - '--initial-cluster={{ range $index := untilStep 0 (int $externalEtcd.highAvailability.replicas) 1 }}{{ if (ne (int $index) 0) }},{{ end }}{{ $releaseName }}-etcd-{{ $index }}=https://{{ $releaseName }}-etcd-{{ $index }}.{{ $releaseName }}-etcd-headless.{{ $releaseNamespace }}:2380{{ end }}' + - '--initial-cluster-token={{ .Release.Name }}' + - '--initial-cluster-state=new' + - '--listen-client-urls=https://0.0.0.0:2379' + - '--listen-metrics-urls=http://0.0.0.0:2381' + - '--listen-peer-urls=https://0.0.0.0:2380' + - '--key-file=/run/config/pki/etcd-server.key' + - '--name=$(NAME)' + - '--peer-cert-file=/run/config/pki/etcd-peer.crt' + - '--peer-client-cert-auth=true' + - '--peer-key-file=/run/config/pki/etcd-peer.key' + - '--peer-trusted-ca-file=/run/config/pki/etcd-ca.crt' + - '--snapshot-count=10000' + - '--trusted-ca-file=/run/config/pki/etcd-ca.crt' + {{- range $f := $externalEtcd.extraArgs }} + - {{ $f | quote }} + {{- end }} + {{- if $externalEtcd.security.containerSecurityContext }} + securityContext: +{{ toYaml $externalEtcd.security.containerSecurityContext | indent 10 }} + {{- end }} + env: + - name: NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + {{- if $externalEtcd.env }} +{{ toYaml $externalEtcd.env | indent 10 }} + {{- end }} + volumeMounts: + - name: data + mountPath: /var/lib/etcd + - mountPath: /run/config/pki + name: certs + readOnly: true + {{- if $externalEtcd.persistence.addVolumeMounts }} +{{ toYaml $externalEtcd.persistence.addVolumeMounts | indent 10 }} + {{- end }} + resources: +{{ toYaml $externalEtcd.resources | indent 10 }} + livenessProbe: + httpGet: + path: /health + port: 2381 + scheme: HTTP + initialDelaySeconds: 10 + timeoutSeconds: 15 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 8 + startupProbe: + httpGet: + path: /health + port: 2381 + scheme: HTTP + initialDelaySeconds: 10 + timeoutSeconds: 15 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 24 + {{- if $externalEtcd.imagePullPolicy }} + imagePullPolicy: {{ $externalEtcd.imagePullPolicy }} + {{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/backing-services/vcluster/templates/headless-service.yaml b/backing-services/vcluster/templates/headless-service.yaml new file mode 100644 index 0000000..08df72e --- /dev/null +++ b/backing-services/vcluster/templates/headless-service.yaml @@ -0,0 +1,43 @@ +{{- if not .Values.experimental.isolatedControlPlane.headless }} +{{- if eq (include "vcluster.kind" .) "StatefulSet" }} +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }}-headless + namespace: {{ .Release.Namespace }} + labels: + app: vcluster + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" + {{- if .Values.controlPlane.advanced.headlessService.labels }} +{{ toYaml .Values.controlPlane.advanced.headlessService.labels | indent 4 }} + {{- end }} + {{- $annotations := merge dict .Values.controlPlane.advanced.headlessService.annotations .Values.controlPlane.advanced.globalMetadata.annotations }} + {{- if $annotations }} + annotations: +{{ toYaml $annotations | indent 4 }} + {{- end }} +spec: + publishNotReadyAddresses: true + ports: + - name: https + port: 443 + targetPort: 8443 + protocol: TCP + {{- if .Values.controlPlane.backingStore.etcd.embedded.enabled }} + - name: etcd + port: 2379 + targetPort: 2379 + protocol: TCP + - name: peer + port: 2380 + targetPort: 2380 + protocol: TCP + {{- end }} + clusterIP: None + selector: + app: vcluster + release: "{{ .Release.Name }}" +{{- end }} +{{- end }} diff --git a/backing-services/vcluster/templates/ingress.yaml b/backing-services/vcluster/templates/ingress.yaml new file mode 100644 index 0000000..4ff847b --- /dev/null +++ b/backing-services/vcluster/templates/ingress.yaml @@ -0,0 +1,37 @@ +{{- if .Values.controlPlane.ingress.enabled }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + {{- $annotations := merge dict .Values.controlPlane.ingress.annotations .Values.controlPlane.advanced.globalMetadata.annotations }} + {{- if $annotations }} + annotations: + {{- toYaml $annotations | nindent 4 }} + {{- end }} + name: {{ .Release.Name }} + namespace: {{ .Release.Namespace }} + labels: + app: vcluster + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" + {{- if .Values.controlPlane.ingress.labels }} +{{ toYaml .Values.controlPlane.ingress.labels | indent 4 }} + {{- end }} +spec: + {{- if .Values.controlPlane.ingress.spec }} +{{ toYaml .Values.controlPlane.ingress.spec | indent 2 }} + {{- end }} + {{- if not .Values.controlPlane.ingress.spec.rules }} + rules: + - host: {{ .Values.controlPlane.ingress.host | quote }} + http: + paths: + - backend: + service: + name: {{ .Release.Name }} + port: + name: https + path: / + pathType: {{ .Values.controlPlane.ingress.pathType }} + {{- end }} +{{- end }} diff --git a/backing-services/vcluster/templates/limitrange.yaml b/backing-services/vcluster/templates/limitrange.yaml new file mode 100644 index 0000000..a40f415 --- /dev/null +++ b/backing-services/vcluster/templates/limitrange.yaml @@ -0,0 +1,49 @@ +{{- if or (eq (toString .Values.policies.limitRange.enabled) "true") (eq (toString .Values.policies.resourceQuota.enabled) "true") }} +{{- if not (eq (toString .Values.policies.limitRange.enabled) "false") }} +apiVersion: v1 +kind: LimitRange +metadata: + name: vc-{{ .Release.Name }} + {{- if .Values.experimental.syncSettings.targetNamespace }} + namespace: {{ .Values.experimental.syncSettings.targetNamespace }} + {{- else }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + app: vcluster + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" + {{- if .Values.policies.limitRange.labels }} +{{ toYaml .Values.policies.limitRange.labels | indent 4 }} + {{- end }} + {{- $annotations := merge dict .Values.controlPlane.advanced.globalMetadata.annotations .Values.policies.limitRange.annotations }} + {{- if $annotations }} + annotations: +{{ toYaml $annotations | indent 4 }} + {{- end }} +spec: + limits: + - default: + {{- range $key, $val := .Values.policies.limitRange.default }} + {{ $key }}: {{ $val | quote }} + {{- end }} + defaultRequest: + {{- range $key, $val := .Values.policies.limitRange.defaultRequest }} + {{ $key }}: {{ $val | quote }} + {{- end }} + {{- if .Values.policies.limitRange.min }} + min: + {{- range $key, $val := .Values.policies.limitRange.min }} + {{ $key }}: {{ $val | quote }} + {{- end }} + {{- end }} + {{- if .Values.policies.limitRange.max }} + max: + {{- range $key, $val := .Values.policies.limitRange.max }} + {{ $key }}: {{ $val | quote }} + {{- end }} + {{- end }} + type: Container +{{- end }} +{{- end }} diff --git a/backing-services/vcluster/templates/manifests.yaml b/backing-services/vcluster/templates/manifests.yaml new file mode 100644 index 0000000..44d5310 --- /dev/null +++ b/backing-services/vcluster/templates/manifests.yaml @@ -0,0 +1,7 @@ +{{- if .Values.experimental.deploy.host.manifests }} +{{ .Values.experimental.deploy.host.manifests }} +{{- end }} +{{- if .Values.experimental.deploy.host.manifestsTemplate }} +--- +{{ tpl .Values.experimental.deploy.host.manifestsTemplate . }} +{{- end }} diff --git a/backing-services/vcluster/templates/networkpolicy.yaml b/backing-services/vcluster/templates/networkpolicy.yaml new file mode 100644 index 0000000..efdf30f --- /dev/null +++ b/backing-services/vcluster/templates/networkpolicy.yaml @@ -0,0 +1,106 @@ +{{- if .Values.policies.networkPolicy.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: vc-work-{{ .Release.Name }} + {{- if .Values.experimental.syncSettings.targetNamespace }} + namespace: {{ .Values.experimental.syncSettings.targetNamespace }} + {{- else }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + app: vcluster + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" + {{- if .Values.policies.networkPolicy.labels }} +{{ toYaml .Values.policies.networkPolicy.labels | indent 4 }} + {{- end }} + {{- $annotations := merge dict .Values.controlPlane.advanced.globalMetadata.annotations .Values.policies.networkPolicy.annotations }} + {{- if $annotations }} + annotations: +{{ toYaml $annotations | indent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + vcluster.loft.sh/managed-by: {{ .Release.Name }} + egress: + # Allows outgoing connections to the vcluster control plane + - ports: + - port: 443 + - port: 8443 + to: + - podSelector: + matchLabels: + release: {{ .Release.Name }} + # Allows outgoing connections to DNS server + - ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + # Allows outgoing connections to the internet or + # other vcluster workloads + - to: + - podSelector: + matchLabels: + vcluster.loft.sh/managed-by: {{ .Release.Name }} + - ipBlock: + cidr: {{ .Values.policies.networkPolicy.outgoingConnections.ipBlock.cidr }} + except: + {{- range .Values.policies.networkPolicy.outgoingConnections.ipBlock.except }} + - {{ . }} + {{- end }} + policyTypes: + - Egress +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: vc-cp-{{ .Release.Name }} + namespace: {{ .Release.Namespace }} + labels: + app: vcluster + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" + {{- if .Values.policies.networkPolicy.labels }} +{{ toYaml .Values.policies.networkPolicy.labels | indent 4 }} + {{- end }} + {{- $annotations := merge dict .Values.controlPlane.advanced.globalMetadata.annotations .Values.policies.networkPolicy.annotations }} + {{- if $annotations }} + annotations: +{{ toYaml $annotations | indent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + release: {{ .Release.Name }} + egress: + # Allows outgoing connections to all pods with + # port 443, 8443 or 6443. This is needed for host Kubernetes + # access + - ports: + - port: 443 + - port: 8443 + - port: 6443 + # Allows outgoing connections to all vcluster workloads + # or kube system dns server + - to: + - podSelector: {} + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: 'kube-system' + podSelector: + matchLabels: + k8s-app: kube-dns + {{- if .Values.policies.networkPolicy.outgoingConnections.platform }} + - podSelector: + matchLabels: + app: loft + namespaceSelector: {} + {{- end }} + policyTypes: + - Egress + {{- end }} diff --git a/backing-services/vcluster/templates/platform-rbac.yaml b/backing-services/vcluster/templates/platform-rbac.yaml new file mode 100644 index 0000000..cb56bef --- /dev/null +++ b/backing-services/vcluster/templates/platform-rbac.yaml @@ -0,0 +1,31 @@ +{{- if include "vcluster.rbac.createPlatformSecretRole" . }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "vcluster.rbac.platformRoleName" . }} + namespace: {{ include "vcluster.rbac.platformSecretNamespace" .}} +rules: +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get"] + resourceNames: + - {{ include "vcluster.rbac.platformSecretName" . }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "vcluster.rbac.platformRoleBindingName" . }} + namespace: {{ include "vcluster.rbac.platformSecretNamespace" .}} +subjects: + - kind: ServiceAccount + {{- if .Values.controlPlane.advanced.serviceAccount.name }} + name: {{ .Values.controlPlane.advanced.serviceAccount.name }} + {{- else }} + name: vc-{{ .Release.Name }} + {{- end }} + namespace: {{ include "vcluster.rbac.platformSecretNamespace" .}} +roleRef: + kind: Role + name: {{ include "vcluster.rbac.platformRoleName" . }} + apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/backing-services/vcluster/templates/resourcequota.yaml b/backing-services/vcluster/templates/resourcequota.yaml new file mode 100644 index 0000000..5424239 --- /dev/null +++ b/backing-services/vcluster/templates/resourcequota.yaml @@ -0,0 +1,44 @@ +{{- if or (eq (toString .Values.policies.resourceQuota.enabled) "true") (eq (toString .Values.policies.limitRange.enabled) "true") }} +{{- if not (eq (toString .Values.policies.resourceQuota.enabled) "false") }} +apiVersion: v1 +kind: ResourceQuota +metadata: + name: vc-{{ .Release.Name }} + {{- if .Values.experimental.syncSettings.targetNamespace }} + namespace: {{ .Values.experimental.syncSettings.targetNamespace }} + {{- else }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + app: vcluster + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" + {{- if .Values.policies.resourceQuota.labels }} +{{ toYaml .Values.policies.resourceQuota.labels | indent 4 }} + {{- end }} + {{- $annotations := merge dict .Values.controlPlane.advanced.globalMetadata.annotations .Values.policies.resourceQuota.annotations }} + {{- if $annotations }} + annotations: +{{ toYaml $annotations | indent 4 }} + {{- end }} +spec: + {{- if .Values.policies.resourceQuota.quota }} + hard: + {{- range $key, $val := .Values.policies.resourceQuota.quota }} + {{ $key }}: {{ $val | quote }} + {{- end }} + {{- end }} + + {{- if .Values.policies.resourceQuota.scopeSelector.matchExpressions }} + scopeSelector: + matchExpressions: +{{- toYaml .Values.policies.resourceQuota.scopeSelector.matchExpressions | nindent 6 }} + {{- end }} + + {{- if .Values.policies.resourceQuota.scopes }} + scopes: +{{- toYaml .Values.policies.resourceQuota.scopes | nindent 4 }} + {{- end}} +{{- end }} +{{- end }} diff --git a/backing-services/vcluster/templates/role.yaml b/backing-services/vcluster/templates/role.yaml new file mode 100644 index 0000000..0f42803 --- /dev/null +++ b/backing-services/vcluster/templates/role.yaml @@ -0,0 +1,114 @@ +{{- if .Values.rbac.role.enabled }} +{{- if .Values.experimental.multiNamespaceMode.enabled }} +kind: ClusterRole +{{- else -}} +kind: Role +{{- end }} +apiVersion: rbac.authorization.k8s.io/v1 +metadata: +{{- if .Values.experimental.multiNamespaceMode.enabled }} + name: {{ template "vcluster.clusterRoleNameMultinamespace" . }} +{{- else }} + name: vc-{{ .Release.Name }} + namespace: {{ .Release.Namespace }} +{{- end }} + labels: + app: vcluster + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" + {{- if .Values.controlPlane.advanced.globalMetadata.annotations }} + annotations: +{{ toYaml .Values.controlPlane.advanced.globalMetadata.annotations | indent 4 }} + {{- end }} +rules: + {{- if .Values.rbac.role.overwriteRules }} +{{ toYaml .Values.rbac.role.overwriteRules | indent 2 }} + {{- else }} + - apiGroups: [""] + resources: ["configmaps", "secrets", "services", "pods", "pods/attach", "pods/portforward", "pods/exec", "persistentvolumeclaims"] + verbs: ["create", "delete", "patch", "update", "get", "list", "watch"] + - apiGroups: [""] + resources: ["pods/status", "pods/ephemeralcontainers"] + verbs: ["patch", "update"] + - apiGroups: ["apps"] + resources: ["statefulsets", "replicasets", "deployments"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["endpoints", "events", "pods/log"] + verbs: ["get", "list", "watch"] + {{- if or .Values.sync.toHost.endpoints.enabled .Values.experimental.isolatedControlPlane.headless }} + - apiGroups: [""] + resources: ["endpoints"] + verbs: ["create", "delete", "patch", "update"] + {{- end }} + {{- if gt (int .Values.controlPlane.statefulSet.highAvailability.replicas) 1 }} + - apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["create", "delete", "patch", "update", "get", "list", "watch"] + {{- end }} + {{- if (and .Values.integrations.metricsServer.enabled .Values.integrations.metricsServer.pods) }} + - apiGroups: ["metrics.k8s.io"] + resources: ["pods"] + verbs: ["get", "list"] + {{- end }} + {{- if .Values.sync.toHost.ingresses.enabled}} + - apiGroups: ["networking.k8s.io"] + resources: ["ingresses"] + verbs: ["create", "delete", "patch", "update", "get", "list", "watch"] + {{- end }} + {{- if .Values.sync.toHost.networkPolicies.enabled }} + - apiGroups: ["networking.k8s.io"] + resources: ["networkpolicies"] + verbs: ["create", "delete", "patch", "update", "get", "list", "watch"] + {{- end }} + {{- if .Values.sync.toHost.volumeSnapshots.enabled }} + - apiGroups: ["snapshot.storage.k8s.io"] + resources: ["volumesnapshots"] + verbs: ["create", "delete", "patch", "update", "get", "list", "watch"] + {{- end }} + {{- if .Values.sync.toHost.serviceAccounts.enabled }} + - apiGroups: [""] + resources: ["serviceaccounts"] + verbs: ["create", "delete", "patch", "update", "get", "list", "watch"] + {{- end }} + {{- if .Values.sync.toHost.podDisruptionBudgets.enabled }} + - apiGroups: ["policy"] + resources: ["poddisruptionbudgets"] + verbs: ["create", "delete", "patch", "update", "get", "list", "watch"] + {{- end }} + {{- if .Values.integrations.kubeVirt.enabled }} + - apiGroups: ["subresources.kubevirt.io"] + resources: ["*"] + verbs: ["create", "delete", "patch", "update", "get", "list", "watch"] + - apiGroups: ["pool.kubevirt.io"] + resources: ["virtualmachinepools", "virtualmachinepools/status"] + verbs: ["create", "delete", "patch", "update", "get", "list", "watch"] + - apiGroups: ["clone.kubevirt.io"] + resources: ["virtualmachineclones", "virtualmachineclones/status"] + verbs: ["create", "delete", "patch", "update", "get", "list", "watch"] + - apiGroups: ["cdi.kubevirt.io"] + resources: ["datavolumes", "datavolumes/status"] + verbs: ["create", "delete", "patch", "update", "get", "list", "watch"] + - apiGroups: ["kubevirt.io"] + resources: ["virtualmachines", "virtualmachines/status", "virtualmachineinstances", "virtualmachineinstances/status", "virtualmachineinstancemigrations", "virtualmachineinstancemigrations/status"] + verbs: ["create", "delete", "patch", "update", "get", "list", "watch"] + {{- end }} + {{- if .Values.integrations.externalSecrets.enabled }} + {{- if .Values.integrations.externalSecrets.sync.externalSecrets.enabled }} + - apiGroups: ["external-secrets.io"] + resources: ["externalsecrets"] + verbs: ["create", "delete", "patch", "update", "get", "list", "watch"] + {{- end }} + {{- if .Values.integrations.externalSecrets.sync.stores.enabled }} + - apiGroups: ["external-secrets.io"] + resources: ["secretstores"] + verbs: ["create", "delete", "patch", "update", "get", "list", "watch"] + {{- end }} + {{- end }} + {{- include "vcluster.customResources.roleExtraRules" . | indent 2 }} + {{- include "vcluster.plugin.roleExtraRules" . | indent 2 }} + {{- include "vcluster.generic.roleExtraRules" . | indent 2 }} + {{- include "vcluster.rbac.roleExtraRules" . | indent 2 }} + {{- end }} +{{- end }} diff --git a/backing-services/vcluster/templates/rolebinding.yaml b/backing-services/vcluster/templates/rolebinding.yaml new file mode 100644 index 0000000..0295101 --- /dev/null +++ b/backing-services/vcluster/templates/rolebinding.yaml @@ -0,0 +1,41 @@ +{{- if .Values.rbac.role.enabled }} +{{- if .Values.experimental.multiNamespaceMode.enabled }} +kind: ClusterRoleBinding +{{- else -}} +kind: RoleBinding +{{- end }} +apiVersion: rbac.authorization.k8s.io/v1 +metadata: +{{- if .Values.experimental.multiNamespaceMode.enabled }} + name: {{ template "vcluster.clusterRoleNameMultinamespace" . }} +{{- else }} + name: vc-{{ .Release.Name }} + namespace: {{ .Release.Namespace }} +{{- end }} + labels: + app: vcluster + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" + {{- if .Values.controlPlane.advanced.globalMetadata.annotations }} + annotations: +{{ toYaml .Values.controlPlane.advanced.globalMetadata.annotations | indent 4 }} + {{- end }} +subjects: + - kind: ServiceAccount + {{- if .Values.controlPlane.advanced.serviceAccount.name }} + name: {{ .Values.controlPlane.advanced.serviceAccount.name }} + {{- else }} + name: vc-{{ .Release.Name }} + {{- end }} + namespace: {{ .Release.Namespace }} +roleRef: +{{- if .Values.experimental.multiNamespaceMode.enabled }} + kind: ClusterRole + name: {{ template "vcluster.clusterRoleNameMultinamespace" . }} +{{- else }} + kind: Role + name: vc-{{ .Release.Name }} +{{- end }} + apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/backing-services/vcluster/templates/service-monitor.yaml b/backing-services/vcluster/templates/service-monitor.yaml new file mode 100644 index 0000000..a92e166 --- /dev/null +++ b/backing-services/vcluster/templates/service-monitor.yaml @@ -0,0 +1,44 @@ +{{- if .Values.controlPlane.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: vc-{{ .Release.Name }} + namespace: {{ .Release.Namespace }} + labels: + app: vcluster + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" + {{- if .Values.controlPlane.serviceMonitor.labels }} +{{ toYaml .Values.controlPlane.serviceMonitor.labels | indent 4 }} + {{- end }} + {{- $annotations := merge dict .Values.controlPlane.serviceMonitor.annotations .Values.controlPlane.advanced.globalMetadata.annotations }} + {{- if $annotations }} + annotations: +{{ toYaml $annotations | indent 4 }} + {{- end }} +spec: + selector: + matchLabels: + app: vcluster + release: "{{ .Release.Name }}" + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + heritage: "{{ .Release.Service }}" + endpoints: + - interval: 30s + port: https + path: /metrics + scheme: https + tlsConfig: + ca: + secret: + name: vc-{{ .Release.Name }} + key: certificate-authority + cert: + secret: + name: vc-{{ .Release.Name }} + key: client-certificate + keySecret: + name: vc-{{ .Release.Name }} + key: client-key +{{- end }} diff --git a/backing-services/vcluster/templates/service.yaml b/backing-services/vcluster/templates/service.yaml new file mode 100644 index 0000000..6972972 --- /dev/null +++ b/backing-services/vcluster/templates/service.yaml @@ -0,0 +1,46 @@ +{{- if .Values.controlPlane.service.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }} + namespace: {{ .Release.Namespace }} + labels: + app: vcluster + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" + {{- if .Values.controlPlane.service.labels }} +{{ toYaml .Values.controlPlane.service.labels | indent 4 }} + {{- end }} + {{- $annotations := merge dict .Values.controlPlane.advanced.globalMetadata.annotations .Values.controlPlane.service.annotations }} + {{- if $annotations }} + annotations: +{{ toYaml $annotations | indent 4 }} + {{- end }} +spec: +{{ toYaml .Values.controlPlane.service.spec | indent 2 }} + {{- if not .Values.controlPlane.service.spec.ports }} + ports: + - name: https + port: 443 + {{- if not .Values.experimental.isolatedControlPlane.headless }} + targetPort: 8443 + {{- end }} + nodePort: {{ .Values.controlPlane.service.httpsNodePort }} + protocol: TCP + {{- if and .Values.networking.advanced.proxyKubelets.byHostname (not (eq .Values.controlPlane.service.spec.type "LoadBalancer")) }} + - name: kubelet + port: 10250 + {{- if not .Values.experimental.isolatedControlPlane.headless }} + targetPort: 8443 + {{- end }} + nodePort: {{ .Values.controlPlane.service.kubeletNodePort }} + protocol: TCP + {{- end }} + {{- end }} + {{- if and (not .Values.controlPlane.service.spec.selector) (not .Values.experimental.isolatedControlPlane.headless) }} + selector: + app: vcluster + release: {{ .Release.Name }} + {{- end }} +{{- end }} diff --git a/backing-services/vcluster/templates/serviceaccount.yaml b/backing-services/vcluster/templates/serviceaccount.yaml new file mode 100644 index 0000000..6faa4d7 --- /dev/null +++ b/backing-services/vcluster/templates/serviceaccount.yaml @@ -0,0 +1,28 @@ +{{- if .Values.controlPlane.advanced.serviceAccount.enabled }} +apiVersion: v1 +kind: ServiceAccount +metadata: + {{- if .Values.controlPlane.advanced.serviceAccount.name }} + name: {{ .Values.controlPlane.advanced.serviceAccount.name | quote }} + {{- else }} + name: vc-{{ .Release.Name }} + {{- end }} + namespace: {{ .Release.Namespace }} + labels: + app: vcluster + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" + {{- if .Values.controlPlane.advanced.serviceAccount.labels }} +{{ toYaml .Values.controlPlane.advanced.serviceAccount.labels | indent 4 }} + {{- end }} + {{- $annotations := merge dict .Values.controlPlane.advanced.serviceAccount.annotations .Values.controlPlane.advanced.globalMetadata.annotations }} + {{- if $annotations }} + annotations: +{{- toYaml $annotations | nindent 4 }} + {{- end }} +{{- if .Values.controlPlane.advanced.serviceAccount.imagePullSecrets }} +imagePullSecrets: +{{ toYaml .Values.controlPlane.advanced.serviceAccount.imagePullSecrets | indent 2 }} +{{- end }} +{{- end }} diff --git a/backing-services/vcluster/templates/statefulset.yaml b/backing-services/vcluster/templates/statefulset.yaml new file mode 100644 index 0000000..22a7d46 --- /dev/null +++ b/backing-services/vcluster/templates/statefulset.yaml @@ -0,0 +1,240 @@ +{{- if not .Values.experimental.isolatedControlPlane.headless }} +apiVersion: apps/v1 +kind: {{ include "vcluster.kind" . }} +metadata: + name: {{ .Release.Name }} + namespace: {{ .Release.Namespace }} + labels: + app: vcluster + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: {{ .Release.Name }} + heritage: "{{ .Release.Service }}" + {{- if .Values.controlPlane.statefulSet.labels }} +{{ toYaml .Values.controlPlane.statefulSet.labels | indent 4 }} + {{- end }} + {{- $annotations := merge dict .Values.controlPlane.statefulSet.annotations .Values.controlPlane.advanced.globalMetadata.annotations }} + {{- if $annotations }} + annotations: +{{ toYaml $annotations | indent 4 }} + {{- end }} +spec: + selector: + matchLabels: + app: vcluster + release: {{ .Release.Name | quote }} + {{- if eq (include "vcluster.kind" .) "StatefulSet" }} + {{- if ge (int .Capabilities.KubeVersion.Minor) 27 }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.controlPlane.statefulSet.persistence.volumeClaim.retentionPolicy }} + {{- end }} + serviceName: {{ .Release.Name }}-headless + podManagementPolicy: {{ .Values.controlPlane.statefulSet.scheduling.podManagementPolicy }} +{{ include "vcluster.persistence" . | indent 2 }} + {{- else }} + strategy: + rollingUpdate: + maxSurge: 1 + {{- if (eq (int .Values.controlPlane.statefulSet.highAvailability.replicas) 1) }} + maxUnavailable: 0 + {{- else }} + maxUnavailable: 1 + {{- end }} + type: RollingUpdate + {{- end }} + replicas: {{ .Values.controlPlane.statefulSet.highAvailability.replicas }} + template: + metadata: + annotations: + vClusterConfigHash: {{ .Values | toYaml | b64enc | sha256sum | quote }} + {{- if .Values.controlPlane.statefulSet.pods.annotations }} +{{ toYaml .Values.controlPlane.statefulSet.pods.annotations | indent 8 }} + {{- end }} + labels: + app: vcluster + release: {{ .Release.Name }} + {{- if .Values.controlPlane.statefulSet.pods.labels }} +{{ toYaml .Values.controlPlane.statefulSet.pods.labels | indent 8 }} + {{- end }} + spec: + terminationGracePeriodSeconds: 10 + {{- if .Values.controlPlane.statefulSet.scheduling.priorityClassName }} + priorityClassName: {{ .Values.controlPlane.statefulSet.scheduling.priorityClassName }} + {{- end }} + {{- if .Values.controlPlane.statefulSet.security.podSecurityContext }} + securityContext: +{{ toYaml .Values.controlPlane.statefulSet.security.podSecurityContext | indent 8 }} + {{- end }} + {{- if .Values.controlPlane.statefulSet.scheduling.nodeSelector }} + nodeSelector: +{{ toYaml .Values.controlPlane.statefulSet.scheduling.nodeSelector | indent 8 }} + {{- end }} + {{- if .Values.controlPlane.statefulSet.scheduling.affinity }} + affinity: +{{ toYaml .Values.controlPlane.statefulSet.scheduling.affinity | indent 8 }} + {{- end }} + {{- if .Values.controlPlane.statefulSet.scheduling.topologySpreadConstraints }} + topologySpreadConstraints: +{{ toYaml .Values.controlPlane.statefulSet.scheduling.topologySpreadConstraints | indent 8 }} + {{- end }} + {{- if .Values.controlPlane.statefulSet.scheduling.tolerations }} + tolerations: +{{ toYaml .Values.controlPlane.statefulSet.scheduling.tolerations | indent 8 }} + {{- end }} + {{- if .Values.controlPlane.statefulSet.scheduling.priorityClassName }} + priorityClassName: {{ .Values.controlPlane.statefulSet.scheduling.priorityClassName }} + {{- end }} + {{- if .Values.controlPlane.statefulSet.dnsPolicy }} + dnsPolicy: {{ .Values.controlPlane.statefulSet.dnsPolicy }} + {{- end }} + {{- if .Values.controlPlane.statefulSet.dnsConfig }} + dnsConfig: +{{ toYaml .Values.controlPlane.statefulSet.dnsConfig | indent 8 }} + {{- end }} + {{- if .Values.controlPlane.advanced.serviceAccount.name }} + serviceAccountName: {{ .Values.controlPlane.advanced.serviceAccount.name }} + {{- else }} + serviceAccountName: vc-{{ .Release.Name }} + {{- end }} + volumes: +{{- include "vcluster.plugins.volumes" . | indent 8 }} + - name: helm-cache + emptyDir: {} +{{ toYaml .Values.controlPlane.statefulSet.persistence.binariesVolume | indent 8 }} + - name: tmp + emptyDir: {} + - name: certs + emptyDir: {} + {{- if eq (include "vcluster.distro" .) "k0s" }} + - name: run-k0s + emptyDir: {} + {{- end }} + {{- if eq (include "vcluster.distro" .) "k3s" }} + - name: k3s-config + emptyDir: {} + {{- end }} + - name: vcluster-config + secret: + secretName: vc-config-{{ .Release.Name }} + {{- if .Values.controlPlane.coredns.enabled }} + - name: coredns + configMap: + name: vc-coredns-{{ .Release.Name }} + # - name: custom-config-volume + # configMap: + # name: coredns-custom + # optional: true + {{- end }} + {{- if .Values.controlPlane.statefulSet.persistence.dataVolume }} +{{ toYaml .Values.controlPlane.statefulSet.persistence.dataVolume | indent 8 }} + {{- else if not (include "vcluster.persistence.volumeClaim.enabled" .) }} + - name: data + emptyDir: {} + {{- end }} + {{- if .Values.controlPlane.statefulSet.persistence.addVolumes }} +{{ toYaml .Values.controlPlane.statefulSet.persistence.addVolumes | indent 8 }} + {{- end }} + {{- if (not .Values.experimental.syncSettings.disableSync) }} + initContainers: +{{ include "vcluster.initContainers" . | indent 8 }} + {{- end }} + enableServiceLinks: {{ .Values.controlPlane.statefulSet.enableServiceLinks }} + containers: + - name: syncer + image: {{ include "vcluster.controlPlane.image" . | quote }} + imagePullPolicy: {{ .Values.controlPlane.statefulSet.imagePullPolicy }} + {{- if .Values.controlPlane.statefulSet.workingDir }} + workingDir: {{ .Values.controlPlane.statefulSet.workingDir }} + {{- end }} + {{- if .Values.controlPlane.statefulSet.command }} + command: +{{ toYaml .Values.controlPlane.statefulSet.command | indent 12 }} + {{- end }} + {{- if .Values.controlPlane.statefulSet.args }} + args: +{{ toYaml .Values.controlPlane.statefulSet.args | indent 12 }} + {{- end }} + {{- if .Values.controlPlane.statefulSet.probes.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: /healthz + port: 8443 + scheme: HTTPS + failureThreshold: 60 + initialDelaySeconds: 60 + periodSeconds: 2 + {{- end }} + {{- if .Values.controlPlane.statefulSet.probes.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: /readyz + port: 8443 + scheme: HTTPS + failureThreshold: 60 + periodSeconds: 2 + {{- end }} + {{- if .Values.controlPlane.statefulSet.probes.startupProbe.enabled }} + startupProbe: + httpGet: + path: /readyz + port: 8443 + scheme: HTTPS + failureThreshold: 300 + periodSeconds: 6 + {{- end }} + {{- if .Values.controlPlane.statefulSet.security.containerSecurityContext }} + securityContext: +{{ toYaml .Values.controlPlane.statefulSet.security.containerSecurityContext | indent 12 }} + {{- end }} + resources: +{{ toYaml .Values.controlPlane.statefulSet.resources | indent 12 }} + env: + - name: VCLUSTER_NAME + value: "{{ .Release.Name }}" + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + {{- if .Values.controlPlane.statefulSet.env }} +{{ toYaml .Values.controlPlane.statefulSet.env | indent 12 }} + {{- end }} +{{ include "vcluster.distro.env" . | indent 12 }} + volumeMounts: +{{- include "vcluster.plugins.volumeMounts" . | indent 12 }} + - name: data + mountPath: /data + - name: binaries + mountPath: /binaries + - name: certs + mountPath: /pki + - name: helm-cache + mountPath: /.cache/helm + {{- if eq (include "vcluster.distro" .) "k0s" }} + - name: run-k0s + mountPath: /run/k0s + {{- end }} + {{- if eq (include "vcluster.distro" .) "k3s" }} + - name: k3s-config + mountPath: /etc/rancher + {{- end }} + - name: vcluster-config + mountPath: /var/vcluster + - name: tmp + mountPath: /tmp + {{- if .Values.controlPlane.coredns.enabled }} + - name: coredns + mountPath: /manifests/coredns + readOnly: true + {{- end }} + {{- if .Values.controlPlane.statefulSet.persistence.addVolumeMounts }} +{{ toYaml .Values.controlPlane.statefulSet.persistence.addVolumeMounts | indent 12 }} + {{- end }} +{{- include "vcluster.legacyPlugins.containers" . | indent 8 }} +{{- end }} diff --git a/backing-services/vcluster/templates/workload-serviceaccount.yaml b/backing-services/vcluster/templates/workload-serviceaccount.yaml new file mode 100644 index 0000000..91a24fd --- /dev/null +++ b/backing-services/vcluster/templates/workload-serviceaccount.yaml @@ -0,0 +1,29 @@ +{{- if .Values.controlPlane.advanced.workloadServiceAccount.enabled }} +apiVersion: v1 +kind: ServiceAccount +metadata: + {{- if .Values.controlPlane.advanced.workloadServiceAccount.name }} + name: {{ .Values.controlPlane.advanced.workloadServiceAccount.name | quote }} + {{- else }} + name: vc-workload-{{ .Release.Name }} + {{- end }} + namespace: {{ .Release.Namespace }} + labels: + app: vcluster + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" + {{- if .Values.controlPlane.advanced.workloadServiceAccount.labels }} +{{ toYaml .Values.controlPlane.advanced.workloadServiceAccount.labels | indent 4 }} + {{- end }} + {{- $annotations := merge dict .Values.controlPlane.advanced.workloadServiceAccount.annotations .Values.controlPlane.advanced.globalMetadata.annotations }} + {{- if $annotations }} + annotations: +{{- toYaml $annotations | nindent 4 }} + {{- end }} +{{- $pullSecrets := concat .Values.controlPlane.advanced.serviceAccount.imagePullSecrets .Values.controlPlane.advanced.workloadServiceAccount.imagePullSecrets }} +{{- if $pullSecrets }} +imagePullSecrets: +{{ toYaml $pullSecrets | indent 2 }} +{{- end }} +{{- end }} diff --git a/backing-services/vcluster/tests/README.md b/backing-services/vcluster/tests/README.md new file mode 100644 index 0000000..56e90a9 --- /dev/null +++ b/backing-services/vcluster/tests/README.md @@ -0,0 +1,14 @@ +Add [unittest plugin](https://github.com/helm-unittest/helm-unittest) via: +``` +helm plugin install https://github.com/helm-unittest/helm-unittest.git +``` + +Run tests via: +``` +helm unittest chart +``` + +To update the `values.schema.json` run: +``` +go run hack/schema/main.go +``` diff --git a/backing-services/vcluster/tests/clusterrole_test.yaml b/backing-services/vcluster/tests/clusterrole_test.yaml new file mode 100644 index 0000000..d4a44cd --- /dev/null +++ b/backing-services/vcluster/tests/clusterrole_test.yaml @@ -0,0 +1,428 @@ +suite: ClusterRoleBinding +templates: + - clusterrole.yaml + +tests: + - it: disable by default + asserts: + - hasDocuments: + count: 0 + + - it: force enable + set: + rbac: + clusterRole: + enabled: true + asserts: + - hasDocuments: + count: 1 + + - it: force disable + set: + rbac: + clusterRole: + enabled: false + extraRules: + - apiGroups: [""] + resources: ["test123"] + verbs: ["test123"] + overwriteRules: + - apiGroups: [""] + resources: ["test"] + verbs: ["test"] + asserts: + - hasDocuments: + count: 0 + + - it: enable isolated control plane + set: + experimental: + isolatedControlPlane: + enabled: true + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: rules + count: 1 + - contains: + path: rules + content: + apiGroups: [ "" ] + resources: [ "nodes" ] + verbs: [ "get", "watch", "list" ] + + - it: enable scheduler + set: + controlPlane: + advanced: + virtualScheduler: + enabled: true + asserts: + - hasDocuments: + count: 1 + - contains: + path: rules + content: + apiGroups: [ "storage.k8s.io" ] + resources: [ "storageclasses", "csinodes", "csidrivers", "csistoragecapacities" ] + verbs: [ "get", "watch", "list" ] + + - it: enable csinodes + set: + sync: + fromHost: + csiNodes: + enabled: true + asserts: + - hasDocuments: + count: 1 + - contains: + path: rules + content: + apiGroups: [ "storage.k8s.io" ] + resources: [ "csinodes" ] + verbs: [ "get", "watch", "list" ] + + - it: enable by multi namespace mode + set: + rbac: + clusterRole: + enabled: auto + experimental: + multiNamespaceMode: + enabled: true + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: rules + count: 1 + - contains: + path: rules + content: + apiGroups: [ "" ] + resources: [ "namespaces", "serviceaccounts" ] + verbs: [ "create", "delete", "patch", "update", "get", "watch", "list" ] + + - it: override rules + set: + rbac: + clusterRole: + extraRules: + - apiGroups: [""] + resources: ["test123"] + verbs: ["test123"] + overwriteRules: + - apiGroups: [""] + resources: ["test"] + verbs: ["test"] + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: rules + count: 1 + - contains: + path: rules + content: + apiGroups: [ "" ] + resources: [ "test" ] + verbs: [ "test" ] + + - it: extra rules + set: + sync: + toHost: + priorityClasses: + enabled: true + rbac: + clusterRole: + extraRules: + - apiGroups: [ "" ] + resources: [ "test123" ] + verbs: [ "test123" ] + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: rules + count: 2 + - contains: + path: rules + content: + apiGroups: [ "" ] + resources: [ "test123" ] + verbs: [ "test123" ] + + - it: plugin rules + set: + plugin: + myTest: + rbac: + clusterRole: + extraRules: + - apiGroups: [ "" ] + resources: [ "test123" ] + verbs: [ "test123" ] + plugins: + myTest2: + rbac: + clusterRole: + extraRules: + - apiGroups: [ "" ] + resources: [ "test1234" ] + verbs: [ "test1234" ] + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: rules + count: 2 + - contains: + path: rules + content: + apiGroups: [ "" ] + resources: [ "test123" ] + verbs: [ "test123" ] + - contains: + path: rules + content: + apiGroups: [ "" ] + resources: [ "test1234" ] + verbs: [ "test1234" ] + + - it: replicate services + set: + networking: + replicateServices: + fromHost: + - from: test + to: other-test + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: rules + count: 1 + - contains: + path: rules + content: + apiGroups: [ "" ] + resources: [ "services", "endpoints" ] + verbs: [ "get", "watch", "list" ] + + - it: real nodes + set: + sync: + fromHost: + nodes: + enabled: true + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: rules + count: 1 + - contains: + path: rules + content: + apiGroups: [ "" ] + resources: [ "pods", "nodes", "nodes/status", "nodes/metrics", "nodes/stats", "nodes/proxy" ] + verbs: [ "get", "watch", "list" ] + + - it: virtual scheduler + set: + controlPlane: + advanced: + virtualScheduler: + enabled: true + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: rules + count: 1 + - contains: + path: rules + content: + apiGroups: ["storage.k8s.io"] + resources: ["storageclasses", "csinodes", "csidrivers", "csistoragecapacities"] + verbs: ["get", "watch", "list"] + + - it: legacy pro + set: + pro: true + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: rules + count: 3 + - contains: + path: rules + content: + apiGroups: [ "" ] + resources: [ "pods", "nodes", "nodes/status", "nodes/metrics", "nodes/stats", "nodes/proxy" ] + verbs: [ "get", "watch", "list" ] + - contains: + path: rules + content: + apiGroups: [ "cluster.loft.sh", "storage.loft.sh" ] + resources: [ "features", "virtualclusters" ] + verbs: [ "get", "list", "watch" ] + - contains: + path: rules + content: + apiGroups: ["management.loft.sh"] + resources: ["virtualclusterinstances"] + verbs: ["get"] + + - it: metrics proxy + set: + integrations: + metricsServer: + enabled: true + nodes: true + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - contains: + path: rules + content: + apiGroups: [ "metrics.k8s.io" ] + resources: [ "nodes" ] + verbs: [ "get", "list" ] + + - it: externalSecrets + set: + integrations: + externalSecrets: + enabled: true + webhook: + enabled: false + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: rules + count: 1 + - contains: + path: rules + content: + apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch"] + - it: kubeVirt + set: + integrations: + kubeVirt: + enabled: true + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: rules + count: 2 + - contains: + path: rules + content: + apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch"] + - contains: + path: rules + content: + apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations", "mutatingwebhookconfigurations"] + verbs: ["get", "list", "watch"] + + - it: crd sync to host + set: + sync: + toHost: + customResources: + test.test-group: + enabled: true + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: rules + count: 1 + - contains: + path: rules + content: + apiGroups: [ "apiextensions.k8s.io" ] + resources: [ "customresourcedefinitions" ] + verbs: [ "get", "list", "watch" ] + + - it: crd sync from host + set: + sync: + fromHost: + customResources: + test.test-group: + enabled: true + scope: Cluster + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: rules + count: 2 + - contains: + path: rules + content: + apiGroups: [ "test-group" ] + resources: [ "test" ] + verbs: [ "get", "list", "watch" ] + - contains: + path: rules + content: + apiGroups: [ "apiextensions.k8s.io" ] + resources: [ "customresourcedefinitions" ] + verbs: [ "get", "list", "watch" ] + - it: eso clusterstore sync + set: + integrations: + externalSecrets: + enabled: true + webhook: + enabled: true + sync: + clusterStores: + enabled: true + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - contains: + path: rules + content: + apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations", "mutatingwebhookconfigurations"] + verbs: ["get", "list", "watch"] + - contains: + path: rules + content: + apiGroups: [ "external-secrets.io" ] + resources: [ "clustersecretstores" ] + verbs: ["get", "list", "watch"] diff --git a/backing-services/vcluster/tests/clusterrolebinding_test.yaml b/backing-services/vcluster/tests/clusterrolebinding_test.yaml new file mode 100644 index 0000000..89a751b --- /dev/null +++ b/backing-services/vcluster/tests/clusterrolebinding_test.yaml @@ -0,0 +1,141 @@ +suite: ClusterRoleBinding +templates: + - clusterrolebinding.yaml + +tests: + - it: disable by default + asserts: + - hasDocuments: + count: 0 + + - it: enable by multi namespace mode + set: + experimental: + multiNamespaceMode: + enabled: true + asserts: + - hasDocuments: + count: 1 + + - it: enable by from syncer + set: + sync: + fromHost: + ingressClasses: + enabled: true + asserts: + - hasDocuments: + count: 1 + + - it: enable by generic sync + set: + experimental: + genericSync: + clusterRole: + extraRules: + - apiGroups: [""] + resources: ["test"] + verbs: ["test"] + asserts: + - hasDocuments: + count: 1 + + - it: enable by plugins + set: + plugins: + test: + rbac: + clusterRole: + extraRules: + - apiGroups: [""] + resources: ["test"] + verbs: ["test"] + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + + - it: enable by plugin + set: + plugin: + test: + rbac: + clusterRole: + extraRules: + - apiGroups: [""] + resources: ["test"] + verbs: ["test"] + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + + - it: enable by legacy api key + set: + pro: true + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - equal: + path: kind + value: ClusterRoleBinding + - equal: + path: metadata.name + value: vc-my-release-v-my-namespace + - notExists: + path: metadata.namespace + + - it: enable by extra rules + set: + rbac: + clusterRole: + extraRules: + - apiGroups: [""] + resources: ["test"] + verbs: ["test"] + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - equal: + path: kind + value: ClusterRoleBinding + - equal: + path: metadata.name + value: vc-my-release-v-my-namespace + - notExists: + path: metadata.namespace + + - it: enable by overwrite rules + set: + rbac: + clusterRole: + overwriteRules: + - apiGroups: [""] + resources: ["test"] + verbs: ["test"] + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - equal: + path: kind + value: ClusterRoleBinding + - equal: + path: metadata.name + value: vc-my-release-v-my-namespace + - notExists: + path: metadata.namespace + + diff --git a/backing-services/vcluster/tests/coredns-configmap_test.yaml b/backing-services/vcluster/tests/coredns-configmap_test.yaml new file mode 100644 index 0000000..263ce2b --- /dev/null +++ b/backing-services/vcluster/tests/coredns-configmap_test.yaml @@ -0,0 +1,577 @@ +suite: CoreDNS Configmap +templates: + - coredns-configmap.yaml + +tests: + - it: should create configmap + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - equal: + path: metadata.name + value: vc-coredns-my-release + - equal: + path: metadata.namespace + value: my-namespace + + - it: should create correct external coredns config + asserts: + - hasDocuments: + count: 1 + - notExists: + path: data.Corefile + - equal: + path: data["coredns.yaml"] + value: |- + apiVersion: v1 + kind: ServiceAccount + metadata: + name: coredns + namespace: kube-system + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRole + metadata: + labels: + kubernetes.io/bootstrapping: rbac-defaults + name: system:coredns + rules: + - apiGroups: + - "" + resources: + - endpoints + - services + - pods + - namespaces + verbs: + - list + - watch + - apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - list + - watch + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRoleBinding + metadata: + annotations: + rbac.authorization.kubernetes.io/autoupdate: "true" + labels: + kubernetes.io/bootstrapping: rbac-defaults + name: system:coredns + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:coredns + subjects: + - kind: ServiceAccount + name: coredns + namespace: kube-system + --- + apiVersion: v1 + kind: ConfigMap + metadata: + name: coredns + namespace: kube-system + data: + Corefile: |- + .:1053 { + errors + health + ready + rewrite name regex .*\.nodes\.vcluster\.com kubernetes.default.svc.cluster.local + kubernetes cluster.local in-addr.arpa ip6.arpa { + pods insecure + fallthrough in-addr.arpa ip6.arpa + } + hosts /etc/NodeHosts { + ttl 60 + reload 15s + fallthrough + } + prometheus :9153 + forward . /etc/resolv.conf + cache 30 + loop + loadbalance + } + + import /etc/coredns/custom/*.server + NodeHosts: "" + --- + apiVersion: apps/v1 + kind: Deployment + metadata: + name: coredns + namespace: kube-system + labels: + k8s-app: kube-dns + kubernetes.io/name: "CoreDNS" + spec: + replicas: 1 + strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + selector: + matchLabels: + k8s-app: kube-dns + template: + metadata: + labels: + k8s-app: kube-dns + spec: + priorityClassName: "" + serviceAccountName: coredns + nodeSelector: + kubernetes.io/os: linux + topologySpreadConstraints: + - labelSelector: + matchLabels: + k8s-app: kube-dns + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: DoNotSchedule + containers: + - name: coredns + image: {{.IMAGE}} + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 1000m + memory: 170Mi + requests: + cpu: 20m + memory: 64Mi + args: [ "-conf", "/etc/coredns/Corefile" ] + volumeMounts: + - name: config-volume + mountPath: /etc/coredns + readOnly: true + - name: custom-config-volume + mountPath: /etc/coredns/custom + readOnly: true + securityContext: + runAsNonRoot: true + runAsUser: {{.RUN_AS_USER}} + runAsGroup: {{.RUN_AS_GROUP}} + allowPrivilegeEscalation: false + capabilities: + add: + - NET_BIND_SERVICE + drop: + - ALL + readOnlyRootFilesystem: true + livenessProbe: + httpGet: + path: /health + port: 8080 + scheme: HTTP + initialDelaySeconds: 60 + periodSeconds: 10 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /ready + port: 8181 + scheme: HTTP + initialDelaySeconds: 0 + periodSeconds: 2 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 3 + dnsPolicy: Default + volumes: + - name: config-volume + configMap: + name: coredns + items: + - key: Corefile + path: Corefile + - key: NodeHosts + path: NodeHosts + - name: custom-config-volume + configMap: + name: coredns-custom + optional: true + --- + apiVersion: v1 + kind: Service + metadata: + name: kube-dns + namespace: kube-system + annotations: + prometheus.io/port: "9153" + prometheus.io/scrape: "true" + labels: + k8s-app: kube-dns + kubernetes.io/cluster-service: "true" + kubernetes.io/name: "CoreDNS" + spec: + type: ClusterIP + selector: + k8s-app: kube-dns + ports: + - name: dns + port: 53 + targetPort: 1053 + protocol: UDP + - name: dns-tcp + port: 53 + targetPort: 1053 + protocol: TCP + - name: metrics + port: 9153 + protocol: TCP + + - it: should create correct custom configmap + set: + controlPlane: + coredns: + embedded: true + overwriteManifests: |- + abc + asserts: + - hasDocuments: + count: 1 + - equal: + path: data["coredns.yaml"] + value: |- + abc + + - it: should create correct custom configmap + set: + controlPlane: + coredns: + embedded: true + overwriteConfig: |- + abc + asserts: + - hasDocuments: + count: 1 + - equal: + path: data.Corefile + value: |- + abc + + - it: should create correct embedded configmap + set: + controlPlane: + coredns: + embedded: true + asserts: + - hasDocuments: + count: 1 + - equal: + path: data.Corefile + value: |- + .:1053 { + errors + health + ready + rewrite name regex .*\.nodes\.vcluster\.com kubernetes.default.svc.cluster.local + kubernetes cluster.local in-addr.arpa ip6.arpa { + kubeconfig /data/vcluster/admin.conf + pods insecure + fallthrough in-addr.arpa ip6.arpa + } + hosts /etc/NodeHosts { + ttl 60 + reload 15s + fallthrough + } + prometheus :9153 + forward . /etc/resolv.conf + cache 30 + loop + loadbalance + } + + import /etc/coredns/custom/*.server + - equal: + path: data["coredns.yaml"] + value: |- + apiVersion: v1 + kind: ConfigMap + metadata: + name: coredns + namespace: kube-system + data: + NodeHosts: "" + --- + apiVersion: v1 + kind: Service + metadata: + name: kube-dns + namespace: kube-system + annotations: + prometheus.io/port: "9153" + prometheus.io/scrape: "true" + labels: + k8s-app: kube-dns + kubernetes.io/cluster-service: "true" + kubernetes.io/name: "CoreDNS" + spec: + type: ClusterIP + ports: + - name: dns + port: 53 + targetPort: 1053 + protocol: UDP + - name: dns-tcp + port: 53 + targetPort: 1053 + protocol: TCP + - name: metrics + port: 9153 + protocol: TCP + - it: should correctly apply affinity and tolerations + set: + controlPlane: + coredns: + deployment: + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app + operator: In + values: + - coredns + topologyKey: kubernetes.io/hostname + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + operator: Exists + asserts: + - equal: + path: data["coredns.yaml"] + value: |- + apiVersion: v1 + kind: ServiceAccount + metadata: + name: coredns + namespace: kube-system + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRole + metadata: + labels: + kubernetes.io/bootstrapping: rbac-defaults + name: system:coredns + rules: + - apiGroups: + - "" + resources: + - endpoints + - services + - pods + - namespaces + verbs: + - list + - watch + - apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - list + - watch + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRoleBinding + metadata: + annotations: + rbac.authorization.kubernetes.io/autoupdate: "true" + labels: + kubernetes.io/bootstrapping: rbac-defaults + name: system:coredns + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:coredns + subjects: + - kind: ServiceAccount + name: coredns + namespace: kube-system + --- + apiVersion: v1 + kind: ConfigMap + metadata: + name: coredns + namespace: kube-system + data: + Corefile: |- + .:1053 { + errors + health + ready + rewrite name regex .*\.nodes\.vcluster\.com kubernetes.default.svc.cluster.local + kubernetes cluster.local in-addr.arpa ip6.arpa { + pods insecure + fallthrough in-addr.arpa ip6.arpa + } + hosts /etc/NodeHosts { + ttl 60 + reload 15s + fallthrough + } + prometheus :9153 + forward . /etc/resolv.conf + cache 30 + loop + loadbalance + } + + import /etc/coredns/custom/*.server + NodeHosts: "" + --- + apiVersion: apps/v1 + kind: Deployment + metadata: + name: coredns + namespace: kube-system + labels: + k8s-app: kube-dns + kubernetes.io/name: "CoreDNS" + spec: + replicas: 1 + strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + selector: + matchLabels: + k8s-app: kube-dns + template: + metadata: + labels: + k8s-app: kube-dns + spec: + priorityClassName: "" + serviceAccountName: coredns + nodeSelector: + kubernetes.io/os: linux + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app + operator: In + values: + - coredns + topologyKey: kubernetes.io/hostname + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + operator: Exists + topologySpreadConstraints: + - labelSelector: + matchLabels: + k8s-app: kube-dns + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: DoNotSchedule + containers: + - name: coredns + image: {{.IMAGE}} + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 1000m + memory: 170Mi + requests: + cpu: 20m + memory: 64Mi + args: [ "-conf", "/etc/coredns/Corefile" ] + volumeMounts: + - name: config-volume + mountPath: /etc/coredns + readOnly: true + - name: custom-config-volume + mountPath: /etc/coredns/custom + readOnly: true + securityContext: + runAsNonRoot: true + runAsUser: {{.RUN_AS_USER}} + runAsGroup: {{.RUN_AS_GROUP}} + allowPrivilegeEscalation: false + capabilities: + add: + - NET_BIND_SERVICE + drop: + - ALL + readOnlyRootFilesystem: true + livenessProbe: + httpGet: + path: /health + port: 8080 + scheme: HTTP + initialDelaySeconds: 60 + periodSeconds: 10 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /ready + port: 8181 + scheme: HTTP + initialDelaySeconds: 0 + periodSeconds: 2 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 3 + dnsPolicy: Default + volumes: + - name: config-volume + configMap: + name: coredns + items: + - key: Corefile + path: Corefile + - key: NodeHosts + path: NodeHosts + - name: custom-config-volume + configMap: + name: coredns-custom + optional: true + --- + apiVersion: v1 + kind: Service + metadata: + name: kube-dns + namespace: kube-system + annotations: + prometheus.io/port: "9153" + prometheus.io/scrape: "true" + labels: + k8s-app: kube-dns + kubernetes.io/cluster-service: "true" + kubernetes.io/name: "CoreDNS" + spec: + type: ClusterIP + selector: + k8s-app: kube-dns + ports: + - name: dns + port: 53 + targetPort: 1053 + protocol: UDP + - name: dns-tcp + port: 53 + targetPort: 1053 + protocol: TCP + - name: metrics + port: 9153 + protocol: TCP diff --git a/backing-services/vcluster/tests/etcd-headless-service_test.yaml b/backing-services/vcluster/tests/etcd-headless-service_test.yaml new file mode 100644 index 0000000..fb58ea7 --- /dev/null +++ b/backing-services/vcluster/tests/etcd-headless-service_test.yaml @@ -0,0 +1,125 @@ +suite: External etcd headless Service +templates: + - etcd-headless-service.yaml + +tests: + - it: check disabled + asserts: + - hasDocuments: + count: 0 + + - it: enable for k3s & defaults + release: + name: my-release + namespace: my-namespace + set: + controlPlane: + backingStore: + etcd: + deploy: + enabled: true + headlessService: + annotations: + test: test + distro: + k3s: + enabled: true + asserts: + - hasDocuments: + count: 1 + - equal: + path: metadata.name + value: my-release-etcd-headless + - equal: + path: metadata.namespace + value: my-namespace + - equal: + path: metadata.annotations.test + value: test + + - it: enable for k0s & defaults + release: + name: my-release + namespace: my-namespace + set: + controlPlane: + backingStore: + etcd: + deploy: + enabled: true + headlessService: + annotations: + test: test + distro: + k0s: + enabled: true + asserts: + - hasDocuments: + count: 1 + - equal: + path: metadata.name + value: my-release-etcd-headless + - equal: + path: metadata.namespace + value: my-namespace + - equal: + path: metadata.annotations.test + value: test + + - it: enable for k8s & defaults + release: + name: my-release + namespace: my-namespace + set: + controlPlane: + backingStore: + etcd: + deploy: + enabled: true + headlessService: + annotations: + test: test + distro: + k8s: + enabled: true + asserts: + - hasDocuments: + count: 1 + - equal: + path: metadata.name + value: my-release-etcd-headless + - equal: + path: metadata.namespace + value: my-namespace + - equal: + path: metadata.annotations.test + value: test + + - it: enable for k8s & defaults + release: + name: my-release + namespace: my-namespace + set: + controlPlane: + backingStore: + etcd: + deploy: + enabled: true + headlessService: + annotations: + test: test + distro: + k8s: + enabled: true + asserts: + - hasDocuments: + count: 1 + - equal: + path: metadata.name + value: my-release-etcd-headless + - equal: + path: metadata.namespace + value: my-namespace + - equal: + path: metadata.annotations.test + value: test diff --git a/backing-services/vcluster/tests/etcd-service_test.yaml b/backing-services/vcluster/tests/etcd-service_test.yaml new file mode 100644 index 0000000..fb44431 --- /dev/null +++ b/backing-services/vcluster/tests/etcd-service_test.yaml @@ -0,0 +1,38 @@ +suite: External etcd Service +templates: + - etcd-service.yaml + +tests: + - it: check disabled + asserts: + - hasDocuments: + count: 0 + + - it: enable for k8s & defaults + release: + name: my-release + namespace: my-namespace + set: + controlPlane: + backingStore: + etcd: + deploy: + enabled: true + service: + annotations: + test: test + distro: + k8s: + enabled: true + asserts: + - hasDocuments: + count: 1 + - equal: + path: metadata.name + value: my-release-etcd + - equal: + path: metadata.namespace + value: my-namespace + - equal: + path: metadata.annotations.test + value: test diff --git a/backing-services/vcluster/tests/etcd-statefulset_test.yaml b/backing-services/vcluster/tests/etcd-statefulset_test.yaml new file mode 100644 index 0000000..edd5a97 --- /dev/null +++ b/backing-services/vcluster/tests/etcd-statefulset_test.yaml @@ -0,0 +1,196 @@ +suite: External etcd StatefulSet +templates: + - etcd-statefulset.yaml + +tests: + - it: check disabled + asserts: + - hasDocuments: + count: 0 + + - it: check disabled headless + set: + controlPlane: + distro: + k8s: + enabled: true + experimental: + isolatedControlPlane: + headless: true + asserts: + - hasDocuments: + count: 0 + + - it: check default image registry + set: + controlPlane: + backingStore: + etcd: + deploy: + enabled: true + statefulSet: + image: + tag: "123" + advanced: + defaultImageRegistry: fabi.com + asserts: + - hasDocuments: + count: 1 + - equal: + path: spec.template.spec.containers[0].image + value: fabi.com/etcd:123 + + - it: disables serviceLinks for backingStore etcd pod + set: + controlPlane: + backingStore: + etcd: + deploy: + enabled: true + statefulSet: + enabled: true + enableServiceLinks: false + asserts: + - hasDocuments: + count: 1 + - equal: + path: spec.template.spec.enableServiceLinks + value: false + + - it: change image registry + set: + controlPlane: + backingStore: + etcd: + deploy: + enabled: true + statefulSet: + image: + registry: fabi.com + tag: "123" + asserts: + - hasDocuments: + count: 1 + - equal: + path: spec.template.spec.containers[0].image + value: fabi.com/etcd:123 + + - it: check specified storage class is used + set: + controlPlane: + backingStore: + etcd: + deploy: + enabled: true + statefulSet: + persistence: + volumeClaim: + storageClass: test-sc + asserts: + - hasDocuments: + count: 1 + - equal: + path: spec.volumeClaimTemplates[0].spec.storageClassName + value: test-sc + + - it: enabled for k3s & non persistent + set: + controlPlane: + backingStore: + etcd: + deploy: + enabled: true + statefulSet: + extraArgs: + - "extra-arg" + env: + - name: my-new-env + persistence: + volumeClaim: + enabled: false + addVolumes: + - name: my-new-volume + addVolumeMounts: + - name: my-new-volume + asserts: + - hasDocuments: + count: 1 + - contains: + path: spec.template.spec.volumes + content: + name: "data" + emptyDir: {} + count: 1 + - notExists: + path: spec.volumeClaimTemplates + - contains: + path: spec.template.spec.volumes + content: + name: "my-new-volume" + count: 1 + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: "my-new-volume" + count: 1 + - contains: + path: spec.template.spec.containers[0].env + content: + name: "my-new-env" + count: 1 + - contains: + path: spec.template.spec.containers[0].command + content: "extra-arg" + count: 1 + + - it: enable for k8s & defaults + release: + name: my-release + namespace: my-namespace + set: + controlPlane: + backingStore: + etcd: + deploy: + enabled: true + statefulSet: + highAvailability: + replicas: 3 + annotations: + test: test + distro: + k8s: + enabled: true + asserts: + - hasDocuments: + count: 1 + - equal: + path: metadata.name + value: my-release-etcd + - equal: + path: metadata.namespace + value: my-namespace + - equal: + path: metadata.annotations.test + value: test + - equal: + path: spec.replicas + value: 3 + - lengthEqual: + path: spec.volumeClaimTemplates + count: 1 + - lengthEqual: + path: spec.template.spec.volumes + count: 1 + - lengthEqual: + path: spec.template.spec.containers[0].volumeMounts + count: 2 + - lengthEqual: + path: spec.template.spec.containers[0].env + count: 1 + - notExists: + path: spec.template.spec.containers[0].args + - contains: + path: spec.template.spec.containers[0].command + content: "--initial-cluster=my-release-etcd-0=https://my-release-etcd-0.my-release-etcd-headless.my-namespace:2380,my-release-etcd-1=https://my-release-etcd-1.my-release-etcd-headless.my-namespace:2380,my-release-etcd-2=https://my-release-etcd-2.my-release-etcd-headless.my-namespace:2380" + count: 1 diff --git a/backing-services/vcluster/tests/headless-service_test.yaml b/backing-services/vcluster/tests/headless-service_test.yaml new file mode 100644 index 0000000..c0b8cbb --- /dev/null +++ b/backing-services/vcluster/tests/headless-service_test.yaml @@ -0,0 +1,97 @@ +suite: ControlPlane StatefulSet +templates: + - headless-service.yaml + +tests: + - it: should not create control-plane + set: + experimental: + isolatedControlPlane: + headless: true + asserts: + - hasDocuments: + count: 0 + + - it: should create if k8s + set: + controlPlane: + distro: + k8s: + enabled: true + asserts: + - hasDocuments: + count: 1 + + - it: should not create if stateless + set: + controlPlane: + backingStore: + etcd: + deploy: + enabled: true + asserts: + - hasDocuments: + count: 0 + + - it: should not create if stateless 2 + set: + controlPlane: + backingStore: + database: + external: + enabled: true + asserts: + - hasDocuments: + count: 0 + + - it: name + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: spec.ports + count: 1 + - equal: + path: metadata.name + value: my-release-headless + - equal: + path: metadata.namespace + value: my-namespace + + - it: embedded-etcd + set: + controlPlane: + backingStore: + etcd: + embedded: + enabled: true + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: spec.ports + count: 3 + - equal: + path: spec.ports[1].name + value: etcd + - equal: + path: spec.ports[2].name + value: peer + + - it: embedded-database + set: + controlPlane: + backingStore: + database: + embedded: + enabled: true + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: spec.ports + count: 1 + diff --git a/backing-services/vcluster/tests/ingress_test.yaml b/backing-services/vcluster/tests/ingress_test.yaml new file mode 100644 index 0000000..c5a11d8 --- /dev/null +++ b/backing-services/vcluster/tests/ingress_test.yaml @@ -0,0 +1,56 @@ +suite: ControlPlane Ingress +templates: + - ingress.yaml + +tests: + - it: should not create ingress by default + asserts: + - hasDocuments: + count: 0 + + - it: ingress defaults + set: + controlPlane: + ingress: + enabled: true + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - equal: + path: metadata.name + value: my-release + - equal: + path: metadata.namespace + value: my-namespace + + - it: overwrite ingress tls + set: + controlPlane: + ingress: + enabled: true + host: my-host + spec: + tls: + - hosts: + - ingress-demo.example.com + secretName: ingress-demo-tls + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: spec.tls + count: 1 + - equal: + path: spec.rules[0].host + value: my-host + - contains: + path: spec.tls + count: 1 + content: + hosts: + - ingress-demo.example.com + secretName: ingress-demo-tls + diff --git a/backing-services/vcluster/tests/limitrange_test.yaml b/backing-services/vcluster/tests/limitrange_test.yaml new file mode 100644 index 0000000..bf6cd9d --- /dev/null +++ b/backing-services/vcluster/tests/limitrange_test.yaml @@ -0,0 +1,94 @@ +suite: LimitRange +templates: + - limitrange.yaml + +tests: + - it: should not create limit range by default + asserts: + - hasDocuments: + count: 0 + + - it: check defaults + release: + name: my-release + namespace: my-namespace + set: + policies: + limitRange: + enabled: true + asserts: + - hasDocuments: + count: 1 + - equal: + path: metadata.name + value: vc-my-release + - equal: + path: metadata.namespace + value: my-namespace + - lengthEqual: + path: spec.limits + count: 1 + + - it: check enabled + release: + name: my-release + namespace: my-namespace + set: + policies: + resourceQuota: + enabled: true + asserts: + - hasDocuments: + count: 1 + + - it: check disabled + release: + name: my-release + namespace: my-namespace + set: + policies: + resourceQuota: + enabled: true + limitRange: + enabled: false + asserts: + - hasDocuments: + count: 0 + + - it: check disabled both false + release: + name: my-release + namespace: my-namespace + set: + policies: + resourceQuota: + enabled: false + limitRange: + enabled: false + asserts: + - hasDocuments: + count: 0 + + - it: check disabled both false + release: + name: my-release + namespace: my-namespace + set: + policies: + limitRange: + enabled: true + min: + cpu: 1 + max: + memory: 256Mi + asserts: + - hasDocuments: + count: 1 + - equal: + path: spec.limits[0].min.cpu + value: "1" + - equal: + path: spec.limits[0].max.memory + value: "256Mi" + + diff --git a/backing-services/vcluster/tests/manifests_test.yaml b/backing-services/vcluster/tests/manifests_test.yaml new file mode 100644 index 0000000..974b40d --- /dev/null +++ b/backing-services/vcluster/tests/manifests_test.yaml @@ -0,0 +1,94 @@ +suite: Manifests +templates: + - manifests.yaml + +tests: + - it: should not create manifests by default + asserts: + - hasDocuments: + count: 0 + + - it: check defaults + release: + name: my-release + namespace: my-namespace + set: + experimental: + deploy: + vcluster: + manifests: |- + apiVersion: v1 + kind: Pod + metadata: + name: nginx + labels: + app: nginx + spec: + containers: + - image: nginx + name: nginx + asserts: + - hasDocuments: + count: 0 + + - it: check defaults + release: + name: my-release + namespace: my-namespace + set: + experimental: + deploy: + host: + manifests: |- + apiVersion: v1 + kind: Pod + metadata: + name: nginx + labels: + app: nginx + spec: + containers: + - image: nginx + name: nginx + asserts: + - hasDocuments: + count: 1 + - equal: + path: kind + value: Pod + - equal: + path: spec.containers[0].name + value: nginx + + - it: check defaults + release: + name: my-release + namespace: my-namespace + set: + experimental: + deploy: + host: + manifestsTemplate: |- + apiVersion: v1 + kind: Pod + metadata: + name: nginx + namespace: {{ .Release.Namespace }} + labels: + app: nginx + spec: + containers: + - image: nginx + name: nginx + asserts: + - hasDocuments: + count: 1 + - equal: + path: kind + value: Pod + - equal: + path: metadata.namespace + value: my-namespace + - equal: + path: spec.containers[0].name + value: nginx diff --git a/backing-services/vcluster/tests/networkpolicy_test.yaml b/backing-services/vcluster/tests/networkpolicy_test.yaml new file mode 100644 index 0000000..06da055 --- /dev/null +++ b/backing-services/vcluster/tests/networkpolicy_test.yaml @@ -0,0 +1,49 @@ +suite: NetworkPolicy +templates: + - networkpolicy.yaml + +tests: + - it: should not create network policy by default + asserts: + - hasDocuments: + count: 0 + + - it: check defaults + release: + name: my-release + namespace: my-namespace + set: + policies: + networkPolicy: + enabled: true + asserts: + - hasDocuments: + count: 2 + - documentIndex: 0 + equal: + path: metadata.name + value: vc-work-my-release + - documentIndex: 0 + equal: + path: spec.egress[2].to[1].ipBlock.cidr + value: 0.0.0.0/0 + - documentIndex: 1 + equal: + path: metadata.name + value: vc-cp-my-release + - documentIndex: 0 + equal: + path: metadata.namespace + value: my-namespace + - documentIndex: 1 + equal: + path: metadata.namespace + value: my-namespace + - documentIndex: 0 + lengthEqual: + path: spec.egress + count: 3 + - documentIndex: 1 + lengthEqual: + path: spec.egress + count: 2 diff --git a/backing-services/vcluster/tests/platform-secret-role_test.yaml b/backing-services/vcluster/tests/platform-secret-role_test.yaml new file mode 100644 index 0000000..4ad0323 --- /dev/null +++ b/backing-services/vcluster/tests/platform-secret-role_test.yaml @@ -0,0 +1,114 @@ +suite: Platform Secret Role +templates: + - platform-rbac.yaml + +tests: + - it: check explicitly disabled + set: + external: + platform: + apiKey: + namespace: "some-other-namespace" + createRBAC: false + asserts: + - hasDocuments: + count: 0 + + - it: check disabled on empty namespace + set: + external: + platform: + apiKey: + namespace: "" + asserts: + - hasDocuments: + count: 0 + + - it: check disabled on implicit same namespace + set: + external: + platform: + apiKey: + secretName: "some-other-secret" + asserts: + - hasDocuments: + count: 0 + + - it: automatically create role for specific secret for reading & patching + set: + external: + platform: + apiKey: + secretName: "my-secret-name" + namespace: "some-other-namespace" + asserts: + - hasDocuments: + count: 2 + - documentIndex: 0 + lengthEqual: + path: rules + count: 1 + - documentIndex: 0 + equal: + path: metadata.name + value: "vc-RELEASE-NAME-v-NAMESPACE-platform-role" + - documentIndex: 1 + equal: + path: metadata.name + value: "vc-RELEASE-NAME-v-NAMESPACE-platform-role-binding" + - documentIndex: 0 + contains: + path: rules + count: 1 + content: + apiGroups: [""] + resources: ["secrets"] + verbs: ["get"] + resourceNames: ["my-secret-name"] + - documentIndex: 1 + contains: + path: subjects + count: 1 + content: + kind: ServiceAccount + name: vc-RELEASE-NAME + namespace: some-other-namespace + + - it: automatically create role for default secret for reading & patching + set: + external: + platform: + apiKey: + namespace: "some-other-namespace" + asserts: + - hasDocuments: + count: 2 + - documentIndex: 0 + lengthEqual: + path: rules + count: 1 + - documentIndex: 0 + equal: + path: metadata.name + value: "vc-RELEASE-NAME-v-NAMESPACE-platform-role" + - documentIndex: 1 + equal: + path: metadata.name + value: "vc-RELEASE-NAME-v-NAMESPACE-platform-role-binding" + - documentIndex: 0 + contains: + path: rules + count: 1 + content: + apiGroups: [""] + resources: ["secrets"] + verbs: ["get"] + resourceNames: ["vcluster-platform-api-key"] + - documentIndex: 1 + contains: + path: subjects + count: 1 + content: + kind: ServiceAccount + name: vc-RELEASE-NAME + namespace: some-other-namespace diff --git a/backing-services/vcluster/tests/resourcequota_test.yaml b/backing-services/vcluster/tests/resourcequota_test.yaml new file mode 100644 index 0000000..a1933b9 --- /dev/null +++ b/backing-services/vcluster/tests/resourcequota_test.yaml @@ -0,0 +1,70 @@ +suite: ResourceQuota +templates: + - resourcequota.yaml + +tests: + - it: should not create resource quota by default + asserts: + - hasDocuments: + count: 0 + + - it: check defaults + release: + name: my-release + namespace: my-namespace + set: + policies: + resourceQuota: + enabled: true + asserts: + - hasDocuments: + count: 1 + - equal: + path: metadata.name + value: vc-my-release + - equal: + path: metadata.namespace + value: my-namespace + - equal: + path: spec.hard["requests.cpu"] + value: "10" + + - it: check enabled + release: + name: my-release + namespace: my-namespace + set: + policies: + limitRange: + enabled: true + asserts: + - hasDocuments: + count: 1 + + - it: check disabled + release: + name: my-release + namespace: my-namespace + set: + policies: + resourceQuota: + enabled: false + limitRange: + enabled: true + asserts: + - hasDocuments: + count: 0 + + - it: check disabled both false + release: + name: my-release + namespace: my-namespace + set: + policies: + resourceQuota: + enabled: false + limitRange: + enabled: false + asserts: + - hasDocuments: + count: 0 diff --git a/backing-services/vcluster/tests/role_test.yaml b/backing-services/vcluster/tests/role_test.yaml new file mode 100644 index 0000000..10667ba --- /dev/null +++ b/backing-services/vcluster/tests/role_test.yaml @@ -0,0 +1,349 @@ +suite: Role +templates: + - role.yaml + +tests: + - it: check disabled + set: + rbac: + role: + enabled: false + asserts: + - hasDocuments: + count: 0 + + - it: check overwrite rules + set: + rbac: + role: + overwriteRules: + - apiGroups: [""] + resources: ["configmaps"] + verbs: ["create"] + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: rules + count: 1 + - contains: + path: rules + count: 1 + content: + apiGroups: [""] + resources: ["configmaps"] + verbs: ["create"] + + - it: check plugin extra rules + set: + plugin: + test123: + rbac: + role: + extraRules: + - apiGroups: [""] + resources: ["test123"] + verbs: ["test123"] + plugins: + test: + rbac: + role: + extraRules: + - apiGroups: [""] + resources: ["test"] + verbs: ["test"] + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: rules + count: 7 + - contains: + path: rules + count: 1 + content: + apiGroups: [""] + resources: ["test123"] + verbs: ["test123"] + - contains: + path: rules + count: 1 + content: + apiGroups: [""] + resources: ["test"] + verbs: ["test"] + + - it: check generic sync + set: + experimental: + genericSync: + role: + extraRules: + - apiGroups: [""] + resources: ["test"] + verbs: ["test"] + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: rules + count: 6 + - contains: + path: rules + count: 1 + content: + apiGroups: [""] + resources: ["test"] + verbs: ["test"] + + - it: check extra rules + set: + rbac: + role: + extraRules: + - apiGroups: [""] + resources: ["test"] + verbs: ["test"] + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: rules + count: 6 + - contains: + path: rules + count: 1 + content: + apiGroups: [""] + resources: ["test"] + verbs: ["test"] + + - it: check defaults + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - equal: + path: kind + value: Role + - equal: + path: metadata.name + value: vc-my-release + - equal: + path: metadata.namespace + value: my-namespace + + - it: multi-namespace mode + set: + experimental: + multiNamespaceMode: + enabled: true + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - equal: + path: kind + value: ClusterRole + - equal: + path: metadata.name + value: vc-mn-my-release-v-my-namespace + + - it: metrics proxy + set: + integrations: + metricsServer: + enabled: true + pods: true + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - equal: + path: kind + value: Role + - contains: + path: rules + content: + apiGroups: ["metrics.k8s.io"] + resources: ["pods"] + verbs: ["get", "list"] + + - it: external secret test + set: + integrations: + externalSecrets: + enabled: true + sync: + externalSecrets: + enabled: true + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - equal: + path: kind + value: Role + - contains: + path: rules + content: + apiGroups: ["external-secrets.io"] + resources: ["externalsecrets"] + verbs: + ["create", "delete", "patch", "update", "get", "list", "watch"] + - it: external secret test store sync + set: + integrations: + externalSecrets: + enabled: true + sync: + externalSecrets: + enabled: true + stores: + enabled: true + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - equal: + path: kind + value: Role + - contains: + path: rules + content: + apiGroups: ["external-secrets.io"] + resources: ["secretstores"] + verbs: + ["create", "delete", "patch", "update", "get", "list", "watch"] + - it: kubeVirt test + set: + integrations: + kubeVirt: + enabled: true + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - equal: + path: kind + value: Role + - contains: + path: rules + content: + apiGroups: ["kubevirt.io"] + resources: + [ + "virtualmachines", + "virtualmachines/status", + "virtualmachineinstances", + "virtualmachineinstances/status", + "virtualmachineinstancemigrations", + "virtualmachineinstancemigrations/status", + ] + verbs: + ["create", "delete", "patch", "update", "get", "list", "watch"] + - contains: + path: rules + content: + apiGroups: ["cdi.kubevirt.io"] + resources: ["datavolumes", "datavolumes/status"] + verbs: + ["create", "delete", "patch", "update", "get", "list", "watch"] + - contains: + path: rules + content: + apiGroups: ["clone.kubevirt.io"] + resources: ["virtualmachineclones", "virtualmachineclones/status"] + verbs: + ["create", "delete", "patch", "update", "get", "list", "watch"] + - contains: + path: rules + content: + apiGroups: ["pool.kubevirt.io"] + resources: ["virtualmachinepools", "virtualmachinepools/status"] + verbs: + ["create", "delete", "patch", "update", "get", "list", "watch"] + + - it: crd sync + set: + sync: + toHost: + customResources: + test.my-group: + enabled: false + test.my-group-2: + enabled: true + tests.my-group-3.com: + enabled: true + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - equal: + path: kind + value: Role + - lengthEqual: + path: rules + count: 7 + - contains: + path: rules + content: + apiGroups: ["my-group-2"] + resources: ["test"] + verbs: + ["create", "delete", "patch", "update", "get", "list", "watch"] + - contains: + path: rules + content: + apiGroups: ["my-group-3.com"] + resources: ["tests"] + verbs: + ["create", "delete", "patch", "update", "get", "list", "watch"] + + - it: patches + set: + sync: + toHost: + customResources: + test.my-group-2: + enabled: true + patches: + - path: "test" + expression: "test" + release: + name: my-release + namespace: my-namespace + asserts: + - notFailedTemplate: {} + + - it: patches 2 + set: + sync: + toHost: + customResources: + test.my-group-2: + enabled: true + patches: + - path: "test" + reference: + apiVersion: "v1" + kind: "Secret" + release: + name: my-release + namespace: my-namespace + asserts: + - notFailedTemplate: {} diff --git a/backing-services/vcluster/tests/rolebinding_test.yaml b/backing-services/vcluster/tests/rolebinding_test.yaml new file mode 100644 index 0000000..6695445 --- /dev/null +++ b/backing-services/vcluster/tests/rolebinding_test.yaml @@ -0,0 +1,59 @@ +suite: RoleBinding +templates: + - rolebinding.yaml + +tests: + - it: check defaults + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - equal: + path: kind + value: RoleBinding + - equal: + path: metadata.name + value: vc-my-release + - equal: + path: metadata.namespace + value: my-namespace + - equal: + path: subjects[0].name + value: vc-my-release + - equal: + path: roleRef.kind + value: Role + - equal: + path: roleRef.name + value: vc-my-release + + - it: multi-namespace mode + set: + experimental: + multiNamespaceMode: + enabled: true + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - equal: + path: kind + value: ClusterRoleBinding + - equal: + path: metadata.name + value: vc-mn-my-release-v-my-namespace + - notExists: + path: metadata.namespace + - equal: + path: subjects[0].name + value: vc-my-release + - equal: + path: roleRef.kind + value: ClusterRole + - equal: + path: roleRef.name + value: vc-mn-my-release-v-my-namespace diff --git a/backing-services/vcluster/tests/service-monitor_test.yaml b/backing-services/vcluster/tests/service-monitor_test.yaml new file mode 100644 index 0000000..c05c0e0 --- /dev/null +++ b/backing-services/vcluster/tests/service-monitor_test.yaml @@ -0,0 +1,33 @@ +suite: ServiceMonitor +templates: + - service-monitor.yaml + +tests: + - it: should not create service monitor by default + asserts: + - hasDocuments: + count: 0 + + - it: check defaults + release: + name: my-release + namespace: my-namespace + set: + controlPlane: + serviceMonitor: + enabled: true + asserts: + - hasDocuments: + count: 1 + - equal: + path: metadata.name + value: vc-my-release + - equal: + path: metadata.namespace + value: my-namespace + - equal: + path: spec.selector.matchLabels.app + value: vcluster + - lengthEqual: + path: spec.endpoints + count: 1 diff --git a/backing-services/vcluster/tests/service_test.yaml b/backing-services/vcluster/tests/service_test.yaml new file mode 100644 index 0000000..cbbc774 --- /dev/null +++ b/backing-services/vcluster/tests/service_test.yaml @@ -0,0 +1,118 @@ +suite: ControlPlane Service +templates: + - service.yaml + +tests: + - it: should not create service + set: + controlPlane: + service: + enabled: false + asserts: + - hasDocuments: + count: 0 + + - it: should not create kubelet port + set: + networking: + advanced: + proxyKubelets: + byHostname: false + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: spec.ports + count: 1 + - contains: + path: spec.ports + content: + name: https + nodePort: 0 + targetPort: 8443 + protocol: TCP + port: 443 + + - it: should not create kubelet port 2 + set: + controlPlane: + service: + spec: + type: LoadBalancer + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: spec.ports + count: 1 + - contains: + path: spec.ports + content: + name: https + nodePort: 0 + targetPort: 8443 + protocol: TCP + port: 443 + + - it: should create kubelet port + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: spec.ports + count: 2 + - contains: + path: spec.ports + content: + name: kubelet + nodePort: 0 + targetPort: 8443 + protocol: TCP + port: 10250 + + - it: service defaults + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - equal: + path: metadata.name + value: my-release + - equal: + path: metadata.namespace + value: my-namespace + - equal: + path: spec.type + value: ClusterIP + - equal: + path: spec.selector.app + value: vcluster + - lengthEqual: + path: spec.ports + count: 2 + + - it: isolated control plane + release: + name: my-release + namespace: my-namespace + set: + experimental: + isolatedControlPlane: + headless: true + asserts: + - hasDocuments: + count: 1 + - equal: + path: spec.type + value: ClusterIP + - lengthEqual: + path: spec.ports + count: 2 + - notExists: + path: spec.ports[0].targetPort + - notExists: + path: spec.ports[1].targetPort + - notExists: + path: spec.selector diff --git a/backing-services/vcluster/tests/serviceaccount_test.yaml b/backing-services/vcluster/tests/serviceaccount_test.yaml new file mode 100644 index 0000000..4441181 --- /dev/null +++ b/backing-services/vcluster/tests/serviceaccount_test.yaml @@ -0,0 +1,61 @@ +suite: ControlPlane ServiceAccount +templates: + - serviceaccount.yaml + +tests: + - it: should not create service account + set: + controlPlane: + advanced: + serviceAccount: + enabled: false + asserts: + - hasDocuments: + count: 0 + + - it: should create service account + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - equal: + path: metadata.name + value: vc-my-release + - equal: + path: metadata.namespace + value: my-namespace + + - it: should create service account with name + set: + controlPlane: + advanced: + serviceAccount: + name: test + asserts: + - hasDocuments: + count: 1 + - equal: + path: metadata.name + value: test + + - it: should create image pull secrets + set: + controlPlane: + advanced: + serviceAccount: + imagePullSecrets: + - name: test1 + workloadServiceAccount: + imagePullSecrets: + - name: test2 + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: imagePullSecrets + count: 1 + - equal: + path: imagePullSecrets[0].name + value: test1 diff --git a/backing-services/vcluster/tests/statefulset_test.yaml b/backing-services/vcluster/tests/statefulset_test.yaml new file mode 100644 index 0000000..091e68d --- /dev/null +++ b/backing-services/vcluster/tests/statefulset_test.yaml @@ -0,0 +1,897 @@ +suite: ControlPlane StatefulSet +templates: + - statefulset.yaml + +tests: + - it: should not create control-plane + set: + experimental: + isolatedControlPlane: + headless: true + asserts: + - hasDocuments: + count: 0 + + - it: image name + set: + controlPlane: + statefulSet: + image: + registry: "custom-registry.com" + asserts: + - equal: + path: spec.template.spec.containers[0].image + value: custom-registry.com/loft-sh/vcluster-pro:0.0.1 + + - it: defaultImageRegistry + set: + controlPlane: + advanced: + defaultImageRegistry: docker.io + asserts: + - equal: + path: spec.template.spec.containers[0].image + value: docker.io/loft-sh/vcluster-pro:0.0.1 + + - it: custom tag + set: + controlPlane: + statefulSet: + image: + repository: my-repo + tag: "custom-tag" + asserts: + - equal: + path: spec.template.spec.containers[0].image + value: ghcr.io/my-repo:custom-tag + + - it: custom init container + set: + controlPlane: + distro: + k3s: + enabled: true + image: + registry: "ghcr.io" + repository: "test" + tag: "123" + asserts: + - equal: + path: spec.template.spec.initContainers[0].image + value: ghcr.io/test:123 + + - it: custom init container + set: + controlPlane: + distro: + k0s: + enabled: true + image: + registry: "" + repository: "k0s" + tag: "123" + asserts: + - equal: + path: spec.template.spec.initContainers[0].image + value: k0s:123 + + - it: disables serviceLinks for sts etcd pod + set: + controlPlane: + statefulSet: + enableServiceLinks: false + asserts: + - equal: + path: spec.template.spec.enableServiceLinks + value: false + + - it: custom init container + set: + controlPlane: + distro: + k8s: + enabled: true + controllerManager: + image: + registry: "" + repository: "k8s-controller" + tag: "123" + apiServer: + image: + registry: "" + repository: "k8s-api" + tag: "456" + asserts: + - equal: + path: spec.template.spec.initContainers[1].image + value: k8s-controller:123 + - equal: + path: spec.template.spec.initContainers[2].image + value: k8s-api:456 + + - it: custom init container + set: + controlPlane: + distro: + k8s: + enabled: true + controllerManager: + image: + repository: "k8s-controller" + tag: "123" + apiServer: + image: + repository: "k8s-api" + tag: "456" + advanced: + defaultImageRegistry: "bbb.com" + asserts: + - equal: + path: spec.template.spec.initContainers[1].image + value: bbb.com/k8s-controller:123 + - equal: + path: spec.template.spec.initContainers[2].image + value: bbb.com/k8s-api:456 + + - it: name & defaults + release: + name: my-release + namespace: my-namespace + capabilities: + majorVersion: 1 + minorVersion: 29 + asserts: + - hasDocuments: + count: 1 + - equal: + path: kind + value: StatefulSet + - lengthEqual: + path: spec.template.spec.containers + count: 1 + - equal: + path: spec.template.spec.containers[0].image + value: ghcr.io/loft-sh/vcluster-pro:0.0.1 + - contains: + path: spec.template.spec.containers[0].env + content: + name: VCLUSTER_NAME + value: my-release + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: data + mountPath: /data + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: binaries + mountPath: /binaries + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: certs + mountPath: /pki + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: helm-cache + mountPath: /.cache/helm + - equal: + path: metadata.name + value: my-release + - equal: + path: metadata.namespace + value: my-namespace + - equal: + path: spec.podManagementPolicy + value: Parallel + - equal: + path: spec.persistentVolumeClaimRetentionPolicy.whenDeleted + value: Retain + - equal: + path: spec.replicas + value: 1 + - equal: + path: spec.template.metadata.labels.app + value: vcluster + - equal: + path: spec.template.spec.terminationGracePeriodSeconds + value: 10 + - equal: + path: spec.volumeClaimTemplates[0].spec.accessModes[0] + value: ReadWriteOnce + - equal: + path: spec.volumeClaimTemplates[0].spec.resources.requests.storage + value: 5Gi + + - it: fail when both backing stores are enabled + set: + controlPlane: + backingStore: + etcd: + embedded: + enabled: true + deploy: + enabled: true + asserts: + - failedTemplate: + errorMessage: "you can only enable one backingStore at the same time" + + - it: not persistent when external etcd is enabled + set: + controlPlane: + backingStore: + etcd: + deploy: + enabled: true + asserts: + - equal: + path: kind + value: Deployment + - notExists: + path: spec.volumeClaimTemplates + + - it: not persistent when k8s and external database + set: + controlPlane: + distro: + k8s: + enabled: true + backingStore: + database: + external: + enabled: true + asserts: + - equal: + path: kind + value: Deployment + - notExists: + path: spec.volumeClaimTemplates + + - it: persistent when embedded database + set: + controlPlane: + distro: + k8s: + enabled: true + backingStore: + database: + embedded: + enabled: true + asserts: + - equal: + path: kind + value: StatefulSet + - lengthEqual: + path: spec.volumeClaimTemplates + count: 1 + + - it: persistent when k8s and embedded etcd + set: + controlPlane: + backingStore: + etcd: + embedded: + enabled: true + distro: + k8s: + enabled: true + asserts: + - equal: + path: kind + value: StatefulSet + - lengthEqual: + path: spec.volumeClaimTemplates + count: 1 + + - it: persistent when embedded database + asserts: + - equal: + path: kind + value: StatefulSet + - lengthEqual: + path: spec.volumeClaimTemplates + count: 1 + + - it: plugin 1 + set: + plugins: + test: + image: test + plugin: + test123: + version: v2 + image: test + asserts: + - lengthEqual: + path: spec.template.spec.volumes + count: 7 + - lengthEqual: + path: spec.template.spec.initContainers + count: 5 + + - it: plugin volumes 2 + set: + controlPlane: + distro: + k0s: + enabled: true + plugin: + test: + version: v2 + image: test + asserts: + - equal: + path: kind + value: StatefulSet + - lengthEqual: + path: spec.template.spec.volumes + count: 8 + - lengthEqual: + path: spec.template.spec.initContainers + count: 2 + + - it: plugin volumes 3 + set: + plugin: + test: + image: test + asserts: + - lengthEqual: + path: spec.template.spec.volumes + count: 6 + - lengthEqual: + path: spec.template.spec.initContainers + count: 3 + + - it: add volumes + set: + controlPlane: + distro: + k3s: + enabled: true + statefulSet: + persistence: + addVolumes: + - name: myVolume + asserts: + - contains: + path: spec.template.spec.volumes + content: + name: myVolume + - lengthEqual: + path: spec.template.spec.volumes + count: 8 + + - it: enable k8s + set: + controlPlane: + distro: + k8s: + enabled: true + asserts: + - equal: + path: kind + value: StatefulSet + - lengthEqual: + path: spec.volumeClaimTemplates + count: 1 + + - it: enable k8s with deploy etcd + set: + controlPlane: + distro: + k8s: + enabled: true + backingStore: + etcd: + deploy: + enabled: true + asserts: + - equal: + path: kind + value: Deployment + - notExists: + path: spec.volumeClaimTemplates + - contains: + path: spec.template.spec.volumes + content: + name: data + emptyDir: {} + + - it: enable k8s + release: + name: my-release + namespace: my-namespace + set: + controlPlane: + distro: + k8s: + enabled: true + statefulSet: + persistence: + volumeClaim: + enabled: false + volumeClaimTemplates: + - metadata: + name: data + spec: + resources: + requests: + storage: 5Gi + asserts: + - equal: + path: kind + value: StatefulSet + - equal: + path: spec.serviceName + value: my-release-headless + - contains: + path: spec.volumeClaimTemplates + content: + metadata: + name: data + spec: + resources: + requests: + storage: 5Gi + + - it: enable k8s + set: + controlPlane: + distro: + k8s: + enabled: true + release: + name: my-release + namespace: my-namespace + asserts: + - equal: + path: kind + value: StatefulSet + - equal: + path: spec.serviceName + value: my-release-headless + - lengthEqual: + path: spec.volumeClaimTemplates + count: 1 + + - it: enable k8s with deploy etcd + set: + controlPlane: + distro: + k8s: + enabled: true + backingStore: + etcd: + deploy: + enabled: true + asserts: + - equal: + path: kind + value: Deployment + - notExists: + path: spec.volumeClaimTemplates + - contains: + path: spec.template.spec.volumes + content: + name: data + emptyDir: {} + + - it: enable k0s + set: + controlPlane: + backingStore: + etcd: + deploy: + enabled: true + distro: + k0s: + enabled: true + asserts: + - equal: + path: kind + value: Deployment + - notExists: + path: spec.volumeClaimTemplates + - contains: + path: spec.template.spec.volumes + content: + name: data + emptyDir: {} + + - it: append distro env + set: + controlPlane: + distro: + k3s: + enabled: true + env: + - name: KEY + value: VALUE + asserts: + - equal: + path: kind + value: StatefulSet + - contains: + path: spec.template.spec.containers[0].env + content: + name: KEY + value: VALUE + + - it: should correctly set labels on the statefulset + set: + controlPlane: + statefulSet: + labels: + my-label: my-value + + asserts: + - equal: + path: kind + value: StatefulSet + - equal: + path: metadata.labels["my-label"] + value: "my-value" + + - it: binariesVolume - should set to emptyDir by default + asserts: + - contains: + path: spec.template.spec.volumes + content: + name: binaries + emptyDir: {} + + - it: binariesVolume - should set the specified volume type correctly + set: + controlPlane: + statefulSet: + persistence: + binariesVolume: + - name: binaries + persistentVolumeClaim: + claimName: my-pvc + asserts: + - contains: + path: spec.template.spec.volumes + content: + name: binaries + persistentVolumeClaim: + claimName: my-pvc + + - it: dataVolume - should set the specified data volume type correctly + set: + controlPlane: + statefulSet: + persistence: + dataVolume: + - name: data + persistentVolumeClaim: + claimName: my-custom-pvc + asserts: + - contains: + path: spec.template.spec.volumes + content: + name: data + persistentVolumeClaim: + claimName: my-custom-pvc + + - it: k8s version not set, default tag images used for apiServer and controllerManager + chart: + version: "test-" + set: + controlPlane: + distro: + k8s: + enabled: true + asserts: + - equal: + path: spec.template.spec.initContainers[1].image + value: registry.k8s.io/kube-controller-manager:v1.31.1 + - equal: + path: spec.template.spec.initContainers[2].image + value: registry.k8s.io/kube-apiserver:v1.31.1 + + - it: k8s capabilities set + chart: + version: "test-v1.29.3" + asserts: + - equal: + path: spec.template.spec.initContainers[1].image + value: registry.k8s.io/kube-controller-manager:v1.29.3 + - equal: + path: spec.template.spec.initContainers[2].image + value: registry.k8s.io/kube-apiserver:v1.29.3 + + - it: k8s capabilities orbstack + chart: + version: "test-v1.29.3+orb1" + asserts: + - equal: + path: spec.template.spec.initContainers[1].image + value: registry.k8s.io/kube-controller-manager:v1.29.3 + - equal: + path: spec.template.spec.initContainers[2].image + value: registry.k8s.io/kube-apiserver:v1.29.3 + + - it: k8s capabilities invalid + chart: + version: "test-invalid" + asserts: + - equal: + path: spec.template.spec.initContainers[1].image + value: registry.k8s.io/kube-controller-manager:v1.31.1 + + - it: k8s capabilities incomplete + chart: + version: "test-v1.22" + asserts: + - equal: + path: spec.template.spec.initContainers[1].image + value: registry.k8s.io/kube-controller-manager:v1.31.1 + + - it: k8s capabilities incomplete 2 + chart: + version: "test-1.22.11" + asserts: + - equal: + path: spec.template.spec.initContainers[1].image + value: registry.k8s.io/kube-controller-manager:v1.31.1 + + - it: k8s capabilities incomplete 2 + chart: + version: "test-v1.22.33" + asserts: + - equal: + path: spec.template.spec.initContainers[1].image + value: registry.k8s.io/kube-controller-manager:v1.22.33 + + - it: k8s version sets image tag for apiServer and controllerManager + set: + controlPlane: + distro: + k8s: + enabled: true + version: v1.35.999 + asserts: + - equal: + path: spec.template.spec.initContainers[1].image + value: registry.k8s.io/kube-controller-manager:v1.35.999 + - equal: + path: spec.template.spec.initContainers[2].image + value: registry.k8s.io/kube-apiserver:v1.35.999 + + - it: k8s version set but overridden by image tag for apiServer and controllerManager + set: + controlPlane: + distro: + k8s: + enabled: true + version: v1.30.999 + apiServer: + image: + tag: v99912 + controllerManager: + image: + tag: v23123 + + asserts: + - equal: + path: spec.template.spec.initContainers[1].image + value: registry.k8s.io/kube-controller-manager:v23123 + - equal: + path: spec.template.spec.initContainers[2].image + value: registry.k8s.io/kube-apiserver:v99912 + + - it: k8s not version set but image tags for apiServer and controllerManager set + set: + controlPlane: + distro: + k8s: + enabled: true + apiServer: + image: + tag: v99914 + controllerManager: + image: + tag: v23127 + + asserts: + - equal: + path: spec.template.spec.initContainers[1].image + value: registry.k8s.io/kube-controller-manager:v23127 + - equal: + path: spec.template.spec.initContainers[2].image + value: registry.k8s.io/kube-apiserver:v99914 + + - it: k8s version not set, default tag images used for apiServer and controllerManager (virtual scheduler enabled) + chart: + version: "test-" + set: + controlPlane: + distro: + k8s: + enabled: true + advanced: + virtualScheduler: + enabled: true + asserts: + - equal: + path: spec.template.spec.initContainers[1].image + value: registry.k8s.io/kube-controller-manager:v1.31.1 + - equal: + path: spec.template.spec.initContainers[2].image + value: registry.k8s.io/kube-scheduler:v1.31.1 + - equal: + path: spec.template.spec.initContainers[3].image + value: registry.k8s.io/kube-apiserver:v1.31.1 + + - it: k8s version sets image tag for apiServer and controllerManager (virtual scheduler enabled) + set: + controlPlane: + distro: + k8s: + enabled: true + version: v1.35.999 + advanced: + virtualScheduler: + enabled: true + asserts: + - equal: + path: spec.template.spec.initContainers[1].image + value: registry.k8s.io/kube-controller-manager:v1.35.999 + - equal: + path: spec.template.spec.initContainers[2].image + value: registry.k8s.io/kube-scheduler:v1.35.999 + - equal: + path: spec.template.spec.initContainers[3].image + value: registry.k8s.io/kube-apiserver:v1.35.999 + + - it: k8s version set but overridden by image tag for apiServer and controllerManager (virtual scheduler enabled) + set: + controlPlane: + distro: + k8s: + enabled: true + version: v1.30.999 + apiServer: + image: + tag: v99912 + controllerManager: + image: + tag: v23123 + scheduler: + image: + tag: v123654 + advanced: + virtualScheduler: + enabled: true + + asserts: + - equal: + path: spec.template.spec.initContainers[1].image + value: registry.k8s.io/kube-controller-manager:v23123 + - equal: + path: spec.template.spec.initContainers[2].image + value: registry.k8s.io/kube-scheduler:v123654 + - equal: + path: spec.template.spec.initContainers[3].image + value: registry.k8s.io/kube-apiserver:v99912 + + - it: k8s not version set but image tags for apiServer and controllerManager set (virtual scheduler enabled) + set: + controlPlane: + distro: + k8s: + enabled: true + apiServer: + image: + tag: v99914 + controllerManager: + image: + tag: v23127 + scheduler: + image: + tag: v123656 + + advanced: + virtualScheduler: + enabled: true + + asserts: + - equal: + path: spec.template.spec.initContainers[1].image + value: registry.k8s.io/kube-controller-manager:v23127 + - equal: + path: spec.template.spec.initContainers[2].image + value: registry.k8s.io/kube-scheduler:v123656 + - equal: + path: spec.template.spec.initContainers[3].image + value: registry.k8s.io/kube-apiserver:v99914 + + - it: custom dnsPolicy + set: + controlPlane: + statefulSet: + dnsPolicy: "ClusterFirst" + asserts: + - equal: + path: spec.template.spec.dnsPolicy + value: "ClusterFirst" + + - it: custom dnsConfig + set: + controlPlane: + statefulSet: + dnsConfig: + nameservers: + - 192.0.2.1 + searches: + - ns1.svc.cluster-domain.example + options: + - name: ndots + value: "2" + asserts: + - equal: + path: spec.template.spec.dnsConfig.nameservers[0] + value: "192.0.2.1" + - equal: + path: spec.template.spec.dnsConfig.searches[0] + value: "ns1.svc.cluster-domain.example" + - equal: + path: spec.template.spec.dnsConfig.options[0].name + value: "ndots" + - equal: + path: spec.template.spec.dnsConfig.options[0].value + value: "2" + + - it: must use StatefulSet for embedded etcd + set: + controlPlane: + backingStore: + etcd: + embedded: + enabled: true + + asserts: + - equal: + path: kind + value: StatefulSet + + - it: must use StatefulSet for embedded etcd without persistence + set: + controlPlane: + backingStore: + etcd: + embedded: + enabled: true + statefulSet: + persistence: + volumeClaim: + enabled: false + binariesVolume: + - name: binaries + emptyDir: + medium: Memory + + asserts: + - equal: + path: kind + value: StatefulSet + + - it: sync custom resources + set: + sync: + toHost: + customResources: + test.cert-manager.io: + enabled: true + patches: + - path: spec.dnsNames[*] + expression: "value.startsWith('www.') ? value.slice(4) : value" + reverseExpression: '"www."+value' + asserts: + - equal: + path: kind + value: StatefulSet diff --git a/backing-services/vcluster/tests/workload-serviceaccount_test.yaml b/backing-services/vcluster/tests/workload-serviceaccount_test.yaml new file mode 100644 index 0000000..8b2ced4 --- /dev/null +++ b/backing-services/vcluster/tests/workload-serviceaccount_test.yaml @@ -0,0 +1,64 @@ +suite: Workload ServiceAccount +templates: + - workload-serviceaccount.yaml + +tests: + - it: should not create service account + set: + controlPlane: + advanced: + workloadServiceAccount: + enabled: false + asserts: + - hasDocuments: + count: 0 + + - it: should create service account + release: + name: my-release + namespace: my-namespace + asserts: + - hasDocuments: + count: 1 + - equal: + path: metadata.name + value: vc-workload-my-release + - equal: + path: metadata.namespace + value: my-namespace + + - it: should create service account with name + set: + controlPlane: + advanced: + workloadServiceAccount: + name: test + asserts: + - hasDocuments: + count: 1 + - equal: + path: metadata.name + value: test + + - it: should create image pull secrets + set: + controlPlane: + advanced: + serviceAccount: + imagePullSecrets: + - name: test1 + workloadServiceAccount: + imagePullSecrets: + - name: test2 + asserts: + - hasDocuments: + count: 1 + - lengthEqual: + path: imagePullSecrets + count: 2 + - equal: + path: imagePullSecrets[0].name + value: test1 + - equal: + path: imagePullSecrets[1].name + value: test2 diff --git a/backing-services/vcluster/values.schema.json b/backing-services/vcluster/values.schema.json new file mode 100644 index 0000000..1cf65b1 --- /dev/null +++ b/backing-services/vcluster/values.schema.json @@ -0,0 +1,3661 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://vcluster.com/schemas/config", + "$defs": { + "APIService": { + "properties": { + "service": { + "$ref": "#/$defs/APIServiceService", + "description": "Service is a reference to the service for the API server." + } + }, + "additionalProperties": false, + "type": "object", + "description": "APIService holds configuration related to the api server" + }, + "APIServiceService": { + "properties": { + "name": { + "type": "string", + "description": "Name is the name of the host service of the apiservice." + }, + "namespace": { + "type": "string", + "description": "Namespace is the name of the host service of the apiservice." + }, + "port": { + "type": "integer", + "description": "Port is the target port on the host service to connect to." + } + }, + "additionalProperties": false, + "type": "object", + "description": "APIServiceService holds the service name and namespace of the host apiservice." + }, + "BackingStore": { + "properties": { + "etcd": { + "$ref": "#/$defs/Etcd", + "description": "Etcd defines that etcd should be used as the backend for the virtual cluster" + }, + "database": { + "$ref": "#/$defs/Database", + "description": "Database defines that a database backend should be used as the backend for the virtual cluster. This uses a project called kine under the hood which is a shim for bridging Kubernetes and relational databases." + } + }, + "additionalProperties": false, + "type": "object" + }, + "CentralAdmission": { + "properties": { + "validatingWebhooks": { + "items": { + "$ref": "#/$defs/ValidatingWebhookConfiguration" + }, + "type": "array", + "description": "ValidatingWebhooks are validating webhooks that should be enforced in the virtual cluster" + }, + "mutatingWebhooks": { + "items": { + "$ref": "#/$defs/MutatingWebhookConfiguration" + }, + "type": "array", + "description": "MutatingWebhooks are mutating webhooks that should be enforced in the virtual cluster" + } + }, + "additionalProperties": false, + "type": "object" + }, + "ClusterStoresSyncConfig": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled defines if this option should be enabled." + }, + "selector": { + "$ref": "#/$defs/LabelSelector", + "description": "Selector defines what cluster stores should be synced" + } + }, + "additionalProperties": false, + "type": "object" + }, + "ControlPlane": { + "properties": { + "distro": { + "$ref": "#/$defs/Distro", + "description": "Distro holds virtual cluster related distro options. A distro cannot be changed after vCluster is deployed." + }, + "backingStore": { + "$ref": "#/$defs/BackingStore", + "description": "BackingStore defines which backing store to use for virtual cluster. If not defined will use embedded database as a default backing store." + }, + "coredns": { + "$ref": "#/$defs/CoreDNS", + "description": "CoreDNS defines everything related to the coredns that is deployed and used within the vCluster." + }, + "proxy": { + "$ref": "#/$defs/ControlPlaneProxy", + "description": "Proxy defines options for the virtual cluster control plane proxy that is used to do authentication and intercept requests." + }, + "hostPathMapper": { + "$ref": "#/$defs/HostPathMapper", + "description": "HostPathMapper defines if vCluster should rewrite host paths.", + "pro": true + }, + "ingress": { + "$ref": "#/$defs/ControlPlaneIngress", + "description": "Ingress defines options for vCluster ingress deployed by Helm." + }, + "service": { + "$ref": "#/$defs/ControlPlaneService", + "description": "Service defines options for vCluster service deployed by Helm." + }, + "statefulSet": { + "$ref": "#/$defs/ControlPlaneStatefulSet", + "description": "StatefulSet defines options for vCluster statefulSet deployed by Helm." + }, + "serviceMonitor": { + "$ref": "#/$defs/ServiceMonitor", + "description": "ServiceMonitor can be used to automatically create a service monitor for vCluster deployment itself." + }, + "advanced": { + "$ref": "#/$defs/ControlPlaneAdvanced", + "description": "Advanced holds additional configuration for the vCluster control plane." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ControlPlaneAdvanced": { + "properties": { + "defaultImageRegistry": { + "type": "string", + "description": "DefaultImageRegistry will be used as a prefix for all internal images deployed by vCluster or Helm. This makes it easy to\nupload all required vCluster images to a single private repository and set this value. Workload images are not affected by this." + }, + "virtualScheduler": { + "$ref": "#/$defs/EnableSwitch", + "description": "VirtualScheduler defines if a scheduler should be used within the virtual cluster or the scheduling decision for workloads will be made by the host cluster." + }, + "serviceAccount": { + "$ref": "#/$defs/ControlPlaneServiceAccount", + "description": "ServiceAccount specifies options for the vCluster control plane service account." + }, + "workloadServiceAccount": { + "$ref": "#/$defs/ControlPlaneWorkloadServiceAccount", + "description": "WorkloadServiceAccount specifies options for the service account that will be used for the workloads that run within the virtual cluster." + }, + "headlessService": { + "$ref": "#/$defs/ControlPlaneHeadlessService", + "description": "HeadlessService specifies options for the headless service used for the vCluster StatefulSet." + }, + "globalMetadata": { + "$ref": "#/$defs/ControlPlaneGlobalMetadata", + "description": "GlobalMetadata is metadata that will be added to all resources deployed by Helm." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ControlPlaneGlobalMetadata": { + "properties": { + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Annotations are extra annotations for this resource." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ControlPlaneHeadlessService": { + "properties": { + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Annotations are extra annotations for this resource." + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Labels are extra labels for this resource." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ControlPlaneHighAvailability": { + "properties": { + "replicas": { + "type": "integer", + "description": "Replicas is the amount of replicas to use for the statefulSet." + }, + "leaseDuration": { + "type": "integer", + "description": "LeaseDuration is the time to lease for the leader." + }, + "renewDeadline": { + "type": "integer", + "description": "RenewDeadline is the deadline to renew a lease for the leader." + }, + "retryPeriod": { + "type": "integer", + "description": "RetryPeriod is the time until a replica will retry to get a lease." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ControlPlaneIngress": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled defines if the control plane ingress should be enabled" + }, + "host": { + "type": "string", + "description": "Host is the host where vCluster will be reachable" + }, + "pathType": { + "type": "string", + "description": "PathType is the path type of the ingress" + }, + "spec": { + "type": "object", + "description": "Spec allows you to configure extra ingress options." + }, + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Annotations are extra annotations for this resource." + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Labels are extra labels for this resource." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ControlPlanePersistence": { + "properties": { + "volumeClaim": { + "$ref": "#/$defs/VolumeClaim", + "description": "VolumeClaim can be used to configure the persistent volume claim." + }, + "volumeClaimTemplates": { + "items": { + "type": "object" + }, + "type": "array", + "description": "VolumeClaimTemplates defines the volumeClaimTemplates for the statefulSet" + }, + "dataVolume": { + "items": { + "type": "object" + }, + "type": "array", + "description": "Allows you to override the dataVolume. Only works correctly if volumeClaim.enabled=false." + }, + "binariesVolume": { + "items": { + "type": "object" + }, + "type": "array", + "description": "BinariesVolume defines a binaries volume that is used to retrieve\ndistro specific executables to be run by the syncer controller.\nThis volume doesn't need to be persistent." + }, + "addVolumes": { + "items": { + "type": "object" + }, + "type": "array", + "description": "AddVolumes defines extra volumes for the pod" + }, + "addVolumeMounts": { + "items": { + "$ref": "#/$defs/VolumeMount" + }, + "type": "array", + "description": "AddVolumeMounts defines extra volume mounts for the container" + } + }, + "additionalProperties": false, + "type": "object" + }, + "ControlPlaneProbes": { + "properties": { + "livenessProbe": { + "$ref": "#/$defs/EnableSwitch", + "description": "LivenessProbe specifies if the liveness probe for the container should be enabled" + }, + "readinessProbe": { + "$ref": "#/$defs/EnableSwitch", + "description": "ReadinessProbe specifies if the readiness probe for the container should be enabled" + }, + "startupProbe": { + "$ref": "#/$defs/EnableSwitch", + "description": "StartupProbe specifies if the startup probe for the container should be enabled" + } + }, + "additionalProperties": false, + "type": "object" + }, + "ControlPlaneProxy": { + "properties": { + "bindAddress": { + "type": "string", + "description": "BindAddress under which vCluster will expose the proxy." + }, + "port": { + "type": "integer", + "description": "Port under which vCluster will expose the proxy. Changing port is currently not supported." + }, + "extraSANs": { + "items": { + "type": "string" + }, + "type": "array", + "description": "ExtraSANs are extra hostnames to sign the vCluster proxy certificate for." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ControlPlaneScheduling": { + "properties": { + "nodeSelector": { + "type": "object", + "description": "NodeSelector is the node selector to apply to the pod." + }, + "affinity": { + "type": "object", + "description": "Affinity is the affinity to apply to the pod." + }, + "tolerations": { + "items": { + "type": "object" + }, + "type": "array", + "description": "Tolerations are the tolerations to apply to the pod." + }, + "priorityClassName": { + "type": "string", + "description": "PriorityClassName is the priority class name for the the pod." + }, + "podManagementPolicy": { + "type": "string", + "description": "PodManagementPolicy is the statefulSet pod management policy." + }, + "topologySpreadConstraints": { + "items": true, + "type": "array", + "description": "TopologySpreadConstraints are the topology spread constraints for the pod." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ControlPlaneSecurity": { + "properties": { + "podSecurityContext": { + "type": "object", + "description": "PodSecurityContext specifies security context options on the pod level." + }, + "containerSecurityContext": { + "type": "object", + "description": "ContainerSecurityContext specifies security context options on the container level." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ControlPlaneService": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled defines if the control plane service should be enabled" + }, + "spec": { + "type": "object", + "description": "Spec allows you to configure extra service options." + }, + "kubeletNodePort": { + "type": "integer", + "description": "KubeletNodePort is the node port where the fake kubelet is exposed. Defaults to 0." + }, + "httpsNodePort": { + "type": "integer", + "description": "HTTPSNodePort is the node port where https is exposed. Defaults to 0." + }, + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Annotations are extra annotations for this resource." + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Labels are extra labels for this resource." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ControlPlaneServiceAccount": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled specifies if the service account should get deployed." + }, + "name": { + "type": "string", + "description": "Name specifies what name to use for the service account." + }, + "imagePullSecrets": { + "items": { + "$ref": "#/$defs/ImagePullSecretName" + }, + "type": "array", + "description": "ImagePullSecrets defines extra image pull secrets for the service account." + }, + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Annotations are extra annotations for this resource." + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Labels are extra labels for this resource." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ControlPlaneStatefulSet": { + "properties": { + "highAvailability": { + "$ref": "#/$defs/ControlPlaneHighAvailability", + "description": "HighAvailability holds options related to high availability." + }, + "resources": { + "$ref": "#/$defs/Resources", + "description": "Resources are the resource requests and limits for the statefulSet container." + }, + "scheduling": { + "$ref": "#/$defs/ControlPlaneScheduling", + "description": "Scheduling holds options related to scheduling." + }, + "security": { + "$ref": "#/$defs/ControlPlaneSecurity", + "description": "Security defines pod or container security context." + }, + "probes": { + "$ref": "#/$defs/ControlPlaneProbes", + "description": "Probes enables or disables the main container probes." + }, + "persistence": { + "$ref": "#/$defs/ControlPlanePersistence", + "description": "Persistence defines options around persistence for the statefulSet." + }, + "enableServiceLinks": { + "type": "boolean", + "description": "EnableServiceLinks for the StatefulSet pod" + }, + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Annotations are extra annotations for this resource." + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Labels are extra labels for this resource." + }, + "pods": { + "$ref": "#/$defs/LabelsAndAnnotations", + "description": "Additional labels or annotations for the statefulSet pods." + }, + "image": { + "$ref": "#/$defs/StatefulSetImage", + "description": "Image is the image for the controlPlane statefulSet container" + }, + "imagePullPolicy": { + "type": "string", + "description": "ImagePullPolicy is the policy how to pull the image." + }, + "workingDir": { + "type": "string", + "description": "WorkingDir specifies in what folder the main process should get started." + }, + "command": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Command allows you to override the main command." + }, + "args": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Args allows you to override the main arguments." + }, + "env": { + "items": { + "type": "object" + }, + "type": "array", + "description": "Env are additional environment variables for the statefulSet container." + }, + "dnsPolicy": { + "type": "string", + "description": "Set DNS policy for the pod." + }, + "dnsConfig": { + "$ref": "#/$defs/PodDNSConfig", + "description": "Specifies the DNS parameters of a pod." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ControlPlaneWorkloadServiceAccount": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled specifies if the service account for the workloads should get deployed." + }, + "name": { + "type": "string", + "description": "Name specifies what name to use for the service account for the virtual cluster workloads." + }, + "imagePullSecrets": { + "items": { + "$ref": "#/$defs/ImagePullSecretName" + }, + "type": "array", + "description": "ImagePullSecrets defines extra image pull secrets for the workload service account." + }, + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Annotations are extra annotations for this resource." + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Labels are extra labels for this resource." + } + }, + "additionalProperties": false, + "type": "object" + }, + "CoreDNS": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled defines if coredns is enabled" + }, + "embedded": { + "type": "boolean", + "description": "Embedded defines if vCluster will start the embedded coredns service within the control-plane and not as a separate deployment. This is a PRO feature.", + "pro": true + }, + "service": { + "$ref": "#/$defs/CoreDNSService", + "description": "Service holds extra options for the coredns service deployed within the virtual cluster" + }, + "deployment": { + "$ref": "#/$defs/CoreDNSDeployment", + "description": "Deployment holds extra options for the coredns deployment deployed within the virtual cluster" + }, + "overwriteConfig": { + "type": "string", + "description": "OverwriteConfig can be used to overwrite the coredns config" + }, + "overwriteManifests": { + "type": "string", + "description": "OverwriteManifests can be used to overwrite the coredns manifests used to deploy coredns" + }, + "priorityClassName": { + "type": "string", + "description": "PriorityClassName specifies the priority class name for the CoreDNS pods." + } + }, + "additionalProperties": false, + "type": "object" + }, + "CoreDNSDeployment": { + "properties": { + "image": { + "type": "string", + "description": "Image is the coredns image to use" + }, + "replicas": { + "type": "integer", + "description": "Replicas is the amount of coredns pods to run." + }, + "nodeSelector": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "NodeSelector is the node selector to use for coredns." + }, + "affinity": { + "type": "object", + "description": "Affinity is the affinity to apply to the pod." + }, + "tolerations": { + "items": { + "type": "object" + }, + "type": "array", + "description": "Tolerations are the tolerations to apply to the pod." + }, + "resources": { + "$ref": "#/$defs/Resources", + "description": "Resources are the desired resources for coredns." + }, + "pods": { + "$ref": "#/$defs/LabelsAndAnnotations", + "description": "Pods is additional metadata for the coredns pods." + }, + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Annotations are extra annotations for this resource." + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Labels are extra labels for this resource." + }, + "topologySpreadConstraints": { + "items": true, + "type": "array", + "description": "TopologySpreadConstraints are the topology spread constraints for the CoreDNS pod." + } + }, + "additionalProperties": false, + "type": "object" + }, + "CoreDNSService": { + "properties": { + "spec": { + "type": "object", + "description": "Spec holds extra options for the coredns service" + }, + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Annotations are extra annotations for this resource." + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Labels are extra labels for this resource." + } + }, + "additionalProperties": false, + "type": "object" + }, + "Database": { + "properties": { + "embedded": { + "$ref": "#/$defs/DatabaseKine", + "description": "Embedded defines that an embedded database (sqlite) should be used as the backend for the virtual cluster" + }, + "external": { + "$ref": "#/$defs/ExternalDatabaseKine", + "description": "External defines that an external database should be used as the backend for the virtual cluster" + } + }, + "additionalProperties": false, + "type": "object" + }, + "DatabaseKine": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled defines if the database should be used." + }, + "dataSource": { + "type": "string", + "description": "DataSource is the kine dataSource to use for the database. This depends on the database format.\nThis is optional for the embedded database. Examples:\n* mysql: mysql://username:password@tcp(hostname:3306)/k3s\n* postgres: postgres://username:password@hostname:5432/k3s" + }, + "keyFile": { + "type": "string", + "description": "KeyFile is the key file to use for the database. This is optional." + }, + "certFile": { + "type": "string", + "description": "CertFile is the cert file to use for the database. This is optional." + }, + "caFile": { + "type": "string", + "description": "CaFile is the ca file to use for the database. This is optional." + } + }, + "additionalProperties": false, + "type": "object" + }, + "DenyRule": { + "properties": { + "name": { + "type": "string", + "description": "The name of the check." + }, + "namespaces": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Namespace describe a list of namespaces that will be affected by the check.\nAn empty list means that all namespaces will be affected.\nIn case of ClusterScoped rules, only the Namespace resource is affected." + }, + "rules": { + "items": { + "$ref": "#/$defs/RuleWithVerbs" + }, + "type": "array", + "description": "Rules describes on which verbs and on what resources/subresources the webhook is enforced.\nThe webhook is enforced if it matches any Rule.\nThe version of the request must match the rule version exactly. Equivalent matching is not supported." + }, + "excludedUsers": { + "items": { + "type": "string" + }, + "type": "array", + "description": "ExcludedUsers describe a list of users for which the checks will be skipped.\nImpersonation attempts on these users will still be subjected to the checks." + } + }, + "additionalProperties": false, + "type": "object" + }, + "Distro": { + "properties": { + "k8s": { + "$ref": "#/$defs/DistroK8s", + "description": "K8S holds K8s relevant configuration." + }, + "k3s": { + "$ref": "#/$defs/DistroK3s", + "description": "K3S holds K3s relevant configuration." + }, + "k0s": { + "$ref": "#/$defs/DistroK0s", + "description": "K0S holds k0s relevant configuration." + } + }, + "additionalProperties": false, + "type": "object" + }, + "DistroContainer": { + "properties": { + "image": { + "$ref": "#/$defs/Image", + "description": "Image is the distro image" + }, + "imagePullPolicy": { + "type": "string", + "description": "ImagePullPolicy is the pull policy for the distro image" + }, + "command": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Command is the command to start the distro binary. This will override the existing command." + }, + "extraArgs": { + "items": { + "type": "string" + }, + "type": "array", + "description": "ExtraArgs are additional arguments to pass to the distro binary." + } + }, + "additionalProperties": false, + "type": "object" + }, + "DistroContainerEnabled": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled signals this container should be enabled." + }, + "image": { + "$ref": "#/$defs/Image", + "description": "Image is the distro image" + }, + "imagePullPolicy": { + "type": "string", + "description": "ImagePullPolicy is the pull policy for the distro image" + }, + "command": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Command is the command to start the distro binary. This will override the existing command." + }, + "extraArgs": { + "items": { + "type": "string" + }, + "type": "array", + "description": "ExtraArgs are additional arguments to pass to the distro binary." + } + }, + "additionalProperties": false, + "type": "object" + }, + "DistroK0s": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled specifies if the k0s distro should be enabled. Only one distro can be enabled at the same time." + }, + "config": { + "type": "string", + "description": "Config allows you to override the k0s config passed to the k0s binary." + }, + "env": { + "items": { + "type": "object" + }, + "type": "array", + "description": "Env are extra environment variables to use for the main container and NOT the init container." + }, + "resources": { + "type": "object", + "description": "Resources for the distro init container" + }, + "securityContext": { + "type": "object", + "description": "Security options can be used for the distro init container" + }, + "image": { + "$ref": "#/$defs/Image", + "description": "Image is the distro image" + }, + "imagePullPolicy": { + "type": "string", + "description": "ImagePullPolicy is the pull policy for the distro image" + }, + "command": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Command is the command to start the distro binary. This will override the existing command." + }, + "extraArgs": { + "items": { + "type": "string" + }, + "type": "array", + "description": "ExtraArgs are additional arguments to pass to the distro binary." + } + }, + "additionalProperties": false, + "type": "object" + }, + "DistroK3s": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled specifies if the K3s distro should be enabled. Only one distro can be enabled at the same time." + }, + "token": { + "type": "string", + "description": "Token is the K3s token to use. If empty, vCluster will choose one." + }, + "env": { + "items": { + "type": "object" + }, + "type": "array", + "description": "Env are extra environment variables to use for the main container and NOT the init container." + }, + "resources": { + "type": "object", + "description": "Resources for the distro init container" + }, + "securityContext": { + "type": "object", + "description": "Security options can be used for the distro init container" + }, + "image": { + "$ref": "#/$defs/Image", + "description": "Image is the distro image" + }, + "imagePullPolicy": { + "type": "string", + "description": "ImagePullPolicy is the pull policy for the distro image" + }, + "command": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Command is the command to start the distro binary. This will override the existing command." + }, + "extraArgs": { + "items": { + "type": "string" + }, + "type": "array", + "description": "ExtraArgs are additional arguments to pass to the distro binary." + } + }, + "additionalProperties": false, + "type": "object" + }, + "DistroK8s": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled specifies if the K8s distro should be enabled. Only one distro can be enabled at the same time." + }, + "version": { + "type": "string", + "description": "Version specifies k8s components (scheduler, kube-controller-manager \u0026 apiserver) version.\nIt is a shortcut for controlPlane.distro.k8s.apiServer.image.tag,\ncontrolPlane.distro.k8s.controllerManager.image.tag and\ncontrolPlane.distro.k8s.scheduler.image.tag\nIf e.g. controlPlane.distro.k8s.version is set to v1.30.1 and\ncontrolPlane.distro.k8s.scheduler.image.tag\n(or controlPlane.distro.k8s.controllerManager.image.tag or controlPlane.distro.k8s.apiServer.image.tag)\nis set to v1.31.0,\nvalue from controlPlane.distro.k8s.\u003ccontrolPlane-component\u003e.image.tag will be used\n(where \u003ccontrolPlane-component is apiServer, controllerManager and scheduler)." + }, + "apiServer": { + "$ref": "#/$defs/DistroContainerEnabled", + "description": "APIServer holds configuration specific to starting the api server." + }, + "controllerManager": { + "$ref": "#/$defs/DistroContainerEnabled", + "description": "ControllerManager holds configuration specific to starting the controller manager." + }, + "scheduler": { + "$ref": "#/$defs/DistroContainer", + "description": "Scheduler holds configuration specific to starting the scheduler. Enable this via controlPlane.advanced.virtualScheduler.enabled" + }, + "env": { + "items": { + "type": "object" + }, + "type": "array", + "description": "Env are extra environment variables to use for the main container and NOT the init container." + }, + "resources": { + "type": "object", + "description": "Resources for the distro init container" + }, + "securityContext": { + "type": "object", + "description": "Security options can be used for the distro init container" + } + }, + "additionalProperties": false, + "type": "object" + }, + "EnableAutoSwitchWithPatches": { + "properties": { + "enabled": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "boolean" + } + ], + "description": "Enabled defines if this option should be enabled." + }, + "patches": { + "items": { + "$ref": "#/$defs/TranslatePatch" + }, + "type": "array", + "description": "Patches patch the resource according to the provided specification." + } + }, + "additionalProperties": false, + "type": "object" + }, + "EnableSwitch": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled defines if this option should be enabled." + } + }, + "additionalProperties": false, + "type": "object" + }, + "EnableSwitchWithPatches": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled defines if this option should be enabled." + }, + "patches": { + "items": { + "$ref": "#/$defs/TranslatePatch" + }, + "type": "array", + "description": "Patches patch the resource according to the provided specification." + } + }, + "additionalProperties": false, + "type": "object" + }, + "Etcd": { + "properties": { + "embedded": { + "$ref": "#/$defs/EtcdEmbedded", + "description": "Embedded defines to use embedded etcd as a storage backend for the virtual cluster", + "pro": true + }, + "deploy": { + "$ref": "#/$defs/EtcdDeploy", + "description": "Deploy defines to use an external etcd that is deployed by the helm chart" + } + }, + "additionalProperties": false, + "type": "object" + }, + "EtcdDeploy": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled defines that an external etcd should be deployed." + }, + "statefulSet": { + "$ref": "#/$defs/EtcdDeployStatefulSet", + "description": "StatefulSet holds options for the external etcd statefulSet." + }, + "service": { + "$ref": "#/$defs/EtcdDeployService", + "description": "Service holds options for the external etcd service." + }, + "headlessService": { + "$ref": "#/$defs/EtcdDeployHeadlessService", + "description": "HeadlessService holds options for the external etcd headless service." + } + }, + "additionalProperties": false, + "type": "object" + }, + "EtcdDeployHeadlessService": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled defines if the etcd headless service should be deployed" + }, + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Annotations are extra annotations for the external etcd headless service" + } + }, + "additionalProperties": false, + "type": "object" + }, + "EtcdDeployService": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled defines if the etcd service should be deployed" + }, + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Annotations are extra annotations for the external etcd service" + } + }, + "additionalProperties": false, + "type": "object" + }, + "EtcdDeployStatefulSet": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled defines if the statefulSet should be deployed" + }, + "enableServiceLinks": { + "type": "boolean", + "description": "EnableServiceLinks for the StatefulSet pod" + }, + "image": { + "$ref": "#/$defs/Image", + "description": "Image is the image to use for the external etcd statefulSet" + }, + "imagePullPolicy": { + "type": "string", + "description": "ImagePullPolicy is the pull policy for the external etcd image" + }, + "env": { + "items": { + "type": "object" + }, + "type": "array", + "description": "Env are extra environment variables" + }, + "extraArgs": { + "items": { + "type": "string" + }, + "type": "array", + "description": "ExtraArgs are appended to the etcd command." + }, + "resources": { + "$ref": "#/$defs/Resources", + "description": "Resources the etcd can consume" + }, + "pods": { + "$ref": "#/$defs/LabelsAndAnnotations", + "description": "Pods defines extra metadata for the etcd pods." + }, + "highAvailability": { + "$ref": "#/$defs/ExternalEtcdHighAvailability", + "description": "HighAvailability are high availability options" + }, + "scheduling": { + "$ref": "#/$defs/ControlPlaneScheduling", + "description": "Scheduling options for the etcd pods." + }, + "security": { + "$ref": "#/$defs/ControlPlaneSecurity", + "description": "Security options for the etcd pods." + }, + "persistence": { + "$ref": "#/$defs/ExternalEtcdPersistence", + "description": "Persistence options for the etcd pods." + }, + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Annotations are extra annotations for this resource." + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Labels are extra labels for this resource." + } + }, + "additionalProperties": false, + "type": "object" + }, + "EtcdEmbedded": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled defines if the embedded etcd should be used.", + "pro": true + }, + "migrateFromDeployedEtcd": { + "type": "boolean", + "description": "MigrateFromDeployedEtcd signals that vCluster should migrate from the deployed external etcd to embedded etcd." + } + }, + "additionalProperties": false, + "type": "object" + }, + "Experimental": { + "properties": { + "deploy": { + "$ref": "#/$defs/ExperimentalDeploy", + "description": "Deploy allows you to configure manifests and Helm charts to deploy within the virtual cluster." + }, + "syncSettings": { + "$ref": "#/$defs/ExperimentalSyncSettings", + "description": "SyncSettings are advanced settings for the syncer controller." + }, + "genericSync": { + "$ref": "#/$defs/ExperimentalGenericSync", + "description": "GenericSync holds options to generically sync resources from virtual cluster to host." + }, + "multiNamespaceMode": { + "$ref": "#/$defs/ExperimentalMultiNamespaceMode", + "description": "MultiNamespaceMode tells virtual cluster to sync to multiple namespaces instead of a single one. This will map each virtual cluster namespace to a single namespace in the host cluster." + }, + "isolatedControlPlane": { + "$ref": "#/$defs/ExperimentalIsolatedControlPlane", + "description": "IsolatedControlPlane is a feature to run the vCluster control plane in a different Kubernetes cluster than the workloads themselves.", + "pro": true + }, + "virtualClusterKubeConfig": { + "$ref": "#/$defs/VirtualClusterKubeConfig", + "description": "VirtualClusterKubeConfig allows you to override distro specifics and specify where vCluster will find the required certificates and vCluster config." + }, + "denyProxyRequests": { + "items": { + "$ref": "#/$defs/DenyRule" + }, + "type": "array", + "description": "DenyProxyRequests denies certain requests in the vCluster proxy.", + "pro": true + } + }, + "additionalProperties": false, + "type": "object" + }, + "ExperimentalDeploy": { + "properties": { + "host": { + "$ref": "#/$defs/ExperimentalDeployHost", + "description": "Host defines what manifests to deploy into the host cluster" + }, + "vcluster": { + "$ref": "#/$defs/ExperimentalDeployVCluster", + "description": "VCluster defines what manifests and charts to deploy into the vCluster" + } + }, + "additionalProperties": false, + "type": "object" + }, + "ExperimentalDeployHelm": { + "properties": { + "chart": { + "$ref": "#/$defs/ExperimentalDeployHelmChart", + "description": "Chart defines what chart should get deployed." + }, + "release": { + "$ref": "#/$defs/ExperimentalDeployHelmRelease", + "description": "Release defines what release should get deployed." + }, + "values": { + "type": "string", + "description": "Values defines what values should get used." + }, + "timeout": { + "type": "string", + "description": "Timeout defines the timeout for Helm" + }, + "bundle": { + "type": "string", + "description": "Bundle allows to compress the Helm chart and specify this instead of an online chart" + } + }, + "additionalProperties": false, + "type": "object" + }, + "ExperimentalDeployHelmChart": { + "properties": { + "name": { + "type": "string" + }, + "repo": { + "type": "string" + }, + "insecure": { + "type": "boolean" + }, + "version": { + "type": "string" + }, + "username": { + "type": "string" + }, + "password": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "ExperimentalDeployHelmRelease": { + "properties": { + "name": { + "type": "string", + "description": "Name of the release" + }, + "namespace": { + "type": "string", + "description": "Namespace of the release" + } + }, + "additionalProperties": false, + "type": "object" + }, + "ExperimentalDeployHost": { + "properties": { + "manifests": { + "type": "string", + "description": "Manifests are raw Kubernetes manifests that should get applied within the virtual cluster." + }, + "manifestsTemplate": { + "type": "string", + "description": "ManifestsTemplate is a Kubernetes manifest template that will be rendered with vCluster values before applying it within the virtual cluster." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ExperimentalDeployVCluster": { + "properties": { + "manifests": { + "type": "string", + "description": "Manifests are raw Kubernetes manifests that should get applied within the virtual cluster." + }, + "manifestsTemplate": { + "type": "string", + "description": "ManifestsTemplate is a Kubernetes manifest template that will be rendered with vCluster values before applying it within the virtual cluster." + }, + "helm": { + "items": { + "$ref": "#/$defs/ExperimentalDeployHelm" + }, + "type": "array", + "description": "Helm are Helm charts that should get deployed into the virtual cluster" + } + }, + "additionalProperties": false, + "type": "object" + }, + "ExperimentalGenericSync": { + "properties": { + "version": { + "type": "string", + "description": "Version is the config version" + }, + "export": { + "items": { + "$ref": "#/$defs/Export" + }, + "type": "array", + "description": "Exports syncs a resource from the virtual cluster to the host" + }, + "import": { + "items": { + "$ref": "#/$defs/Import" + }, + "type": "array", + "description": "Imports syncs a resource from the host cluster to virtual cluster" + }, + "hooks": { + "$ref": "#/$defs/Hooks", + "description": "Hooks are hooks that can be used to inject custom patches before syncing" + }, + "clusterRole": { + "$ref": "#/$defs/ExperimentalGenericSyncExtraRules" + }, + "role": { + "$ref": "#/$defs/ExperimentalGenericSyncExtraRules" + } + }, + "additionalProperties": false, + "type": "object" + }, + "ExperimentalGenericSyncExtraRules": { + "properties": { + "extraRules": { + "items": true, + "type": "array" + } + }, + "additionalProperties": false, + "type": "object" + }, + "ExperimentalIsolatedControlPlane": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled specifies if the isolated control plane feature should be enabled." + }, + "headless": { + "type": "boolean", + "description": "Headless states that Helm should deploy the vCluster in headless mode for the isolated control plane." + }, + "kubeConfig": { + "type": "string", + "description": "KubeConfig is the path where to find the remote workload cluster kubeconfig." + }, + "namespace": { + "type": "string", + "description": "Namespace is the namespace where to sync the workloads into." + }, + "service": { + "type": "string", + "description": "Service is the vCluster service in the remote cluster." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ExperimentalMultiNamespaceMode": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled specifies if multi namespace mode should get enabled" + }, + "namespaceLabels": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "NamespaceLabels are extra labels that will be added by vCluster to each created namespace." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ExperimentalSyncSettings": { + "properties": { + "disableSync": { + "type": "boolean", + "description": "DisableSync will not sync any resources and disable most control plane functionality.", + "pro": true + }, + "rewriteKubernetesService": { + "type": "boolean", + "description": "RewriteKubernetesService will rewrite the Kubernetes service to point to the vCluster service if disableSync is enabled", + "pro": true + }, + "targetNamespace": { + "type": "string", + "description": "TargetNamespace is the namespace where the workloads should get synced to." + }, + "setOwner": { + "type": "boolean", + "description": "SetOwner specifies if vCluster should set an owner reference on the synced objects to the vCluster service. This allows for easy garbage collection." + }, + "hostMetricsBindAddress": { + "type": "string", + "description": "HostMetricsBindAddress is the bind address for the local manager" + }, + "virtualMetricsBindAddress": { + "type": "string", + "description": "VirtualMetricsBindAddress is the bind address for the virtual manager" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Export": { + "properties": { + "apiVersion": { + "type": "string", + "description": "APIVersion of the object to sync" + }, + "kind": { + "type": "string", + "description": "Kind of the object to sync" + }, + "optional": { + "type": "boolean" + }, + "replaceOnConflict": { + "type": "boolean", + "description": "ReplaceWhenInvalid determines if the controller should try to recreate the object\nif there is a problem applying" + }, + "patches": { + "items": { + "$ref": "#/$defs/Patch" + }, + "type": "array", + "description": "Patches are the patches to apply on the virtual cluster objects\nwhen syncing them from the host cluster" + }, + "reversePatches": { + "items": { + "$ref": "#/$defs/Patch" + }, + "type": "array", + "description": "ReversePatches are the patches to apply to host cluster objects\nafter it has been synced to the virtual cluster" + }, + "selector": { + "$ref": "#/$defs/Selector", + "description": "Selector is a label selector to select the synced objects in the virtual cluster.\nIf empty, all objects will be synced." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ExportKubeConfig": { + "properties": { + "context": { + "type": "string", + "description": "Context is the name of the context within the generated kubeconfig to use." + }, + "server": { + "type": "string", + "description": "Override the default https://localhost:8443 and specify a custom hostname for the generated kubeconfig." + }, + "insecure": { + "type": "boolean", + "description": "If tls should get skipped for the server" + }, + "serviceAccount": { + "$ref": "#/$defs/ExportKubeConfigServiceAccount", + "description": "ServiceAccount can be used to generate a service account token instead of the default certificates." + }, + "secret": { + "$ref": "#/$defs/ExportKubeConfigSecretReference", + "description": "Declare in which host cluster secret vCluster should store the generated virtual cluster kubeconfig.\nIf this is not defined, vCluster will create it with `vc-NAME`. If you specify another name,\nvCluster creates the config in this other secret." + } + }, + "additionalProperties": false, + "type": "object", + "description": "ExportKubeConfig describes how vCluster should export the vCluster kubeconfig." + }, + "ExportKubeConfigSecretReference": { + "properties": { + "name": { + "type": "string", + "description": "Name is the name of the secret where the kubeconfig should get stored." + }, + "namespace": { + "type": "string", + "description": "Namespace where vCluster should store the kubeconfig secret. If this is not equal to the namespace\nwhere you deployed vCluster, you need to make sure vCluster has access to this other namespace." + } + }, + "additionalProperties": false, + "type": "object", + "description": "Declare in which host cluster secret vCluster should store the generated virtual cluster kubeconfig." + }, + "ExportKubeConfigServiceAccount": { + "properties": { + "name": { + "type": "string", + "description": "Name of the service account to be used to generate a service account token instead of the default certificates." + }, + "namespace": { + "type": "string", + "description": "Namespace of the service account to be used to generate a service account token instead of the default certificates.\nIf omitted, will use the kube-system namespace." + }, + "clusterRole": { + "type": "string", + "description": "ClusterRole to assign to the service account." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ExternalConfig": { + "properties": { + "platform": { + "$ref": "#/$defs/PlatformConfig", + "type": "object", + "description": "platform holds platform configuration" + } + }, + "type": "object", + "description": "ExternalConfig holds external configuration" + }, + "ExternalDatabaseKine": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled defines if the database should be used." + }, + "dataSource": { + "type": "string", + "description": "DataSource is the kine dataSource to use for the database. This depends on the database format.\nThis is optional for the embedded database. Examples:\n* mysql: mysql://username:password@tcp(hostname:3306)/k3s\n* postgres: postgres://username:password@hostname:5432/k3s" + }, + "keyFile": { + "type": "string", + "description": "KeyFile is the key file to use for the database. This is optional." + }, + "certFile": { + "type": "string", + "description": "CertFile is the cert file to use for the database. This is optional." + }, + "caFile": { + "type": "string", + "description": "CaFile is the ca file to use for the database. This is optional." + }, + "connector": { + "type": "string", + "description": "Connector specifies a secret located in a connected vCluster Platform that contains database server connection information\nto be used by Platform to create a database and database user for the vCluster.\nand non-privileged user. A kine endpoint should be created using the database and user on Platform registration.\nThis is optional." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ExternalEtcdHighAvailability": { + "properties": { + "replicas": { + "type": "integer", + "description": "Replicas are the amount of pods to use." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ExternalEtcdPersistence": { + "properties": { + "volumeClaim": { + "$ref": "#/$defs/ExternalEtcdPersistenceVolumeClaim", + "description": "VolumeClaim can be used to configure the persistent volume claim." + }, + "volumeClaimTemplates": { + "items": { + "type": "object" + }, + "type": "array", + "description": "VolumeClaimTemplates defines the volumeClaimTemplates for the statefulSet" + }, + "addVolumes": { + "items": { + "type": "object" + }, + "type": "array", + "description": "AddVolumes defines extra volumes for the pod" + }, + "addVolumeMounts": { + "items": { + "$ref": "#/$defs/VolumeMount" + }, + "type": "array", + "description": "AddVolumeMounts defines extra volume mounts for the container" + } + }, + "additionalProperties": false, + "type": "object" + }, + "ExternalEtcdPersistenceVolumeClaim": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled enables deploying a persistent volume claim." + }, + "accessModes": { + "items": { + "type": "string" + }, + "type": "array", + "description": "AccessModes are the persistent volume claim access modes." + }, + "retentionPolicy": { + "type": "string", + "description": "RetentionPolicy is the persistent volume claim retention policy." + }, + "size": { + "type": "string", + "description": "Size is the persistent volume claim storage size." + }, + "storageClass": { + "type": "string", + "description": "StorageClass is the persistent volume claim storage class." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ExternalSecrets": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled defines whether the external secret integration is enabled or not" + }, + "webhook": { + "$ref": "#/$defs/EnableSwitch", + "description": "Webhook defines whether the host webhooks are reused or not" + }, + "sync": { + "$ref": "#/$defs/ExternalSecretsSync", + "description": "Sync defines the syncing behavior for the integration" + } + }, + "additionalProperties": false, + "type": "object", + "description": "ExternalSecrets reuses a host external secret operator and makes certain CRDs from it available inside the vCluster" + }, + "ExternalSecretsSync": { + "properties": { + "externalSecrets": { + "$ref": "#/$defs/EnableSwitch", + "description": "ExternalSecrets defines whether to sync external secrets or not" + }, + "stores": { + "$ref": "#/$defs/EnableSwitch", + "description": "Stores defines whether to sync stores or not" + }, + "clusterStores": { + "$ref": "#/$defs/ClusterStoresSyncConfig", + "description": "ClusterStores defines whether to sync cluster stores or not" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Hook": { + "properties": { + "apiVersion": { + "type": "string", + "description": "APIVersion of the object to sync" + }, + "kind": { + "type": "string", + "description": "Kind of the object to sync" + }, + "verbs": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Verbs are the verbs that the hook should mutate" + }, + "patches": { + "items": { + "$ref": "#/$defs/Patch" + }, + "type": "array", + "description": "Patches are the patches to apply on the object to be synced" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Hooks": { + "properties": { + "hostToVirtual": { + "items": { + "$ref": "#/$defs/Hook" + }, + "type": "array", + "description": "HostToVirtual is a hook that is executed before syncing from the host to the virtual cluster" + }, + "virtualToHost": { + "items": { + "$ref": "#/$defs/Hook" + }, + "type": "array", + "description": "VirtualToHost is a hook that is executed before syncing from the virtual to the host cluster" + } + }, + "additionalProperties": false, + "type": "object" + }, + "HostPathMapper": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled specifies if the host path mapper will be used" + }, + "central": { + "type": "boolean", + "description": "Central specifies if the central host path mapper will be used" + } + }, + "additionalProperties": false, + "type": "object" + }, + "IPBlock": { + "properties": { + "cidr": { + "type": "string", + "description": "cidr is a string representing the IPBlock\nValid examples are \"192.168.1.0/24\" or \"2001:db8::/64\"" + }, + "except": { + "items": { + "type": "string" + }, + "type": "array", + "description": "except is a slice of CIDRs that should not be included within an IPBlock\nValid examples are \"192.168.1.0/24\" or \"2001:db8::/64\"\nExcept values will be rejected if they are outside the cidr range\n+optional" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Image": { + "properties": { + "registry": { + "type": "string", + "description": "Registry is the registry of the container image, e.g. my-registry.com or ghcr.io. This setting can be globally\noverridden via the controlPlane.advanced.defaultImageRegistry option. Empty means docker hub." + }, + "repository": { + "type": "string", + "description": "Repository is the repository of the container image, e.g. my-repo/my-image" + }, + "tag": { + "type": "string", + "description": "Tag is the tag of the container image, e.g. latest" + } + }, + "additionalProperties": false, + "type": "object" + }, + "ImagePullSecretName": { + "properties": { + "name": { + "type": "string", + "description": "Name of the image pull secret to use." + } + }, + "additionalProperties": false, + "type": "object" + }, + "Import": { + "properties": { + "apiVersion": { + "type": "string", + "description": "APIVersion of the object to sync" + }, + "kind": { + "type": "string", + "description": "Kind of the object to sync" + }, + "optional": { + "type": "boolean" + }, + "replaceOnConflict": { + "type": "boolean", + "description": "ReplaceWhenInvalid determines if the controller should try to recreate the object\nif there is a problem applying" + }, + "patches": { + "items": { + "$ref": "#/$defs/Patch" + }, + "type": "array", + "description": "Patches are the patches to apply on the virtual cluster objects\nwhen syncing them from the host cluster" + }, + "reversePatches": { + "items": { + "$ref": "#/$defs/Patch" + }, + "type": "array", + "description": "ReversePatches are the patches to apply to host cluster objects\nafter it has been synced to the virtual cluster" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Integrations": { + "properties": { + "metricsServer": { + "$ref": "#/$defs/MetricsServer", + "description": "MetricsServer reuses the metrics server from the host cluster within the vCluster." + }, + "kubeVirt": { + "$ref": "#/$defs/KubeVirt", + "description": "KubeVirt reuses a host kubevirt and makes certain CRDs from it available inside the vCluster" + }, + "externalSecrets": { + "$ref": "#/$defs/ExternalSecrets", + "description": "ExternalSecrets reuses a host external secret operator and makes certain CRDs from it available inside the vCluster" + } + }, + "additionalProperties": false, + "type": "object", + "description": "Integrations holds config for vCluster integrations with other operators or tools running on the host cluster" + }, + "KubeVirt": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled signals if the integration should be enabled" + }, + "apiService": { + "$ref": "#/$defs/APIService", + "description": "APIService holds information about where to find the virt-api service. Defaults to virt-api/kubevirt." + }, + "webhook": { + "$ref": "#/$defs/EnableSwitch", + "description": "Webhook holds configuration for enabling the webhook within the vCluster" + }, + "sync": { + "$ref": "#/$defs/KubeVirtSync", + "description": "Sync holds configuration on what resources to sync" + } + }, + "additionalProperties": false, + "type": "object", + "description": "KubeVirt reuses a host kubevirt and makes certain CRDs from it available inside the vCluster" + }, + "KubeVirtSync": { + "properties": { + "dataVolumes": { + "$ref": "#/$defs/EnableSwitch", + "description": "If DataVolumes should get synced" + }, + "virtualMachineInstanceMigrations": { + "$ref": "#/$defs/EnableSwitch", + "description": "If VirtualMachineInstanceMigrations should get synced" + }, + "virtualMachineInstances": { + "$ref": "#/$defs/EnableSwitch", + "description": "If VirtualMachineInstances should get synced" + }, + "virtualMachines": { + "$ref": "#/$defs/EnableSwitch", + "description": "If VirtualMachines should get synced" + }, + "virtualMachineClones": { + "$ref": "#/$defs/EnableSwitch", + "description": "If VirtualMachineClones should get synced" + }, + "virtualMachinePools": { + "$ref": "#/$defs/EnableSwitch", + "description": "If VirtualMachinePools should get synced" + } + }, + "additionalProperties": false, + "type": "object", + "description": "KubeVirtSync are the crds that are supported by this integration" + }, + "LabelSelector": { + "properties": { + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Labels defines what labels should be looked for" + } + }, + "additionalProperties": false, + "type": "object" + }, + "LabelsAndAnnotations": { + "properties": { + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Annotations are extra annotations for this resource." + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Labels are extra labels for this resource." + } + }, + "additionalProperties": false, + "type": "object" + }, + "LimitRange": { + "properties": { + "enabled": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "boolean" + } + ], + "description": "Enabled defines if the limit range should be deployed by vCluster. \"auto\" means that if resourceQuota is enabled,\nthe limitRange will be enabled as well." + }, + "default": { + "type": "object", + "description": "Default are the default limits for the limit range" + }, + "defaultRequest": { + "type": "object", + "description": "DefaultRequest are the default request options for the limit range" + }, + "max": { + "type": "object", + "description": "Max are the max limits for the limit range" + }, + "min": { + "type": "object", + "description": "Min are the min limits for the limit range" + }, + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Annotations are extra annotations for this resource." + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Labels are extra labels for this resource." + } + }, + "additionalProperties": false, + "type": "object" + }, + "MetricsServer": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled signals the metrics server integration should be enabled." + }, + "apiService": { + "$ref": "#/$defs/APIService", + "description": "APIService holds information about where to find the metrics-server service. Defaults to metrics-server/kube-system." + }, + "nodes": { + "type": "boolean", + "description": "Nodes defines if metrics-server nodes api should get proxied from host to virtual cluster." + }, + "pods": { + "type": "boolean", + "description": "Pods defines if metrics-server pods api should get proxied from host to virtual cluster." + } + }, + "additionalProperties": false, + "type": "object", + "description": "MetricsServer reuses the metrics server from the host cluster within the vCluster." + }, + "MutatingWebhook": { + "properties": { + "reinvocationPolicy": { + "type": "string", + "description": "reinvocationPolicy indicates whether this webhook should be called multiple times as part of a single admission evaluation.\nAllowed values are \"Never\" and \"IfNeeded\"." + }, + "name": { + "type": "string", + "description": "The name of the admission webhook.\nName should be fully qualified, e.g., imagepolicy.kubernetes.io, where\n\"imagepolicy\" is the name of the webhook, and kubernetes.io is the name\nof the organization." + }, + "clientConfig": { + "$ref": "#/$defs/ValidatingWebhookClientConfig", + "description": "ClientConfig defines how to communicate with the hook." + }, + "rules": { + "items": true, + "type": "array", + "description": "Rules describes what operations on what resources/subresources the webhook cares about.\nThe webhook cares about an operation if it matches _any_ Rule." + }, + "failurePolicy": { + "type": "string", + "description": "FailurePolicy defines how unrecognized errors from the admission endpoint are handled -\nallowed values are Ignore or Fail. Defaults to Fail." + }, + "matchPolicy": { + "type": "string", + "description": "matchPolicy defines how the \"rules\" list is used to match incoming requests.\nAllowed values are \"Exact\" or \"Equivalent\"." + }, + "namespaceSelector": { + "description": "NamespaceSelector decides whether to run the webhook on an object based\non whether the namespace for that object matches the selector. If the\nobject itself is a namespace, the matching is performed on\nobject.metadata.labels. If the object is another cluster scoped resource,\nit never skips the webhook." + }, + "objectSelector": { + "description": "ObjectSelector decides whether to run the webhook based on if the\nobject has matching labels. objectSelector is evaluated against both\nthe oldObject and newObject that would be sent to the webhook, and\nis considered to match if either object matches the selector." + }, + "sideEffects": { + "type": "string", + "description": "SideEffects states whether this webhook has side effects." + }, + "timeoutSeconds": { + "type": "integer", + "description": "TimeoutSeconds specifies the timeout for this webhook." + }, + "admissionReviewVersions": { + "items": { + "type": "string" + }, + "type": "array", + "description": "AdmissionReviewVersions is an ordered list of preferred `AdmissionReview`\nversions the Webhook expects." + }, + "matchConditions": { + "items": true, + "type": "array", + "description": "MatchConditions is a list of conditions that must be met for a request to be sent to this\nwebhook. Match conditions filter requests that have already been matched by the rules,\nnamespaceSelector, and objectSelector. An empty list of matchConditions matches all requests.\nThere are a maximum of 64 match conditions allowed." + } + }, + "additionalProperties": false, + "type": "object" + }, + "MutatingWebhookConfiguration": { + "properties": { + "kind": { + "type": "string", + "description": "Kind is a string value representing the REST resource this object represents.\nServers may infer this from the endpoint the client submits requests to." + }, + "apiVersion": { + "type": "string", + "description": "APIVersion defines the versioned schema of this representation of an object.\nServers should convert recognized schemas to the latest internal value, and\nmay reject unrecognized values." + }, + "metadata": { + "$ref": "#/$defs/ObjectMeta", + "description": "Standard object metadata; More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata." + }, + "webhooks": { + "items": { + "$ref": "#/$defs/MutatingWebhook" + }, + "type": "array", + "description": "Webhooks is a list of webhooks and the affected resources and operations." + } + }, + "additionalProperties": false, + "type": "object" + }, + "NetworkPolicy": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled defines if the network policy should be deployed by vCluster." + }, + "fallbackDns": { + "type": "string" + }, + "outgoingConnections": { + "$ref": "#/$defs/OutgoingConnections" + }, + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Annotations are extra annotations for this resource." + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Labels are extra labels for this resource." + } + }, + "additionalProperties": false, + "type": "object" + }, + "NetworkProxyKubelets": { + "properties": { + "byHostname": { + "type": "boolean", + "description": "ByHostname will add a special vCluster hostname to the nodes where the node can be reached at. This doesn't work\nfor all applications, e.g. Prometheus requires a node IP." + }, + "byIP": { + "type": "boolean", + "description": "ByIP will create a separate service in the host cluster for every node that will point to virtual cluster and will be used to\nroute traffic." + } + }, + "additionalProperties": false, + "type": "object" + }, + "Networking": { + "properties": { + "replicateServices": { + "$ref": "#/$defs/ReplicateServices", + "description": "ReplicateServices allows replicating services from the host within the virtual cluster or the other way around." + }, + "resolveDNS": { + "items": { + "$ref": "#/$defs/ResolveDNS" + }, + "type": "array", + "description": "ResolveDNS allows to define extra DNS rules. This only works if embedded coredns is configured.", + "pro": true + }, + "advanced": { + "$ref": "#/$defs/NetworkingAdvanced", + "description": "Advanced holds advanced network options." + } + }, + "additionalProperties": false, + "type": "object" + }, + "NetworkingAdvanced": { + "properties": { + "clusterDomain": { + "type": "string", + "description": "ClusterDomain is the Kubernetes cluster domain to use within the virtual cluster." + }, + "fallbackHostCluster": { + "type": "boolean", + "description": "FallbackHostCluster allows to fallback dns to the host cluster. This is useful if you want to reach host services without\nany other modification. You will need to provide a namespace for the service, e.g. my-other-service.my-other-namespace" + }, + "proxyKubelets": { + "$ref": "#/$defs/NetworkProxyKubelets", + "description": "ProxyKubelets allows rewriting certain metrics and stats from the Kubelet to \"fake\" this for applications such as\nprometheus or other node exporters." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ObjectMeta": { + "properties": { + "name": { + "type": "string", + "description": "Name must be unique within a namespace. Is required when creating resources, although\nsome resources may allow a client to request the generation of an appropriate name\nautomatically. Name is primarily intended for creation idempotence and configuration\ndefinition." + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Map of string keys and values that can be used to organize and categorize\n(scope and select) objects. May match selectors of replication controllers\nand services." + }, + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Annotations is an unstructured key value map stored with a resource that may be\nset by external tools to store and retrieve arbitrary metadata." + } + }, + "additionalProperties": false, + "type": "object" + }, + "OutgoingConnections": { + "properties": { + "ipBlock": { + "$ref": "#/$defs/IPBlock", + "description": "IPBlock describes a particular CIDR (Ex. \"192.168.1.0/24\",\"2001:db8::/64\") that is allowed\nto the pods matched by a NetworkPolicySpec's podSelector. The except entry describes CIDRs\nthat should not be included within this rule." + }, + "platform": { + "type": "boolean", + "description": "Platform enables egress access towards loft platform" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Patch": { + "properties": { + "op": { + "type": "string", + "description": "Operation is the type of the patch" + }, + "fromPath": { + "type": "string", + "description": "FromPath is the path from the other object" + }, + "path": { + "type": "string", + "description": "Path is the path of the patch" + }, + "namePath": { + "type": "string", + "description": "NamePath is the path to the name of a child resource within Path" + }, + "namespacePath": { + "type": "string", + "description": "NamespacePath is path to the namespace of a child resource within Path" + }, + "value": { + "description": "Value is the new value to be set to the path" + }, + "regex": { + "type": "string", + "description": "Regex - is regular expresion used to identify the Name,\nand optionally Namespace, parts of the field value that\nwill be replaced with the rewritten Name and/or Namespace" + }, + "conditions": { + "items": { + "$ref": "#/$defs/PatchCondition" + }, + "type": "array", + "description": "Conditions are conditions that must be true for\nthe patch to get executed" + }, + "ignore": { + "type": "boolean", + "description": "Ignore determines if the path should be ignored if handled as a reverse patch" + }, + "sync": { + "$ref": "#/$defs/PatchSync", + "description": "Sync defines if a specialized syncer should be initialized using values\nfrom the rewriteName operation as Secret/Configmap names to be synced" + } + }, + "additionalProperties": false, + "type": "object" + }, + "PatchCondition": { + "properties": { + "path": { + "type": "string", + "description": "Path is the path within the object to select" + }, + "subPath": { + "type": "string", + "description": "SubPath is the path below the selected object to select" + }, + "equal": { + "description": "Equal is the value the path should be equal to" + }, + "notEqual": { + "description": "NotEqual is the value the path should not be equal to" + }, + "empty": { + "type": "boolean", + "description": "Empty means that the path value should be empty or unset" + } + }, + "additionalProperties": false, + "type": "object" + }, + "PatchSync": { + "properties": { + "secret": { + "type": "boolean" + }, + "configmap": { + "type": "boolean" + } + }, + "additionalProperties": false, + "type": "object" + }, + "PlatformAPIKey": { + "properties": { + "secretName": { + "type": "string", + "description": "SecretName is the name of the secret where the platform access key is stored. This defaults to vcluster-platform-api-key if undefined." + }, + "namespace": { + "type": "string", + "description": "Namespace defines the namespace where the access key secret should be retrieved from. If this is not equal to the namespace\nwhere the vCluster instance is deployed, you need to make sure vCluster has access to this other namespace." + }, + "createRBAC": { + "type": "boolean", + "description": "CreateRBAC will automatically create the necessary RBAC roles and role bindings to allow vCluster to read the secret specified\nin the above namespace, if specified.\nThis defaults to true." + } + }, + "additionalProperties": false, + "type": "object", + "description": "PlatformAPIKey defines where to find the platform access key." + }, + "PlatformConfig": { + "properties": { + "apiKey": { + "$ref": "#/$defs/PlatformAPIKey", + "description": "APIKey defines where to find the platform access key and host. By default, vCluster will search in the following locations in this precedence:\n* environment variable called LICENSE\n* secret specified under external.platform.apiKey.secretName\n* secret called \"vcluster-platform-api-key\" in the vCluster namespace" + } + }, + "type": "object", + "description": "PlatformConfig holds platform configuration" + }, + "Plugin": { + "properties": { + "name": { + "type": "string", + "description": "Name is the name of the init-container and NOT the plugin name" + }, + "image": { + "type": "string", + "description": "Image is the container image that should be used for the plugin" + }, + "imagePullPolicy": { + "type": "string", + "description": "ImagePullPolicy is the pull policy to use for the container image" + }, + "config": { + "type": "object", + "description": "Config is the plugin config to use. This can be arbitrary config used for the plugin." + }, + "rbac": { + "$ref": "#/$defs/PluginsRBAC", + "description": "RBAC holds additional rbac configuration for the plugin" + }, + "command": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Command is the command that should be used for the init container" + }, + "args": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Args are the arguments that should be used for the init container" + }, + "securityContext": { + "type": "object", + "description": "SecurityContext is the container security context used for the init container" + }, + "resources": { + "type": "object", + "description": "Resources are the container resources used for the init container" + }, + "volumeMounts": { + "items": true, + "type": "array", + "description": "VolumeMounts are extra volume mounts for the init container" + }, + "version": { + "type": "string", + "description": "Version is the plugin version, this is only needed for legacy plugins." + }, + "env": { + "items": true, + "type": "array" + }, + "envFrom": { + "items": true, + "type": "array" + }, + "lifecycle": { + "type": "object" + }, + "livenessProbe": { + "type": "object" + }, + "readinessProbe": { + "type": "object" + }, + "startupProbe": { + "type": "object" + }, + "workingDir": { + "type": "string" + }, + "optional": { + "type": "boolean" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Plugins": { + "properties": { + "name": { + "type": "string", + "description": "Name is the name of the init-container and NOT the plugin name" + }, + "image": { + "type": "string", + "description": "Image is the container image that should be used for the plugin" + }, + "imagePullPolicy": { + "type": "string", + "description": "ImagePullPolicy is the pull policy to use for the container image" + }, + "config": { + "type": "object", + "description": "Config is the plugin config to use. This can be arbitrary config used for the plugin." + }, + "rbac": { + "$ref": "#/$defs/PluginsRBAC", + "description": "RBAC holds additional rbac configuration for the plugin" + }, + "command": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Command is the command that should be used for the init container" + }, + "args": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Args are the arguments that should be used for the init container" + }, + "securityContext": { + "type": "object", + "description": "SecurityContext is the container security context used for the init container" + }, + "resources": { + "type": "object", + "description": "Resources are the container resources used for the init container" + }, + "volumeMounts": { + "items": true, + "type": "array", + "description": "VolumeMounts are extra volume mounts for the init container" + } + }, + "additionalProperties": false, + "type": "object" + }, + "PluginsExtraRules": { + "properties": { + "extraRules": { + "items": { + "$ref": "#/$defs/RBACPolicyRule" + }, + "type": "array", + "description": "ExtraRules are extra rbac permissions roles that will be added to role or cluster role" + } + }, + "additionalProperties": false, + "type": "object" + }, + "PluginsRBAC": { + "properties": { + "role": { + "$ref": "#/$defs/PluginsExtraRules", + "description": "Role holds extra virtual cluster role permissions for the plugin" + }, + "clusterRole": { + "$ref": "#/$defs/PluginsExtraRules", + "description": "ClusterRole holds extra virtual cluster cluster role permissions required for the plugin" + } + }, + "additionalProperties": false, + "type": "object" + }, + "PodDNSConfig": { + "properties": { + "nameservers": { + "items": { + "type": "string" + }, + "type": "array", + "description": "A list of DNS name server IP addresses.\nThis will be appended to the base nameservers generated from DNSPolicy.\nDuplicated nameservers will be removed.\n+optional\n+listType=atomic" + }, + "searches": { + "items": { + "type": "string" + }, + "type": "array", + "description": "A list of DNS search domains for host-name lookup.\nThis will be appended to the base search paths generated from DNSPolicy.\nDuplicated search paths will be removed.\n+optional\n+listType=atomic" + }, + "options": { + "items": { + "$ref": "#/$defs/PodDNSConfigOption" + }, + "type": "array", + "description": "A list of DNS resolver options.\nThis will be merged with the base options generated from DNSPolicy.\nDuplicated entries will be removed. Resolution options given in Options\nwill override those that appear in the base DNSPolicy.\n+optional\n+listType=atomic" + } + }, + "additionalProperties": false, + "type": "object", + "description": "PodDNSConfig defines the DNS parameters of a pod in addition to those generated from DNSPolicy." + }, + "PodDNSConfigOption": { + "properties": { + "name": { + "type": "string", + "description": "Required." + }, + "value": { + "type": "string", + "description": "+optional" + } + }, + "additionalProperties": false, + "type": "object", + "description": "PodDNSConfigOption defines DNS resolver options of a pod." + }, + "Policies": { + "properties": { + "networkPolicy": { + "$ref": "#/$defs/NetworkPolicy", + "description": "NetworkPolicy specifies network policy options." + }, + "podSecurityStandard": { + "type": "string", + "description": "PodSecurityStandard that can be enforced can be one of: empty (\"\"), baseline, restricted or privileged" + }, + "resourceQuota": { + "$ref": "#/$defs/ResourceQuota", + "description": "ResourceQuota specifies resource quota options." + }, + "limitRange": { + "$ref": "#/$defs/LimitRange", + "description": "LimitRange specifies limit range options." + }, + "centralAdmission": { + "$ref": "#/$defs/CentralAdmission", + "description": "CentralAdmission defines what validating or mutating webhooks should be enforced within the virtual cluster.", + "pro": true + } + }, + "additionalProperties": false, + "type": "object" + }, + "RBAC": { + "properties": { + "role": { + "$ref": "#/$defs/RBACRole", + "description": "Role holds virtual cluster role configuration" + }, + "clusterRole": { + "$ref": "#/$defs/RBACClusterRole", + "description": "ClusterRole holds virtual cluster cluster role configuration" + } + }, + "additionalProperties": false, + "type": "object" + }, + "RBACClusterRole": { + "properties": { + "enabled": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "boolean" + } + ], + "description": "Enabled defines if the cluster role should be enabled or disabled. If auto, vCluster automatically determines whether the virtual cluster requires a cluster role." + }, + "extraRules": { + "items": { + "type": "object" + }, + "type": "array", + "description": "ExtraRules will add rules to the cluster role." + }, + "overwriteRules": { + "items": { + "type": "object" + }, + "type": "array", + "description": "OverwriteRules will overwrite the cluster role rules completely." + } + }, + "additionalProperties": false, + "type": "object" + }, + "RBACPolicyRule": { + "properties": { + "verbs": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Verbs is a list of Verbs that apply to ALL the ResourceKinds contained in this rule. '*' represents all verbs." + }, + "apiGroups": { + "items": { + "type": "string" + }, + "type": "array", + "description": "APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of\nthe enumerated resources in any API group will be allowed. \"\" represents the core API group and \"*\" represents all API groups." + }, + "resources": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Resources is a list of resources this rule applies to. '*' represents all resources." + }, + "resourceNames": { + "items": { + "type": "string" + }, + "type": "array", + "description": "ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed." + }, + "nonResourceURLs": { + "items": { + "type": "string" + }, + "type": "array", + "description": "NonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, final step in the path\nSince non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding.\nRules can either apply to API resources (such as \"pods\" or \"secrets\") or non-resource URL paths (such as \"/api\"), but not both." + } + }, + "additionalProperties": false, + "type": "object" + }, + "RBACRole": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled defines if the role should be enabled or disabled." + }, + "extraRules": { + "items": { + "type": "object" + }, + "type": "array", + "description": "ExtraRules will add rules to the role." + }, + "overwriteRules": { + "items": { + "type": "object" + }, + "type": "array", + "description": "OverwriteRules will overwrite the role rules completely." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ReplicateServices": { + "properties": { + "toHost": { + "items": { + "$ref": "#/$defs/ServiceMapping" + }, + "type": "array", + "description": "ToHost defines the services that should get synced from virtual cluster to the host cluster. If services are\nsynced to a different namespace than the virtual cluster is in, additional permissions for the other namespace\nare required." + }, + "fromHost": { + "items": { + "$ref": "#/$defs/ServiceMapping" + }, + "type": "array", + "description": "FromHost defines the services that should get synced from the host to the virtual cluster." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ResolveDNS": { + "properties": { + "hostname": { + "type": "string", + "description": "Hostname is the hostname within the vCluster that should be resolved from." + }, + "service": { + "type": "string", + "description": "Service is the virtual cluster service that should be resolved from." + }, + "namespace": { + "type": "string", + "description": "Namespace is the virtual cluster namespace that should be resolved from." + }, + "target": { + "$ref": "#/$defs/ResolveDNSTarget", + "description": "Target is the DNS target that should get mapped to" + } + }, + "additionalProperties": false, + "type": "object" + }, + "ResolveDNSTarget": { + "properties": { + "hostname": { + "type": "string", + "description": "Hostname to use as a DNS target" + }, + "ip": { + "type": "string", + "description": "IP to use as a DNS target" + }, + "hostService": { + "type": "string", + "description": "HostService to target, format is hostNamespace/hostService" + }, + "hostNamespace": { + "type": "string", + "description": "HostNamespace to target" + }, + "vClusterService": { + "type": "string", + "description": "VClusterService format is hostNamespace/vClusterName/vClusterNamespace/vClusterService" + } + }, + "additionalProperties": false, + "type": "object" + }, + "ResourceQuota": { + "properties": { + "enabled": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "boolean" + } + ], + "description": "Enabled defines if the resource quota should be enabled. \"auto\" means that if limitRange is enabled,\nthe resourceQuota will be enabled as well." + }, + "quota": { + "type": "object", + "description": "Quota are the quota options" + }, + "scopeSelector": { + "type": "object", + "description": "ScopeSelector is the resource quota scope selector" + }, + "scopes": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Scopes are the resource quota scopes" + }, + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Annotations are extra annotations for this resource." + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Labels are extra labels for this resource." + } + }, + "additionalProperties": false, + "type": "object" + }, + "Resources": { + "properties": { + "limits": { + "type": "object", + "description": "Limits are resource limits for the container" + }, + "requests": { + "type": "object", + "description": "Requests are minimal resources that will be consumed by the container" + } + }, + "additionalProperties": false, + "type": "object" + }, + "RuleWithVerbs": { + "properties": { + "apiGroups": { + "items": { + "type": "string" + }, + "type": "array", + "description": "APIGroups is the API groups the resources belong to. '*' is all groups." + }, + "apiVersions": { + "items": { + "type": "string" + }, + "type": "array", + "description": "APIVersions is the API versions the resources belong to. '*' is all versions." + }, + "resources": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Resources is a list of resources this rule applies to." + }, + "scope": { + "type": "string", + "description": "Scope specifies the scope of this rule." + }, + "operations": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Verb is the kube verb associated with the request for API requests, not the http verb. This includes things like list and watch.\nFor non-resource requests, this is the lowercase http verb.\nIf '*' is present, the length of the slice must be one." + } + }, + "additionalProperties": false, + "type": "object" + }, + "Selector": { + "properties": { + "labelSelector": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "LabelSelector are the labels to select the object from" + } + }, + "additionalProperties": false, + "type": "object" + }, + "ServiceMapping": { + "properties": { + "from": { + "type": "string", + "description": "From is the service that should get synced. Can be either in the form name or namespace/name." + }, + "to": { + "type": "string", + "description": "To is the target service that it should get synced to. Can be either in the form name or namespace/name." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ServiceMonitor": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled configures if Helm should create the service monitor." + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Labels are the extra labels to add to the service monitor." + }, + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Annotations are the extra annotations to add to the service monitor." + } + }, + "additionalProperties": false, + "type": "object" + }, + "StatefulSetImage": { + "properties": { + "registry": { + "type": "string", + "description": "Configure the registry of the container image, e.g. my-registry.com or ghcr.io\nIt defaults to ghcr.io and can be overriding either by using this field or controlPlane.advanced.defaultImageRegistry" + }, + "repository": { + "type": "string", + "description": "Configure the repository of the container image, e.g. my-repo/my-image.\nIt defaults to the vCluster pro repository that includes the optional pro modules that are turned off by default.\nIf you still want to use the pure OSS build, use 'loft-sh/vcluster-oss' instead." + }, + "tag": { + "type": "string", + "description": "Tag is the tag of the container image, e.g. latest" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Sync": { + "properties": { + "toHost": { + "$ref": "#/$defs/SyncToHost", + "description": "Configure resources to sync from the virtual cluster to the host cluster." + }, + "fromHost": { + "$ref": "#/$defs/SyncFromHost", + "description": "Configure what resources vCluster should sync from the host cluster to the virtual cluster." + } + }, + "additionalProperties": false, + "type": "object" + }, + "SyncAllResource": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled defines if this option should be enabled." + }, + "all": { + "type": "boolean", + "description": "All defines if all resources of that type should get synced or only the necessary ones that are needed." + }, + "patches": { + "items": { + "$ref": "#/$defs/TranslatePatch" + }, + "type": "array", + "description": "Patches patch the resource according to the provided specification." + } + }, + "additionalProperties": false, + "type": "object" + }, + "SyncFromHost": { + "properties": { + "nodes": { + "$ref": "#/$defs/SyncNodes", + "description": "Nodes defines if nodes should get synced from the host cluster to the virtual cluster, but not back." + }, + "events": { + "$ref": "#/$defs/EnableSwitchWithPatches", + "description": "Events defines if events should get synced from the host cluster to the virtual cluster, but not back." + }, + "ingressClasses": { + "$ref": "#/$defs/EnableSwitchWithPatches", + "description": "IngressClasses defines if ingress classes should get synced from the host cluster to the virtual cluster, but not back." + }, + "runtimeClasses": { + "$ref": "#/$defs/EnableSwitchWithPatches", + "description": "RuntimeClasses defines if runtime classes should get synced from the host cluster to the virtual cluster, but not back." + }, + "priorityClasses": { + "$ref": "#/$defs/EnableSwitchWithPatches", + "description": "PriorityClasses defines if priority classes classes should get synced from the host cluster to the virtual cluster, but not back." + }, + "storageClasses": { + "$ref": "#/$defs/EnableAutoSwitchWithPatches", + "description": "StorageClasses defines if storage classes should get synced from the host cluster to the virtual cluster, but not back. If auto, is automatically enabled when the virtual scheduler is enabled." + }, + "csiNodes": { + "$ref": "#/$defs/EnableAutoSwitchWithPatches", + "description": "CSINodes defines if csi nodes should get synced from the host cluster to the virtual cluster, but not back. If auto, is automatically enabled when the virtual scheduler is enabled." + }, + "csiDrivers": { + "$ref": "#/$defs/EnableAutoSwitchWithPatches", + "description": "CSIDrivers defines if csi drivers should get synced from the host cluster to the virtual cluster, but not back. If auto, is automatically enabled when the virtual scheduler is enabled." + }, + "csiStorageCapacities": { + "$ref": "#/$defs/EnableAutoSwitchWithPatches", + "description": "CSIStorageCapacities defines if csi storage capacities should get synced from the host cluster to the virtual cluster, but not back. If auto, is automatically enabled when the virtual scheduler is enabled." + }, + "customResources": { + "additionalProperties": { + "$ref": "#/$defs/SyncFromHostCustomResource" + }, + "type": "object", + "description": "CustomResources defines what custom resources should get synced read-only to the virtual cluster from the host cluster. vCluster will automatically add any required RBAC to the vCluster cluster role." + }, + "volumeSnapshotClasses": { + "$ref": "#/$defs/EnableSwitchWithPatches", + "description": "VolumeSnapshotClasses defines if volume snapshot classes created within the virtual cluster should get synced to the host cluster." + } + }, + "additionalProperties": false, + "type": "object" + }, + "SyncFromHostCustomResource": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled defines if this option should be enabled." + }, + "scope": { + "type": "string", + "description": "Scope defines the scope of the resource" + }, + "patches": { + "items": { + "$ref": "#/$defs/TranslatePatch" + }, + "type": "array", + "description": "Patches patch the resource according to the provided specification." + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "enabled", + "scope" + ] + }, + "SyncNodeSelector": { + "properties": { + "all": { + "type": "boolean", + "description": "All specifies if all nodes should get synced by vCluster from the host to the virtual cluster or only the ones where pods are assigned to." + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "Labels are the node labels used to sync nodes from host cluster to virtual cluster. This will also set the node selector when syncing a pod from virtual cluster to host cluster to the same value." + } + }, + "additionalProperties": false, + "type": "object" + }, + "SyncNodes": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled specifies if syncing real nodes should be enabled. If this is disabled, vCluster will create fake nodes instead." + }, + "syncBackChanges": { + "type": "boolean", + "description": "SyncBackChanges enables syncing labels and taints from the virtual cluster to the host cluster. If this is enabled someone within the virtual cluster will be able to change the labels and taints of the host cluster node." + }, + "clearImageStatus": { + "type": "boolean", + "description": "ClearImageStatus will erase the image status when syncing a node. This allows to hide images that are pulled by the node." + }, + "selector": { + "$ref": "#/$defs/SyncNodeSelector", + "description": "Selector can be used to define more granular what nodes should get synced from the host cluster to the virtual cluster." + }, + "patches": { + "items": { + "$ref": "#/$defs/TranslatePatch" + }, + "type": "array", + "description": "Patches patch the resource according to the provided specification." + } + }, + "additionalProperties": false, + "type": "object" + }, + "SyncPods": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled defines if pod syncing should be enabled." + }, + "translateImage": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "TranslateImage maps an image to another image that should be used instead. For example this can be used to rewrite\na certain image that is used within the virtual cluster to be another image on the host cluster" + }, + "enforceTolerations": { + "items": { + "type": "string" + }, + "type": "array", + "description": "EnforceTolerations will add the specified tolerations to all pods synced by the virtual cluster." + }, + "useSecretsForSATokens": { + "type": "boolean", + "description": "UseSecretsForSATokens will use secrets to save the generated service account tokens by virtual cluster instead of using a\npod annotation." + }, + "rewriteHosts": { + "$ref": "#/$defs/SyncRewriteHosts", + "description": "RewriteHosts is a special option needed to rewrite statefulset containers to allow the correct FQDN. virtual cluster will add\na small container to each stateful set pod that will initially rewrite the /etc/hosts file to match the FQDN expected by\nthe virtual cluster." + }, + "patches": { + "items": { + "$ref": "#/$defs/TranslatePatch" + }, + "type": "array", + "description": "Patches patch the resource according to the provided specification." + } + }, + "additionalProperties": false, + "type": "object" + }, + "SyncRewriteHosts": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled specifies if rewriting stateful set pods should be enabled." + }, + "initContainer": { + "$ref": "#/$defs/SyncRewriteHostsInitContainer", + "description": "InitContainer holds extra options for the init container used by vCluster to rewrite the FQDN for stateful set pods." + } + }, + "additionalProperties": false, + "type": "object" + }, + "SyncRewriteHostsInitContainer": { + "properties": { + "image": { + "type": "string", + "description": "Image is the image virtual cluster should use to rewrite this FQDN." + }, + "resources": { + "$ref": "#/$defs/Resources", + "description": "Resources are the resources that should be assigned to the init container for each stateful set init container." + } + }, + "additionalProperties": false, + "type": "object" + }, + "SyncToHost": { + "properties": { + "pods": { + "$ref": "#/$defs/SyncPods", + "description": "Pods defines if pods created within the virtual cluster should get synced to the host cluster." + }, + "secrets": { + "$ref": "#/$defs/SyncAllResource", + "description": "Secrets defines if secrets created within the virtual cluster should get synced to the host cluster." + }, + "configMaps": { + "$ref": "#/$defs/SyncAllResource", + "description": "ConfigMaps defines if config maps created within the virtual cluster should get synced to the host cluster." + }, + "ingresses": { + "$ref": "#/$defs/EnableSwitchWithPatches", + "description": "Ingresses defines if ingresses created within the virtual cluster should get synced to the host cluster." + }, + "services": { + "$ref": "#/$defs/EnableSwitchWithPatches", + "description": "Services defines if services created within the virtual cluster should get synced to the host cluster." + }, + "endpoints": { + "$ref": "#/$defs/EnableSwitchWithPatches", + "description": "Endpoints defines if endpoints created within the virtual cluster should get synced to the host cluster." + }, + "networkPolicies": { + "$ref": "#/$defs/EnableSwitchWithPatches", + "description": "NetworkPolicies defines if network policies created within the virtual cluster should get synced to the host cluster." + }, + "persistentVolumeClaims": { + "$ref": "#/$defs/EnableSwitchWithPatches", + "description": "PersistentVolumeClaims defines if persistent volume claims created within the virtual cluster should get synced to the host cluster." + }, + "persistentVolumes": { + "$ref": "#/$defs/EnableSwitchWithPatches", + "description": "PersistentVolumes defines if persistent volumes created within the virtual cluster should get synced to the host cluster." + }, + "volumeSnapshots": { + "$ref": "#/$defs/EnableSwitchWithPatches", + "description": "VolumeSnapshots defines if volume snapshots created within the virtual cluster should get synced to the host cluster." + }, + "volumeSnapshotContents": { + "$ref": "#/$defs/EnableSwitchWithPatches", + "description": "VolumeSnapshotContents defines if volume snapshot contents created within the virtual cluster should get synced to the host cluster." + }, + "storageClasses": { + "$ref": "#/$defs/EnableSwitchWithPatches", + "description": "StorageClasses defines if storage classes created within the virtual cluster should get synced to the host cluster." + }, + "serviceAccounts": { + "$ref": "#/$defs/EnableSwitchWithPatches", + "description": "ServiceAccounts defines if service accounts created within the virtual cluster should get synced to the host cluster." + }, + "podDisruptionBudgets": { + "$ref": "#/$defs/EnableSwitchWithPatches", + "description": "PodDisruptionBudgets defines if pod disruption budgets created within the virtual cluster should get synced to the host cluster." + }, + "priorityClasses": { + "$ref": "#/$defs/EnableSwitchWithPatches", + "description": "PriorityClasses defines if priority classes created within the virtual cluster should get synced to the host cluster." + }, + "customResources": { + "additionalProperties": { + "$ref": "#/$defs/SyncToHostCustomResource" + }, + "type": "object", + "description": "CustomResources defines what custom resources should get synced from the virtual cluster to the host cluster. vCluster will copy the definition automatically from host cluster to virtual cluster on startup.\nvCluster will also automatically add any required RBAC permissions to the vCluster role for this to work." + } + }, + "additionalProperties": false, + "type": "object" + }, + "SyncToHostCustomResource": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled defines if this option should be enabled." + }, + "scope": { + "type": "string", + "description": "Scope defines the scope of the resource. If undefined, will use Namespaced. Currently only Namespaced is supported." + }, + "patches": { + "items": { + "$ref": "#/$defs/TranslatePatch" + }, + "type": "array", + "description": "Patches patch the resource according to the provided specification." + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "enabled" + ] + }, + "Telemetry": { + "properties": { + "enabled": { + "type": "boolean", + "description": "Enabled specifies that the telemetry for the vCluster control plane should be enabled." + }, + "instanceCreator": { + "type": "string" + }, + "machineID": { + "type": "string" + }, + "platformUserID": { + "type": "string" + }, + "platformInstanceID": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "TranslatePatch": { + "properties": { + "path": { + "type": "string", + "description": "Path is the path within the patch to target. If the path is not found within the patch, the patch is not applied." + }, + "expression": { + "type": "string", + "description": "Expression transforms the value according to the given JavaScript expression." + }, + "reverseExpression": { + "type": "string", + "description": "ReverseExpression transforms the value according to the given JavaScript expression." + }, + "reference": { + "$ref": "#/$defs/TranslatePatchReference", + "description": "Reference treats the path value as a reference to another object and will rewrite it based on the chosen mode\nautomatically. In single-namespace mode this will translate the name to \"vxxxxxxxxx\" to avoid conflicts with\nother names, in multi-namespace mode this will not translate the name." + }, + "labels": { + "$ref": "#/$defs/TranslatePatchLabels", + "description": "Labels treats the path value as a labels selector." + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "path" + ] + }, + "TranslatePatchLabels": { + "properties": {}, + "additionalProperties": false, + "type": "object" + }, + "TranslatePatchReference": { + "properties": { + "apiVersion": { + "type": "string", + "description": "APIVersion is the apiVersion of the referenced object." + }, + "apiVersionPath": { + "type": "string", + "description": "APIVersionPath is optional relative path to use to determine the kind. If APIVersionPath is not found, will fallback to apiVersion." + }, + "kind": { + "type": "string", + "description": "Kind is the kind of the referenced object." + }, + "kindPath": { + "type": "string", + "description": "KindPath is the optional relative path to use to determine the kind. If KindPath is not found, will fallback to kind." + }, + "namePath": { + "type": "string", + "description": "NamePath is the optional relative path to the reference name within the object." + }, + "namespacePath": { + "type": "string", + "description": "NamespacePath is the optional relative path to the reference namespace within the object. If omitted or not found, namespacePath equals to the\nmetadata.namespace path of the object." + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "apiVersion", + "kind" + ] + }, + "ValidatingWebhook": { + "properties": { + "name": { + "type": "string", + "description": "The name of the admission webhook.\nName should be fully qualified, e.g., imagepolicy.kubernetes.io, where\n\"imagepolicy\" is the name of the webhook, and kubernetes.io is the name\nof the organization." + }, + "clientConfig": { + "$ref": "#/$defs/ValidatingWebhookClientConfig", + "description": "ClientConfig defines how to communicate with the hook." + }, + "rules": { + "items": true, + "type": "array", + "description": "Rules describes what operations on what resources/subresources the webhook cares about.\nThe webhook cares about an operation if it matches _any_ Rule." + }, + "failurePolicy": { + "type": "string", + "description": "FailurePolicy defines how unrecognized errors from the admission endpoint are handled -\nallowed values are Ignore or Fail. Defaults to Fail." + }, + "matchPolicy": { + "type": "string", + "description": "matchPolicy defines how the \"rules\" list is used to match incoming requests.\nAllowed values are \"Exact\" or \"Equivalent\"." + }, + "namespaceSelector": { + "description": "NamespaceSelector decides whether to run the webhook on an object based\non whether the namespace for that object matches the selector. If the\nobject itself is a namespace, the matching is performed on\nobject.metadata.labels. If the object is another cluster scoped resource,\nit never skips the webhook." + }, + "objectSelector": { + "description": "ObjectSelector decides whether to run the webhook based on if the\nobject has matching labels. objectSelector is evaluated against both\nthe oldObject and newObject that would be sent to the webhook, and\nis considered to match if either object matches the selector." + }, + "sideEffects": { + "type": "string", + "description": "SideEffects states whether this webhook has side effects." + }, + "timeoutSeconds": { + "type": "integer", + "description": "TimeoutSeconds specifies the timeout for this webhook." + }, + "admissionReviewVersions": { + "items": { + "type": "string" + }, + "type": "array", + "description": "AdmissionReviewVersions is an ordered list of preferred `AdmissionReview`\nversions the Webhook expects." + }, + "matchConditions": { + "items": true, + "type": "array", + "description": "MatchConditions is a list of conditions that must be met for a request to be sent to this\nwebhook. Match conditions filter requests that have already been matched by the rules,\nnamespaceSelector, and objectSelector. An empty list of matchConditions matches all requests.\nThere are a maximum of 64 match conditions allowed." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ValidatingWebhookClientConfig": { + "properties": { + "url": { + "type": "string", + "description": "URL gives the location of the webhook, in standard URL form\n(`scheme://host:port/path`). Exactly one of `url` or `service`\nmust be specified." + }, + "service": { + "$ref": "#/$defs/ValidatingWebhookServiceReference", + "description": "Service is a reference to the service for this webhook. Either\n`service` or `url` must be specified.\n\nIf the webhook is running within the cluster, then you should use `service`." + }, + "caBundle": { + "type": "string", + "contentEncoding": "base64", + "description": "CABundle is a PEM encoded CA bundle which will be used to validate the webhook's server certificate.\nIf unspecified, system trust roots on the apiserver are used." + } + }, + "additionalProperties": false, + "type": "object", + "description": "ValidatingWebhookClientConfig contains the information to make a TLS connection with the webhook" + }, + "ValidatingWebhookConfiguration": { + "properties": { + "kind": { + "type": "string", + "description": "Kind is a string value representing the REST resource this object represents.\nServers may infer this from the endpoint the client submits requests to." + }, + "apiVersion": { + "type": "string", + "description": "APIVersion defines the versioned schema of this representation of an object.\nServers should convert recognized schemas to the latest internal value, and\nmay reject unrecognized values." + }, + "metadata": { + "$ref": "#/$defs/ObjectMeta", + "description": "Standard object metadata; More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata." + }, + "webhooks": { + "items": { + "$ref": "#/$defs/ValidatingWebhook" + }, + "type": "array", + "description": "Webhooks is a list of webhooks and the affected resources and operations." + } + }, + "additionalProperties": false, + "type": "object" + }, + "ValidatingWebhookServiceReference": { + "properties": { + "namespace": { + "type": "string", + "description": "Namespace is the namespace of the service." + }, + "name": { + "type": "string", + "description": "Name is the name of the service." + }, + "path": { + "type": "string", + "description": "Path is an optional URL path which will be sent in any request to\nthis service." + }, + "port": { + "type": "integer", + "description": "If specified, the port on the service that hosting webhook.\nDefault to 443 for backward compatibility.\n`port` should be a valid port number (1-65535, inclusive)." + } + }, + "additionalProperties": false, + "type": "object" + }, + "VirtualClusterKubeConfig": { + "properties": { + "kubeConfig": { + "type": "string", + "description": "KubeConfig is the virtual cluster kubeconfig path." + }, + "serverCAKey": { + "type": "string", + "description": "ServerCAKey is the server ca key path." + }, + "serverCACert": { + "type": "string", + "description": "ServerCAKey is the server ca cert path." + }, + "clientCACert": { + "type": "string", + "description": "ServerCAKey is the client ca cert path." + }, + "requestHeaderCACert": { + "type": "string", + "description": "RequestHeaderCACert is the request header ca cert path." + } + }, + "additionalProperties": false, + "type": "object" + }, + "VolumeClaim": { + "properties": { + "enabled": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "boolean" + } + ], + "description": "Enabled enables deploying a persistent volume claim. If auto, vCluster will automatically determine\nbased on the chosen distro and other options if this is required." + }, + "accessModes": { + "items": { + "type": "string" + }, + "type": "array", + "description": "AccessModes are the persistent volume claim access modes." + }, + "retentionPolicy": { + "type": "string", + "description": "RetentionPolicy is the persistent volume claim retention policy." + }, + "size": { + "type": "string", + "description": "Size is the persistent volume claim storage size." + }, + "storageClass": { + "type": "string", + "description": "StorageClass is the persistent volume claim storage class." + } + }, + "additionalProperties": false, + "type": "object" + }, + "VolumeMount": { + "properties": { + "name": { + "type": "string", + "description": "This must match the Name of a Volume." + }, + "readOnly": { + "type": "boolean", + "description": "Mounted read-only if true, read-write otherwise (false or unspecified).\nDefaults to false." + }, + "mountPath": { + "type": "string", + "description": "Path within the container at which the volume should be mounted. Must\nnot contain ':'." + }, + "subPath": { + "type": "string", + "description": "Path within the volume from which the container's volume should be mounted.\nDefaults to \"\" (volume's root)." + }, + "mountPropagation": { + "type": "string", + "description": "mountPropagation determines how mounts are propagated from the host\nto container and the other way around.\nWhen not set, MountPropagationNone is used.\nThis field is beta in 1.10." + }, + "subPathExpr": { + "type": "string", + "description": "Expanded path within the volume from which the container's volume should be mounted.\nBehaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment.\nDefaults to \"\" (volume's root).\nSubPathExpr and SubPath are mutually exclusive." + } + }, + "additionalProperties": false, + "type": "object", + "description": "VolumeMount describes a mounting of a Volume within a container." + } + }, + "properties": { + "global": { + "description": "Global values shared across all (sub)charts" + }, + "exportKubeConfig": { + "$ref": "#/$defs/ExportKubeConfig", + "description": "ExportKubeConfig describes how vCluster should export the vCluster kubeConfig file." + }, + "sync": { + "$ref": "#/$defs/Sync", + "description": "Sync describes how to sync resources from the virtual cluster to host cluster and back." + }, + "integrations": { + "$ref": "#/$defs/Integrations", + "description": "Integrations holds config for vCluster integrations with other operators or tools running on the host cluster" + }, + "networking": { + "$ref": "#/$defs/Networking", + "description": "Networking options related to the virtual cluster." + }, + "policies": { + "$ref": "#/$defs/Policies", + "description": "Policies to enforce for the virtual cluster deployment as well as within the virtual cluster." + }, + "controlPlane": { + "$ref": "#/$defs/ControlPlane", + "description": "Configure vCluster's control plane components and deployment." + }, + "rbac": { + "$ref": "#/$defs/RBAC", + "description": "RBAC options for the virtual cluster." + }, + "plugins": { + "anyOf": [ + { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + { + "type": "object" + }, + { + "type": "object" + } + ], + "additionalProperties": { + "$ref": "#/$defs/Plugins" + }, + "description": "Define which vCluster plugins to load." + }, + "experimental": { + "$ref": "#/$defs/Experimental", + "description": "Experimental features for vCluster. Configuration here might change, so be careful with this." + }, + "external": { + "$ref": "#/$defs/ExternalConfig", + "description": "External holds configuration for tools that are external to the vCluster." + }, + "telemetry": { + "$ref": "#/$defs/Telemetry", + "description": "Configuration related to telemetry gathered about vCluster usage." + }, + "serviceCIDR": { + "type": "string", + "description": "ServiceCIDR holds the service cidr for the virtual cluster. Do not use this option anymore." + }, + "pro": { + "type": "boolean", + "description": "Specifies whether to use vCluster Pro. This is automatically inferred in newer versions. Do not use that option anymore." + }, + "plugin": { + "anyOf": [ + { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + { + "type": "object" + }, + { + "type": "object" + } + ], + "additionalProperties": { + "$ref": "#/$defs/Plugin" + }, + "description": "Plugin specifies which vCluster plugins to enable. Use \"plugins\" instead. Do not use this option anymore." + } + }, + "additionalProperties": false, + "type": "object", + "description": "Config is the vCluster config." +} \ No newline at end of file diff --git a/backing-services/vcluster/values.yaml b/backing-services/vcluster/values.yaml new file mode 100644 index 0000000..f33ba88 --- /dev/null +++ b/backing-services/vcluster/values.yaml @@ -0,0 +1,963 @@ +# Sync describes how to sync resources from the virtual cluster to host cluster and back. +sync: + # Configure resources to sync from the virtual cluster to the host cluster. + toHost: + # Services defines if services created within the virtual cluster should get synced to the host cluster. + services: + # Enabled defines if this option should be enabled. + enabled: true + # Endpoints defines if endpoints created within the virtual cluster should get synced to the host cluster. + endpoints: + # Enabled defines if this option should be enabled. + enabled: true + # PersistentVolumeClaims defines if persistent volume claims created within the virtual cluster should get synced to the host cluster. + persistentVolumeClaims: + # Enabled defines if this option should be enabled. + enabled: true + # ConfigMaps defines if config maps created within the virtual cluster should get synced to the host cluster. + configMaps: + enabled: true + # All defines if all resources of that type should get synced or only the necessary ones that are needed. + all: false + # Secrets defines if secrets created within the virtual cluster should get synced to the host cluster. + secrets: + enabled: true + # All defines if all resources of that type should get synced or only the necessary ones that are needed. + all: false + # Pods defines if pods created within the virtual cluster should get synced to the host cluster. + pods: + # Enabled defines if pod syncing should be enabled. + enabled: true + # TranslateImage maps an image to another image that should be used instead. For example this can be used to rewrite + # a certain image that is used within the virtual cluster to be another image on the host cluster + translateImage: {} + # EnforceTolerations will add the specified tolerations to all pods synced by the virtual cluster. + enforceTolerations: [] + # UseSecretsForSATokens will use secrets to save the generated service account tokens by virtual cluster instead of using a + # pod annotation. + useSecretsForSATokens: false + # RewriteHosts is a special option needed to rewrite statefulset containers to allow the correct FQDN. virtual cluster will add + # a small container to each stateful set pod that will initially rewrite the /etc/hosts file to match the FQDN expected by + # the virtual cluster. + rewriteHosts: + # Enabled specifies if rewriting stateful set pods should be enabled. + enabled: true + # InitContainer holds extra options for the init container used by vCluster to rewrite the FQDN for stateful set pods. + initContainer: + # Image is the image virtual cluster should use to rewrite this FQDN. + image: "library/alpine:3.20" + # Resources are the resources that should be assigned to the init container for each stateful set init container. + resources: + # Limits are resource limits for the container + limits: + cpu: 30m + memory: 64Mi + # Requests are minimal resources that will be consumed by the container + requests: + cpu: 30m + memory: 64Mi + # Ingresses defines if ingresses created within the virtual cluster should get synced to the host cluster. + ingresses: + # Enabled defines if this option should be enabled. + enabled: false + # PriorityClasses defines if priority classes created within the virtual cluster should get synced to the host cluster. + priorityClasses: + # Enabled defines if this option should be enabled. + enabled: false + # NetworkPolicies defines if network policies created within the virtual cluster should get synced to the host cluster. + networkPolicies: + # Enabled defines if this option should be enabled. + enabled: false + # VolumeSnapshots defines if volume snapshots created within the virtual cluster should get synced to the host cluster. + volumeSnapshots: + # Enabled defines if this option should be enabled. + enabled: false + # VolumeSnapshotContents defines if volume snapshot contents created within the virtual cluster should get synced to the host cluster. + volumeSnapshotContents: + # Enabled defines if this option should be enabled. + enabled: false + # PodDisruptionBudgets defines if pod disruption budgets created within the virtual cluster should get synced to the host cluster. + podDisruptionBudgets: + # Enabled defines if this option should be enabled. + enabled: false + # ServiceAccounts defines if service accounts created within the virtual cluster should get synced to the host cluster. + serviceAccounts: + # Enabled defines if this option should be enabled. + enabled: false + # StorageClasses defines if storage classes created within the virtual cluster should get synced to the host cluster. + storageClasses: + # Enabled defines if this option should be enabled. + enabled: false + # PersistentVolumes defines if persistent volumes created within the virtual cluster should get synced to the host cluster. + persistentVolumes: + # Enabled defines if this option should be enabled. + enabled: false + + # Configure what resources vCluster should sync from the host cluster to the virtual cluster. + fromHost: + # Events defines if events should get synced from the host cluster to the virtual cluster, but not back. + events: + # Enabled defines if this option should be enabled. + enabled: true + # CSIDrivers defines if csi drivers should get synced from the host cluster to the virtual cluster, but not back. If auto, is automatically enabled when the virtual scheduler is enabled. + csiDrivers: + # Enabled defines if this option should be enabled. + enabled: auto + # CSINodes defines if csi nodes should get synced from the host cluster to the virtual cluster, but not back. If auto, is automatically enabled when the virtual scheduler is enabled. + csiNodes: + # Enabled defines if this option should be enabled. + enabled: auto + # CSIStorageCapacities defines if csi storage capacities should get synced from the host cluster to the virtual cluster, but not back. If auto, is automatically enabled when the virtual scheduler is enabled. + csiStorageCapacities: + # Enabled defines if this option should be enabled. + enabled: auto + # StorageClasses defines if storage classes should get synced from the host cluster to the virtual cluster, but not back. If auto, is automatically enabled when the virtual scheduler is enabled. + storageClasses: + # Enabled defines if this option should be enabled. + enabled: auto + # IngressClasses defines if ingress classes should get synced from the host cluster to the virtual cluster, but not back. + ingressClasses: + # Enabled defines if this option should be enabled. + enabled: false + # RuntimeClasses defines if runtime classes should get synced from the host cluster to the virtual cluster, but not back. + runtimeClasses: + # Enabled defines if this option should be enabled. + enabled: false + # PriorityClasses defines if priority classes classes should get synced from the host cluster to the virtual cluster, but not back. + priorityClasses: + # Enabled defines if this option should be enabled. + enabled: false + # Nodes defines if nodes should get synced from the host cluster to the virtual cluster, but not back. + nodes: + # Enabled specifies if syncing real nodes should be enabled. If this is disabled, vCluster will create fake nodes instead. + enabled: false + # SyncBackChanges enables syncing labels and taints from the virtual cluster to the host cluster. If this is enabled someone within the virtual cluster will be able to change the labels and taints of the host cluster node. + syncBackChanges: false + # ClearImageStatus will erase the image status when syncing a node. This allows to hide images that are pulled by the node. + clearImageStatus: false + # Selector can be used to define more granular what nodes should get synced from the host cluster to the virtual cluster. + selector: + # All specifies if all nodes should get synced by vCluster from the host to the virtual cluster or only the ones where pods are assigned to. + all: false + labels: {} + # VolumeSnapshotClasses defines if volume snapshot classes created within the virtual cluster should get synced to the host cluster. + volumeSnapshotClasses: + # Enabled defines if this option should be enabled. + enabled: false + +# Configure vCluster's control plane components and deployment. +controlPlane: + # Distro holds virtual cluster related distro options. A distro cannot be changed after vCluster is deployed. + distro: + # K8S holds K8s relevant configuration. + k8s: + # Enabled specifies if the K8s distro should be enabled. Only one distro can be enabled at the same time. + enabled: false + # Version specifies k8s components (scheduler, kube-controller-manager & apiserver) version. + # It is a shortcut for controlPlane.distro.k8s.apiServer.image.tag, + # controlPlane.distro.k8s.controllerManager.image.tag and + # controlPlane.distro.k8s.scheduler.image.tag + # If e.g. controlPlane.distro.k8s.version is set to v1.30.1 and + # controlPlane.distro.k8s.scheduler.image.tag + # (or controlPlane.distro.k8s.controllerManager.image.tag or controlPlane.distro.k8s.apiServer.image.tag) + # is set to v1.31.0, + # value from controlPlane.distro.k8s..image.tag will be used + # (where = 1.19 + set: + ingress.enabled: true + capabilities: + majorVersion: 1 + minorVersion: 19 + asserts: + - hasDocuments: + count: 1 + - isKind: + of: Ingress + - isAPIVersion: + of: networking.k8s.io/v1 + - it: should have an ingressClassName for k8s >= 1.19 + set: + ingress.enabled: true + ingress.className: nginx-test + capabilities: + majorVersion: 1 + minorVersion: 19 + asserts: + - hasDocuments: + count: 1 + - equal: + path: spec.ingressClassName + value: nginx-test + - it: should match snapshot of default values + set: + ingress.enabled: true + ingress.className: nginx-test + ingress.annotations: + kubernetes.io/ingress.class: nginx + kubernetes.io/tls-acme: "true" + ingress.tls: + - secretName: chart-example-tls + hosts: + - chart-example.local + asserts: + - matchSnapshot: { } diff --git a/backing-services/zot/unittests/secret_checksum_test.yaml b/backing-services/zot/unittests/secret_checksum_test.yaml new file mode 100644 index 0000000..578a373 --- /dev/null +++ b/backing-services/zot/unittests/secret_checksum_test.yaml @@ -0,0 +1,25 @@ +suite: secret checksum in deployment +# Can't use global templates in this test suite as it will break the checksum calculation +# causing false negative test outcome. +# templates: +# - deployment.yaml +tests: + - it: has no checksum/secret if no config + template: deployment.yaml + asserts: + - isNull: + path: spec.template.metadata.annotations.checksum/secret + - it: generate checksum/secret if config is present + template: deployment.yaml + set: + mountSecret: true + secretFiles: + htpasswd: |- + admin:$2y$05$vmiurPmJvHylk78HHFWuruFFVePlit9rZWGA/FbZfTEmNRneGJtha + user:$2y$05$L86zqQDfH5y445dcMlwu6uHv.oXFgT6AiJCwpv3ehr7idc0rI3S2G + asserts: + - isNotNull: + path: spec.template.metadata.annotations.checksum/secret + - matchRegex: + path: spec.template.metadata.annotations.checksum/secret + pattern: "^[a-f0-9]{64}$" # SHA256 hex output diff --git a/backing-services/zot/values.yaml b/backing-services/zot/values.yaml new file mode 100644 index 0000000..8257619 --- /dev/null +++ b/backing-services/zot/values.yaml @@ -0,0 +1,201 @@ +# Default values for zot. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +replicaCount: 1 +image: + repository: ghcr.io/project-zot/zot-linux-amd64 + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "v2.1.2" +# Defaults to the release namespace if not specified +namespace: "" +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" +service: + type: NodePort + port: 5000 + nodePort: null # Set to a specific port if type is NodePort + # Annotations to add to the service + annotations: {} + # Set to a static IP if a static IP is desired, only works when + # type: ClusterIP + clusterIP: null +# Enabling this will publicly expose your zot server +# Only enable this if you have security enabled on your cluster +ingress: + enabled: false + annotations: {} + kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + # If using nginx, disable body limits and increase read and write timeouts + # nginx.ingress.kubernetes.io/proxy-body-size: "0" + # nginx.ingress.kubernetes.io/proxy-read-timeout: "600" + # nginx.ingress.kubernetes.io/proxy-send-timeout: "600" + className: "nginx" + pathtype: ImplementationSpecific + hosts: + - host: reg.tavanasys.app + paths: + - path: / + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local +# By default, Kubernetes HTTP probes use HTTP 'scheme'. So if TLS is enabled +# in configuration, to prevent failures, the scheme must be set to 'HTTPS'. +httpGet: + scheme: HTTP +# By default, Kubernetes considers a Pod healthy if the liveness probe returns +# successfully. However, sometimes applications need additional startup time on +# their first initialization. By defining a startupProbe, we can allow the +# application to take extra time for initialization without compromising fast +# response to deadlocks. +startupProbe: + initialDelaySeconds: 5 + periodSeconds: 10 + failureThreshold: 3 +# If mountConfig is true the configMap named $CHART_RELEASE-config is mounted +# on the pod's '/etc/zot' directory +mountConfig: false +# If mountConfig is true the chart creates the '$CHART_RELEASE-config', if it +# does not exist the user is in charge of managing it (as this file includes a +# sample file you have to add it empty to handle it externally). +configFiles: + config.json: |- + { + "storage": { "rootDirectory": "/var/lib/registry" }, + "http": { "address": "0.0.0.0", "port": "5000" }, + "log": { "level": "debug" } + } +# Alternatively, the configuration can include authentication and acessControl +# data and we can use mountSecret option for the passwords. +# +# config.json: |- +# { +# "storage": { "rootDirectory": "/var/lib/registry" }, +# "http": { +# "address": "0.0.0.0", +# "port": "5000", +# "auth": { "htpasswd": { "path": "/secret/htpasswd" } }, +# "accessControl": { +# "repositories": { +# "**": { +# "policies": [{ +# "users": ["user"], +# "actions": ["read"] +# }], +# "defaultPolicy": [] +# } +# }, +# "adminPolicy": { +# "users": ["admin"], +# "actions": ["read", "create", "update", "delete"] +# } +# } +# }, +# "log": { "level": "debug" } +# } + +# externalSecrets allows to mount external (meaning not managed by this chart) +# Kubernetes secrets within the Zot container. +# The secret is identified by its name (property "secretName") and should be +# present in the same namespace. The property "mountPath" specifies the path +# within the container filesystem where the secret is mounted. +# +# Below is an example: +# +# externalSecrets: +# - secretName: "secret1" +# mountPath: "/secrets/s1" +# - secretName: "secret2" +# mountPath: "/secrets/s2" +externalSecrets: [] +# If mountSecret is true, the Secret named $CHART_RELEASE-secret is mounted on +# the pod's '/secret' directory (it is used to keep files with passwords, like +# a `htpasswd` file) +mountSecret: false +# If secretFiles does not exist the user is in charge of managing it, again, if +# you want to manage it the value has to be added empty to avoid using this one +secretFiles: + # Example htpasswd with 'admin:admin' & 'user:user' user:pass pairs + htpasswd: |- + admin:$2y$05$vmiurPmJvHylk78HHFWuruFFVePlit9rZWGA/FbZfTEmNRneGJtha + user:$2y$05$L86zqQDfH5y445dcMlwu6uHv.oXFgT6AiJCwpv3ehr7idc0rI3S2G +# Authentication string for Kubernetes probes, which is needed when `htpasswd` +# authentication is enabled, but the anonymous access policy is not. +# It contains a `user:password` string encoded in base64. The example value is +# from running `echo -n "foo:var" | base64` +# authHeader: "Zm9vOmJhcg==" + +# If persistence is 'true' the service uses a persistentVolumeClaim to mount a +# volume for zot on '/var/lib/registry'; by default the pvc used is named +# '$CHART_RELEASE-pvc', but the name can be changed below +persistence: false +# PVC data, only used if persistence is 'true' +pvc: + # Make the chart create the PVC, this option is used with storageClasses that + # can create volumes dynamically, if that is not the case is better to do it + # manually and set create to false + create: false + # Name of the PVC to use or create if persistence is enabled, if not set the + # value '$CHART_RELEASE-pvc' is used + name: null + # Volume access mode, if using more than one replica we need + accessMode: "ReadWriteOnce" + # Size of the volume requested + storage: 8Gi + # Name of the storage class to use if it is different than the default one + storageClassName: null +# List of environment variables to set on the container +env: +# - name: "TEST" +# value: "ME" +# - name: SECRET_NAME +# valueFrom: +# secretKeyRef: +# name: mysecret +# key: username + +# Extra Volume Mounts +extraVolumeMounts: [] +# - name: data +# mountPath: /var/lib/registry + +# Extra Volumes +extraVolumes: [] +# - name: data +# emptyDir: {} + +# Deployment strategy type +strategy: + type: RollingUpdate +# rollingUpdate: +# maxUnavailable: 25% + +# Extra args to pass to the deployment's container +extraArgs: [] +podAnnotations: {} +podLabels: {} +deploymentAnnotations: {} +priorityClassName: "" +dnsConfig: {} +dnsPolicy: "ClusterFirst" +# Metrics configuration +# NOTE: need enable metric extension in config.json +metrics: + # Start a prometheus exporter + enabled: false + # Prometheus Operator ServiceMonitor configuration + serviceMonitor: + # Start a ServiceMonitor for Prometheus Operator + enabled: false + # Specify the interval at which metrics should be scraped + interval: "30s" + # Specify the path to scrape metrics from + path: "/metrics"